From 1ea65f0285d7022ce20ef84d4e35e3c94bcb3fbd Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 27 Mar 2012 22:56:02 -0700 Subject: CHUI-51 WIP notifications routig code cleanup phase 1, removal of most of llnotificationhandler --- indra/llui/llnotifications.cpp | 50 +++--- indra/llui/llnotifications.h | 21 +-- indra/llui/llnotificationtemplate.h | 10 +- indra/newview/llbrowsernotification.cpp | 5 +- indra/newview/llchiclet.cpp | 9 +- indra/newview/llfloaternotificationsconsole.cpp | 2 +- indra/newview/llfloateroutbox.cpp | 51 +----- indra/newview/llfloateroutbox.h | 2 +- indra/newview/llimhandler.cpp | 82 +++++----- indra/newview/llnearbychathandler.cpp | 8 +- indra/newview/llnearbychathandler.h | 3 +- indra/newview/llnotificationalerthandler.cpp | 99 +++++------- indra/newview/llnotificationgrouphandler.cpp | 50 +++--- indra/newview/llnotificationhandler.h | 143 ++++++----------- indra/newview/llnotificationhandlerutil.cpp | 126 ++------------- indra/newview/llnotificationhinthandler.cpp | 26 +--- indra/newview/llnotificationmanager.cpp | 90 ++--------- indra/newview/llnotificationmanager.h | 11 +- indra/newview/llnotificationofferhandler.cpp | 172 ++++++++++----------- indra/newview/llnotificationscripthandler.cpp | 89 +++++------ indra/newview/llnotificationtiphandler.cpp | 117 ++++++-------- indra/newview/llscreenchannel.h | 14 +- indra/newview/llsyswellwindow.cpp | 11 +- indra/newview/lltoastgroupnotifypanel.cpp | 2 +- indra/newview/lltoastgroupnotifypanel.h | 2 +- indra/newview/lltoastnotifypanel.cpp | 4 +- indra/newview/lltoastnotifypanel.h | 4 +- indra/newview/llviewermessage.cpp | 2 - indra/newview/llviewerwindow.cpp | 8 +- .../newview/skins/default/xui/en/notifications.xml | 22 +++ 30 files changed, 435 insertions(+), 800 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index d232e27ef2..038a86d20a 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -409,7 +409,9 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par mUnique(p.unique.isProvided()), mPriority(p.priority), mPersist(p.persist), - mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()) + mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()), + mLogToChat(p.log_to_chat), + mLogToIM(p.log_to_im) { if (p.sound.isProvided() && LLUI::sSettingGroups["config"]->controlExists(p.sound)) @@ -886,6 +888,24 @@ std::string LLNotification::getURL() const return (mTemplatep ? url : ""); } +bool LLNotification::canLogToChat() const +{ + return mTemplatep->mLogToChat; +} + +bool LLNotification::canLogToIM() const +{ + return mTemplatep->mLogToIM; +} + +bool LLNotification::hasFormElements() const +{ + return mTemplatep->mForm->getNumElements() != 0; +} + + + + // ========================================================= // LLNotificationChannel implementation // --- @@ -1051,20 +1071,6 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt return abortProcessing; } -/* static */ -LLNotificationChannelPtr LLNotificationChannel::buildChannel(const std::string& name, - const std::string& parent, - LLNotificationFilter filter, - LLNotificationComparator comparator) -{ - // note: this is not a leak; notifications are self-registering. - // This factory helps to prevent excess deletions by making sure all smart - // pointers to notification channels come from the same source - new LLNotificationChannel(name, parent, filter, comparator); - return LLNotifications::instance().getChannel(name); -} - - LLNotificationChannel::LLNotificationChannel(const std::string& name, const std::string& parent, LLNotificationFilter filter, @@ -1272,19 +1278,19 @@ void LLNotifications::createDefaultChannels() { // now construct the various channels AFTER loading the notifications, // because the history channel is going to rewrite the stored notifications file - LLNotificationChannel::buildChannel("Enabled", "", + new LLNotificationChannel("Enabled", "", !boost::bind(&LLNotifications::getIgnoreAllNotifications, this)); - LLNotificationChannel::buildChannel("Expiration", "Enabled", + new LLNotificationChannel("Expiration", "Enabled", boost::bind(&LLNotifications::expirationFilter, this, _1)); - LLNotificationChannel::buildChannel("Unexpired", "Enabled", + new LLNotificationChannel("Unexpired", "Enabled", !boost::bind(&LLNotifications::expirationFilter, this, _1)); // use negated bind - LLNotificationChannel::buildChannel("Unique", "Unexpired", + new LLNotificationChannel("Unique", "Unexpired", boost::bind(&LLNotifications::uniqueFilter, this, _1)); - LLNotificationChannel::buildChannel("Ignore", "Unique", + new LLNotificationChannel("Ignore", "Unique", filterIgnoredNotifications); - LLNotificationChannel::buildChannel("VisibilityRules", "Ignore", + new LLNotificationChannel("VisibilityRules", "Ignore", boost::bind(&LLNotifications::isVisibleByRules, this, _1)); - LLNotificationChannel::buildChannel("Visible", "VisibilityRules", + new LLNotificationChannel("Visible", "VisibilityRules", &LLNotificationFilters::includeEverything); // create special persistent notification channel diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 462d69be2e..f83365a97d 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -513,7 +513,10 @@ public: std::string getURL() const; S32 getURLOption() const; S32 getURLOpenExternally() const; - + bool canLogToChat() const; + bool canLogToIM() const; + bool hasFormElements() const; + const LLNotificationFormPtr getForm(); const LLDate getExpiration() const @@ -791,13 +794,6 @@ typedef boost::shared_ptr<LLNotificationChannel> LLNotificationChannelPtr; // of a queue with notifications being added to different nonequivalent copies. So we // make it inherit from boost::noncopyable, and then create a map of shared_ptr to manage it. // -// NOTE: LLNotificationChannel is self-registering. The *correct* way to create one is to -// do something like: -// LLNotificationChannel::buildChannel("name", "parent"...); -// This returns an LLNotificationChannelPtr, which you can store, or -// you can then retrieve the channel by using the registry: -// LLNotifications::instance().getChannel("name")... -// class LLNotificationChannel : boost::noncopyable, public LLNotificationChannelBase @@ -822,20 +818,13 @@ public: std::string summarize(); - // factory method for constructing these channels; since they're self-registering, - // we want to make sure that you can't use new to make them - static LLNotificationChannelPtr buildChannel(const std::string& name, const std::string& parent, - LLNotificationFilter filter=LLNotificationFilters::includeEverything, - LLNotificationComparator comparator=LLNotificationComparators::orderByUUID()); - -protected: // Notification Channels have a filter, which determines which notifications // will be added to this channel. // Channel filters cannot change. // Channels have a protected constructor so you can't make smart pointers that don't // come from our internal reference; call NotificationChannel::build(args) LLNotificationChannel(const std::string& name, const std::string& parent, - LLNotificationFilter filter, LLNotificationComparator comparator); + LLNotificationFilter filter, LLNotificationComparator comparator=LLNotificationComparators::orderByUUID()); private: std::string mName; diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index fb50c9c123..1df7205b23 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -170,7 +170,9 @@ struct LLNotificationTemplate struct Params : public LLInitParam::Block<Params> { Mandatory<std::string> name; - Optional<bool> persist; + Optional<bool> persist, + log_to_im, + log_to_chat; Optional<std::string> functor, icon, label, @@ -190,6 +192,8 @@ struct LLNotificationTemplate Params() : name("name"), persist("persist", false), + log_to_im("log_to_im", false), + log_to_chat("log_to_chat", false), functor("functor"), icon("icon"), label("label"), @@ -291,6 +295,10 @@ struct LLNotificationTemplate LLUUID mSoundEffect; // List of tags that rules can match against. std::list<std::string> mTags; + + // inject these notifications into chat/IM streams + bool mLogToChat; + bool mLogToIM; }; #endif //LL_LLNOTIFICATION_TEMPLATE_H diff --git a/indra/newview/llbrowsernotification.cpp b/indra/newview/llbrowsernotification.cpp index 6e77d1e336..9e608d2c8b 100644 --- a/indra/newview/llbrowsernotification.cpp +++ b/indra/newview/llbrowsernotification.cpp @@ -35,11 +35,8 @@ using namespace LLNotificationsUI; -bool LLBrowserNotification::processNotification(const LLSD& notify) +bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification) { - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - if (!notification) return false; - LLUUID media_id = notification->getPayload()["media_id"].asUUID(); LLMediaCtrl* media_instance = LLMediaCtrl::getInstance(media_id); if (media_instance) diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index aabab0ccb9..9f19f8dd1c 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -339,9 +339,9 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p) , mUreadSystemNotifications(0) { // connect counter handlers to the signals - connectCounterUpdatersToSignal("notify"); - connectCounterUpdatersToSignal("groupnotify"); - connectCounterUpdatersToSignal("offer"); + connectCounterUpdatersToSignal("Notify"); + connectCounterUpdatersToSignal("Group Notify"); + connectCounterUpdatersToSignal("Offer"); // ensure that notification well window exists, to synchronously // handle toast add/delete events. @@ -350,8 +350,7 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p) void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type) { - LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); - LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); + LLNotificationsUI::LLEventHandler* n_handler = dynamic_cast<LLNotificationsUI::LLEventHandler*>(LLNotifications::instance().getChannel(notification_type).get()); if(n_handler) { n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index 2681d4b34d..90dbabebfb 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -57,7 +57,7 @@ LLNotificationChannelPanel::LLNotificationChannelPanel(const LLNotificationChann { mChannelPtr = LLNotifications::instance().getChannel(p.name); mChannelRejectsPtr = LLNotificationChannelPtr( - LLNotificationChannel::buildChannel(p.name() + "rejects", mChannelPtr->getParentChannelName(), + new LLNotificationChannel(p.name() + "rejects", mChannelPtr->getParentChannelName(), !boost::bind(mChannelPtr->getFilter(), _1))); buildFromFile( "panel_notifications_channel.xml"); } diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index 540f977305..2a2b231b53 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -44,14 +44,12 @@ #include "llviewernetwork.h" #include "llwindowshade.h" -#define USE_WINDOWSHADE_DIALOGS 0 - ///---------------------------------------------------------------------------- /// LLOutboxNotification class ///---------------------------------------------------------------------------- -bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLSD& notify) +bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotificationPtr& notify) { LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance<LLFloaterOutbox>("outbox"); @@ -516,52 +514,11 @@ void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content) updateView(); } -void LLFloaterOutbox::showNotification(const LLSD& notify) +void LLFloaterOutbox::showNotification(const LLNotificationPtr& notification) { - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if (!notification) - { - llerrs << "Unable to find outbox notification!" << notify.asString() << llendl; - - return; - } - -#if USE_WINDOWSHADE_DIALOGS - - if (mWindowShade) - { - delete mWindowShade; - } - - LLRect floater_rect = getLocalRect(); - floater_rect.mTop -= getHeaderHeight(); - floater_rect.stretch(-5, 0); - - LLWindowShade::Params params; - params.name = "notification_shade"; - params.rect = floater_rect; - params.follows.flags = FOLLOWS_ALL; - params.modal = true; - params.can_close = false; - params.shade_color = LLColor4::white % 0.25f; - params.text_color = LLColor4::white; - - mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params); - - addChild(mWindowShade); - mWindowShade->show(notification); - -#else - - LLNotificationsUI::LLEventHandler * handler = - LLNotificationsUI::LLNotificationManager::instance().getHandlerForNotification("alertmodal"); - - LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler *>(handler); + LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler*>(LLNotifications::instance().getChannel("AlertModal").get()); llassert(sys_handler); - sys_handler->processNotification(notify); - -#endif + sys_handler->processNotification(notification); } diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h index 18baccf1c9..a91d8c1139 100644 --- a/indra/newview/llfloateroutbox.h +++ b/indra/newview/llfloateroutbox.h @@ -64,7 +64,7 @@ public: EAcceptance* accept, std::string& tooltip_msg); - void showNotification(const LLSD& notify); + void showNotification(const LLNotificationPtr& notification); BOOL handleHover(S32 x, S32 y, MASK mask); void onMouseLeave(S32 x, S32 y, MASK mask); diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index cd71da7393..a92c4fa387 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -37,10 +37,9 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- -LLIMHandler::LLIMHandler(e_notification_type type, const LLSD& id) +LLIMHandler::LLIMHandler() +: LLSysHandler("IM Notifications", "notifytoast") { - mType = type; - // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel(); } @@ -59,62 +58,51 @@ void LLIMHandler::initChannel() } //-------------------------------------------------------------------------- -bool LLIMHandler::processNotification(const LLSD& notify) +bool LLIMHandler::processNotification(const LLNotificationPtr& notification) { if(!mChannel) { return false; } - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if(!notification) - return false; - // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") - { - LLSD substitutions = notification->getSubstitutions(); - - // According to comments in LLIMMgr::addMessage(), if we get message - // from ourselves, the sender id is set to null. This fixes EXT-875. - LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); - if (avatar_id.isNull()) - avatar_id = gAgentID; - - LLToastIMPanel::Params im_p; - im_p.notification = notification; - im_p.avatar_id = avatar_id; - im_p.from = substitutions["FROM"].asString(); - im_p.time = substitutions["TIME"].asString(); - im_p.message = substitutions["MESSAGE"].asString(); - im_p.session_id = substitutions["SESSION_ID"].asUUID(); - - LLToastIMPanel* im_box = new LLToastIMPanel(im_p); - - LLToast::Params p; - p.notif_id = notification->getID(); - p.session_id = im_p.session_id; - p.notification = notification; - p.panel = im_box; - p.can_be_stored = false; - p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); - if(channel) - channel->addToast(p); - - // send a signal to the counter manager; - mNewNotificationSignal(); - } - else if (notify["sigtype"].asString() == "delete") - { - mChannel->killToastByNotificationID(notification->getID()); - } + LLSD substitutions = notification->getSubstitutions(); + + // According to comments in LLIMMgr::addMessage(), if we get message + // from ourselves, the sender id is set to null. This fixes EXT-875. + LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); + if (avatar_id.isNull()) + avatar_id = gAgentID; + + LLToastIMPanel::Params im_p; + im_p.notification = notification; + im_p.avatar_id = avatar_id; + im_p.from = substitutions["FROM"].asString(); + im_p.time = substitutions["TIME"].asString(); + im_p.message = substitutions["MESSAGE"].asString(); + im_p.session_id = substitutions["SESSION_ID"].asUUID(); + + LLToastIMPanel* im_box = new LLToastIMPanel(im_p); + + LLToast::Params p; + p.notif_id = notification->getID(); + p.session_id = im_p.session_id; + p.notification = notification; + p.panel = im_box; + p.can_be_stored = false; + p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->addToast(p); + + // send a signal to the counter manager; + mNewNotificationSignal(); + return false; } diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 240a7c7a35..269b42bbe9 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -445,10 +445,8 @@ void LLNearbyChatScreenChannel::arrangeToasts() //----------------------------------------------------------------------------------------------- boost::scoped_ptr<LLEventPump> LLNearbyChatHandler::sChatWatcher(new LLEventStream("LLChat")); -LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& id) +LLNearbyChatHandler::LLNearbyChatHandler() { - mType = type; - // Getting a Channel for our notifications LLNearbyChatScreenChannel::Params p; p.id = LLUUID(gSavedSettings.getString("NearByChatChannelUUID")); @@ -614,10 +612,6 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, } } -void LLNearbyChatHandler::onDeleteToast(LLToast* toast) -{ -} - //----------------------------------------------------------------------------------------------- // LLNearbyChatToast diff --git a/indra/newview/llnearbychathandler.h b/indra/newview/llnearbychathandler.h index b0e4f62d51..a5034ac1cb 100644 --- a/indra/newview/llnearbychathandler.h +++ b/indra/newview/llnearbychathandler.h @@ -37,14 +37,13 @@ namespace LLNotificationsUI{ class LLNearbyChatHandler : public LLChatHandler { public: - LLNearbyChatHandler(e_notification_type type,const LLSD& id); + LLNearbyChatHandler(); virtual ~LLNearbyChatHandler(); virtual void processChat(const LLChat& chat_msg, const LLSD &args); protected: - virtual void onDeleteToast(LLToast* toast); virtual void initChannel(); static boost::scoped_ptr<LLEventPump> sChatWatcher; diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index cae7d02fed..e6239534f7 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -40,10 +40,10 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- -LLAlertHandler::LLAlertHandler(e_notification_type type, const LLSD& id) : mIsModal(false) +LLAlertHandler::LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal) +: LLSysHandler(name, notification_type), + mIsModal(is_modal) { - mType = type; - LLScreenChannelBase::Params p; p.id = LLUUID(gSavedSettings.getString("AlertChannelUUID")); p.display_toasts_always = true; @@ -68,79 +68,58 @@ void LLAlertHandler::initChannel() } //-------------------------------------------------------------------------- -bool LLAlertHandler::processNotification(const LLSD& notify) +bool LLAlertHandler::processNotification(const LLNotificationPtr& notification) { if(!mChannel) { return false; } - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if(!notification) - return false; - // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load") + if (notification->canLogToIM() && notification->hasFormElements()) { - if (LLHandlerUtil::canSpawnSessionAndLogToIM(notification)) - { - const std::string name = LLHandlerUtil::getSubstitutionName(notification); - - LLUUID from_id = notification->getPayload()["from_id"]; - - // firstly create session... - LLHandlerUtil::spawnIMSession(name, from_id); - - // ...then log message to have IM Well notified about new message - LLHandlerUtil::logToIMP2P(notification); - } - - LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.panel = dynamic_cast<LLToastPanel*>(alert_dialog); - p.enable_hide_btn = false; - p.can_fade = false; - p.is_modal = mIsModal; - p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); - - // Show alert in middle of progress view (during teleport) (EXT-1093) - LLProgressView* progress = gViewerWindow->getProgressView(); - LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); - mChannel->updatePositionAndSize(rc); - - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); - if(channel) - channel->addToast(p); - } - else if (notify["sigtype"].asString() == "change") - { - LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); - if(channel) - channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); - } - else - { - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); - if(channel) - channel->killToastByNotificationID(notification->getID()); + const std::string name = LLHandlerUtil::getSubstitutionName(notification); + + LLUUID from_id = notification->getPayload()["from_id"]; + + // firstly create session... + LLHandlerUtil::spawnIMSession(name, from_id); + + // ...then log message to have IM Well notified about new message + LLHandlerUtil::logToIMP2P(notification); } + + LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = dynamic_cast<LLToastPanel*>(alert_dialog); + p.enable_hide_btn = false; + p.can_fade = false; + p.is_modal = mIsModal; + p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); + + // Show alert in middle of progress view (during teleport) (EXT-1093) + LLProgressView* progress = gViewerWindow->getProgressView(); + LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); + mChannel->updatePositionAndSize(rc); + + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->addToast(p); + return false; } -//-------------------------------------------------------------------------- - -void LLAlertHandler::onDeleteToast(LLToast* toast) +void LLAlertHandler::onChange( LLNotificationPtr notification ) { + LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); } - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 9b7fdaef82..2ce51fa094 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -37,15 +37,14 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- -LLGroupHandler::LLGroupHandler(e_notification_type type, const LLSD& id) +LLGroupHandler::LLGroupHandler() +: LLSysHandler("Group Notifications", "groupnotify") { - mType = type; - // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel(); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) - channel->setOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1)); + channel->addOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1)); } //-------------------------------------------------------------------------- @@ -62,48 +61,37 @@ void LLGroupHandler::initChannel() } //-------------------------------------------------------------------------- -bool LLGroupHandler::processNotification(const LLSD& notify) +bool LLGroupHandler::processNotification(const LLNotificationPtr& notification) { if(!mChannel) { return false; } - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if(!notification) - return false; - // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") - { - LLHandlerUtil::logGroupNoticeToIMGroup(notification); + LLHandlerUtil::logGroupNoticeToIMGroup(notification); + + LLPanel* notify_box = new LLToastGroupNotifyPanel(notification); + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = notify_box; + p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); - LLPanel* notify_box = new LLToastGroupNotifyPanel(notification); - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.panel = notify_box; - p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->addToast(p); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); - if(channel) - channel->addToast(p); + // send a signal to the counter manager + mNewNotificationSignal(); - // send a signal to the counter manager - mNewNotificationSignal(); + LLGroupActions::refresh_notices(); - LLGroupActions::refresh_notices(); - } - else if (notify["sigtype"].asString() == "delete") - { - mChannel->killToastByNotificationID(notification->getID()); - } return false; } @@ -123,7 +111,7 @@ void LLGroupHandler::onRejectToast(LLUUID& id) { LLNotificationPtr notification = LLNotifications::instance().find(id); - if (notification && LLNotificationManager::getInstance()->getHandlerForNotification(notification->getType()) == this) + if (notification && mItems.find(notification) != mItems.end()) { LLNotifications::instance().cancel(notification); } diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 23dbb6b047..ff9371f7df 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -30,7 +30,7 @@ #include "llwindow.h" -//#include "llnotificationsutil.h" +#include "llnotifications.h" #include "llchannelmanager.h" #include "llchat.h" #include "llinstantmessage.h" @@ -40,20 +40,6 @@ class LLIMFloater; namespace LLNotificationsUI { -// ENotificationType enumerates all possible types of notifications that could be met -// -typedef enum e_notification_type -{ - NT_NOTIFY, - NT_NOTIFYTIP, - NT_GROUPNOTIFY, - NT_IMCHAT, - NT_GROUPCHAT, - NT_NEARBYCHAT, - NT_ALERT, - NT_ALERTMODAL, - NT_OFFER -} ENotificationType; /** * Handler of notification events. @@ -95,7 +81,7 @@ public: boost::signals2::connection setNotificationIDCallback(notification_id_callback_t cb) { return mNotificationIDSignal.connect(cb); } protected: - virtual void onDeleteToast(LLToast* toast)=0; + virtual void onDeleteToast(LLToast* toast) {} // arrange handler's channel on a screen // is necessary to unbind a moment of creation of a channel and a moment of positioning of it @@ -104,8 +90,6 @@ protected: virtual void initChannel()=0; LLScreenChannelBase* mChannel; - e_notification_type mType; - }; // LLSysHandler and LLChatHandler are more specific base classes @@ -115,13 +99,18 @@ protected: /** * Handler for system notifications. */ -class LLSysHandler : public LLEventHandler +class LLSysHandler : public LLEventHandler, public LLNotificationChannel { public: - LLSysHandler(); + LLSysHandler(const std::string& name, const std::string& notification_type); virtual ~LLSysHandler() {}; - virtual bool processNotification(const LLSD& notify)=0; + // base interface functions + /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel) mChannel->killToastByNotificationID(p->getID());} + + virtual bool processNotification(const LLNotificationPtr& notify)=0; protected : static void init(); @@ -149,13 +138,11 @@ public: class LLIMHandler : public LLSysHandler { public: - LLIMHandler(e_notification_type type, const LLSD& id); + LLIMHandler(); virtual ~LLIMHandler(); - // base interface functions - virtual bool processNotification(const LLSD& notify); - protected: + bool processNotification(const LLNotificationPtr& p); virtual void onDeleteToast(LLToast* toast); virtual void initChannel(); }; @@ -167,14 +154,13 @@ protected: class LLTipHandler : public LLSysHandler { public: - LLTipHandler(e_notification_type type, const LLSD& id); + LLTipHandler(); virtual ~LLTipHandler(); // base interface functions - virtual bool processNotification(const LLSD& notify); + virtual bool processNotification(const LLNotificationPtr& p); protected: - virtual void onDeleteToast(LLToast* toast); virtual void onRejectToast(const LLUUID& id); virtual void initChannel(); }; @@ -186,11 +172,12 @@ protected: class LLScriptHandler : public LLSysHandler { public: - LLScriptHandler(e_notification_type type, const LLSD& id); + LLScriptHandler(); virtual ~LLScriptHandler(); + virtual void onDelete(LLNotificationPtr p); // base interface functions - virtual bool processNotification(const LLSD& notify); + virtual bool processNotification(const LLNotificationPtr& p); protected: virtual void onDeleteToast(LLToast* toast); @@ -207,11 +194,11 @@ protected: class LLGroupHandler : public LLSysHandler { public: - LLGroupHandler(e_notification_type type, const LLSD& id); + LLGroupHandler(); virtual ~LLGroupHandler(); // base interface functions - virtual bool processNotification(const LLSD& notify); + virtual bool processNotification(const LLNotificationPtr& p); protected: virtual void onDeleteToast(LLToast* toast); @@ -227,16 +214,16 @@ protected: class LLAlertHandler : public LLSysHandler { public: - LLAlertHandler(e_notification_type type, const LLSD& id); + LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal); virtual ~LLAlertHandler(); - void setAlertMode(bool is_modal) { mIsModal = is_modal; } + /*virtual*/ void onChange(LLNotificationPtr p); + /*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } // base interface functions - virtual bool processNotification(const LLSD& notify); + virtual bool processNotification(const LLNotificationPtr& p); protected: - virtual void onDeleteToast(LLToast* toast); virtual void initChannel(); bool mIsModal; @@ -249,11 +236,12 @@ protected: class LLOfferHandler : public LLSysHandler { public: - LLOfferHandler(e_notification_type type, const LLSD& id); + LLOfferHandler(); virtual ~LLOfferHandler(); // base interface functions - virtual bool processNotification(const LLSD& notify); + /*virtual*/ void onDelete(LLNotificationPtr notification); + virtual bool processNotification(const LLNotificationPtr& p); protected: virtual void onDeleteToast(LLToast* toast); @@ -266,84 +254,54 @@ protected: /** * Handler for UI hints. */ -class LLHintHandler : public LLSingleton<LLHintHandler> +class LLHintHandler : public LLNotificationChannel { public: - LLHintHandler(); - virtual ~LLHintHandler(); + LLHintHandler() : LLNotificationChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint")) + {} + virtual ~LLHintHandler() {} - // base interface functions - virtual bool processNotification(const LLSD& notify); + /*virtual*/ void onAdd(LLNotificationPtr p); + /*virtual*/ void onChange(LLNotificationPtr p); + /*virtual*/ void onDelete(LLNotificationPtr p); }; /** * Handler for browser notifications */ -class LLBrowserNotification : public LLSingleton<LLBrowserNotification> +class LLBrowserNotification : public LLNotificationChannel { public: - virtual bool processNotification(const LLSD& notify); + LLBrowserNotification() + : LLNotificationChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser")) + {} + /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + bool processNotification(const LLNotificationPtr& p); }; /** * Handler for outbox notifications */ -class LLOutboxNotification : public LLSingleton<LLOutboxNotification> +class LLOutboxNotification : public LLNotificationChannel { public: - virtual bool processNotification(const LLSD& notify); + LLOutboxNotification() + : LLNotificationChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")) + {} + /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + bool processNotification(const LLNotificationPtr& p); }; class LLHandlerUtil { public: - /** - * Checks sufficient conditions to log notification message to IM session. - */ - static bool canLogToIM(const LLNotificationPtr& notification); - - /** - * Checks sufficient conditions to log notification message to nearby chat session. - */ - static bool canLogToNearbyChat(const LLNotificationPtr& notification); - - /** - * Checks sufficient conditions to spawn IM session. - */ - static bool canSpawnIMSession(const LLNotificationPtr& notification); - - /** - * Checks sufficient conditions to add notification toast panel IM floater. - */ - static bool canAddNotifPanelToIM(const LLNotificationPtr& notification); - - /** - * Checks whether notification can be used multiple times or not. - */ - static bool isNotificationReusable(const LLNotificationPtr& notification); - - /** - * Checks if passed notification can create IM session and be written into it. - * - * This method uses canLogToIM() & canSpawnIMSession(). - */ - static bool canSpawnSessionAndLogToIM(const LLNotificationPtr& notification); - - /** - * Checks if passed notification can create toast. - */ - static bool canSpawnToast(const LLNotificationPtr& notification); - /** * Determines whether IM floater is opened. */ static bool isIMFloaterOpened(const LLNotificationPtr& notification); - /** - * Determines whether IM floater is focused. - */ - static bool isIMFloaterFocused(const LLNotificationPtr& notification); - /** * Writes notification message to IM session. */ @@ -406,13 +364,6 @@ public: */ static void decIMMesageCounter(const LLNotificationPtr& notification); -private: - - /** - * Find IM floater based on "from_id" - */ - static LLIMFloater* findIMFloater(const LLNotificationPtr& notification); - }; } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 1b767e80d4..dca7fda151 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -54,7 +54,8 @@ void LLSysHandler::init() sExclusiveNotificationGroups.push_back(online_offline_group); } -LLSysHandler::LLSysHandler() +LLSysHandler::LLSysHandler(const std::string& name, const std::string& notification_type) +: LLNotificationChannel(name, "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, notification_type)) { if(sExclusiveNotificationGroups.empty()) { @@ -110,119 +111,9 @@ void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif) } } -const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"), - REVOKED_MODIFY_RIGHTS("RevokedModifyRights"), - OBJECT_GIVE_ITEM("ObjectGiveItem"), - OBJECT_GIVE_ITEM_UNKNOWN_USER("ObjectGiveItemUnknownUser"), - PAYMENT_RECEIVED("PaymentReceived"), - PAYMENT_SENT("PaymentSent"), - ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"), - USER_GIVE_ITEM("UserGiveItem"), - INVENTORY_ACCEPTED("InventoryAccepted"), - INVENTORY_DECLINED("InventoryDeclined"), - OFFER_FRIENDSHIP("OfferFriendship"), - FRIENDSHIP_ACCEPTED("FriendshipAccepted"), - FRIENDSHIP_OFFERED("FriendshipOffered"), - FRIENDSHIP_ACCEPTED_BYME("FriendshipAcceptedByMe"), - FRIENDSHIP_DECLINED_BYME("FriendshipDeclinedByMe"), - FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"), - SERVER_OBJECT_MESSAGE("ServerObjectMessage"), - TELEPORT_OFFERED("TeleportOffered"), - TELEPORT_OFFER_SENT("TeleportOfferSent"), - IM_SYSTEM_MESSAGE_TIP("IMSystemMessageTip"); +const static std::string OBJECT_GIVE_ITEM("ObjectGiveItem"); - -// static -bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) -{ - return GRANTED_MODIFY_RIGHTS == notification->getName() - || REVOKED_MODIFY_RIGHTS == notification->getName() - || PAYMENT_RECEIVED == notification->getName() - || PAYMENT_SENT == notification->getName() - || OFFER_FRIENDSHIP == notification->getName() - || FRIENDSHIP_OFFERED == notification->getName() - || FRIENDSHIP_ACCEPTED == notification->getName() - || FRIENDSHIP_ACCEPTED_BYME == notification->getName() - || FRIENDSHIP_DECLINED_BYME == notification->getName() - || SERVER_OBJECT_MESSAGE == notification->getName() - || INVENTORY_ACCEPTED == notification->getName() - || INVENTORY_DECLINED == notification->getName() - || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName() - || TELEPORT_OFFER_SENT == notification->getName() - || IM_SYSTEM_MESSAGE_TIP == notification->getName(); -} - -// static -bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification) -{ - return notification->getType() == "notifytip" - && FRIEND_ONLINE != notification->getName() - && FRIEND_OFFLINE != notification->getName() - && INVENTORY_ACCEPTED != notification->getName() - && INVENTORY_DECLINED != notification->getName() - && IM_SYSTEM_MESSAGE_TIP != notification->getName(); -} - -// static -bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification) -{ - return OFFER_FRIENDSHIP == notification->getName() - || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); -} - -// static -bool LLHandlerUtil::canAddNotifPanelToIM(const LLNotificationPtr& notification) -{ - return OFFER_FRIENDSHIP == notification->getName() - || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); -} - -// static -bool LLHandlerUtil::isNotificationReusable(const LLNotificationPtr& notification) -{ - return OFFER_FRIENDSHIP == notification->getName() - || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); -} - -// static -bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notification) -{ - return canLogToIM(notification) && canSpawnIMSession(notification); -} - -// static -bool LLHandlerUtil::canSpawnToast(const LLNotificationPtr& notification) -{ - if(INVENTORY_DECLINED == notification->getName() - || INVENTORY_ACCEPTED == notification->getName()) - { - // return false for inventory accepted/declined notifications if respective IM window is open (EXT-5909) - return ! isIMFloaterOpened(notification); - } - - if(FRIENDSHIP_ACCEPTED == notification->getName()) - { - // don't show FRIENDSHIP_ACCEPTED if IM window is opened and focused - EXT-6441 - return ! isIMFloaterFocused(notification); - } - - if(OFFER_FRIENDSHIP == notification->getName() - || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName()) - { - // When ANY offer arrives, show toast, unless IM window is already open - EXT-5904 - return ! isIMFloaterOpened(notification); - } - - return true; -} - -// static -LLIMFloater* LLHandlerUtil::findIMFloater(const LLNotificationPtr& notification) +static LLIMFloater* find_im_floater(const LLNotificationPtr& notification) { LLUUID from_id = notification->getPayload()["from_id"]; LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); @@ -234,7 +125,7 @@ bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) { bool res = false; - LLIMFloater* im_floater = findIMFloater(notification); + LLIMFloater* im_floater = find_im_floater(notification); if (im_floater != NULL) { res = im_floater->getVisible() == TRUE; @@ -243,11 +134,11 @@ bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) return res; } -bool LLHandlerUtil::isIMFloaterFocused(const LLNotificationPtr& notification) +static bool is_IM_floater_focused(const LLNotificationPtr& notification) { bool res = false; - LLIMFloater* im_floater = findIMFloater(notification); + LLIMFloater* im_floater = find_im_floater(notification); if (im_floater != NULL) { res = im_floater->hasFocus() == TRUE; @@ -335,7 +226,7 @@ void log_name_callback(const std::string& full_name, const std::string& from_nam void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_file_only) { // don't create IM p2p session with objects, it's necessary condition to log - if (notification->getName() != OBJECT_GIVE_ITEM) + //if (notification->getName() != OBJECT_GIVE_ITEM) { LLUUID from_id = notification->getPayload()["from_id"]; @@ -505,3 +396,4 @@ void LLHandlerUtil::decIMMesageCounter(const LLNotificationPtr& notification) arg["participant_unread"] = session->mParticipantUnreadMessageCount; LLIMModel::getInstance()->mNewMsgSignal(arg); } + diff --git a/indra/newview/llnotificationhinthandler.cpp b/indra/newview/llnotificationhinthandler.cpp index f7163cb04f..47156a3915 100644 --- a/indra/newview/llnotificationhinthandler.cpp +++ b/indra/newview/llnotificationhinthandler.cpp @@ -33,26 +33,6 @@ using namespace LLNotificationsUI; -LLHintHandler::LLHintHandler() -{ -} - -LLHintHandler::~LLHintHandler() -{ -} - -bool LLHintHandler::processNotification(const LLSD& notify) -{ - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - std::string sigtype = notify["sigtype"].asString(); - if (sigtype == "add" || sigtype == "load") - { - LLHints::show(notification); - } - else if (sigtype == "delete") - { - LLHints::hide(notification); - } - return false; -} +void LLHintHandler::onAdd(LLNotificationPtr p) { LLHints::show(p); } +void LLHintHandler::onChange(LLNotificationPtr p) { LLHints::show(p); } +void LLHintHandler::onDelete(LLNotificationPtr p) { LLHints::hide(p); } diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 6105eff8ea..394ae2ac21 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -41,7 +41,6 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLNotificationManager::LLNotificationManager() { - mNotifyHandlers.clear(); init(); } @@ -53,88 +52,23 @@ LLNotificationManager::~LLNotificationManager() //-------------------------------------------------------------------------- void LLNotificationManager::init() { - LLNotificationChannel::buildChannel("Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notify")); - LLNotificationChannel::buildChannel("NotificationTips", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytip")); - LLNotificationChannel::buildChannel("Group Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "groupnotify")); - LLNotificationChannel::buildChannel("Alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")); - LLNotificationChannel::buildChannel("AlertModal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); - LLNotificationChannel::buildChannel("IM Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytoast")); - LLNotificationChannel::buildChannel("Offer", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "offer")); - LLNotificationChannel::buildChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint")); - LLNotificationChannel::buildChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser")); - LLNotificationChannel::buildChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")); - - LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("Group Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1)); - LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1)); - LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1)); - - mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD())); - mNotifyHandlers["notifytip"] = boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD())); - mNotifyHandlers["groupnotify"] = boost::shared_ptr<LLEventHandler>(new LLGroupHandler(NT_GROUPNOTIFY, LLSD())); - mNotifyHandlers["alert"] = boost::shared_ptr<LLEventHandler>(new LLAlertHandler(NT_ALERT, LLSD())); - mNotifyHandlers["alertmodal"] = boost::shared_ptr<LLEventHandler>(new LLAlertHandler(NT_ALERT, LLSD())); - static_cast<LLAlertHandler*>(mNotifyHandlers["alertmodal"].get())->setAlertMode(true); - mNotifyHandlers["notifytoast"] = boost::shared_ptr<LLEventHandler>(new LLIMHandler(NT_IMCHAT, LLSD())); - - mNotifyHandlers["nearbychat"] = boost::shared_ptr<LLEventHandler>(new LLNearbyChatHandler(NT_NEARBYCHAT, LLSD())); - mNotifyHandlers["offer"] = boost::shared_ptr<LLEventHandler>(new LLOfferHandler(NT_OFFER, LLSD())); -} - -//-------------------------------------------------------------------------- -bool LLNotificationManager::onNotification(const LLSD& notify) -{ - LLSysHandler* handle = NULL; - - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if (!notification) - return false; - - std::string notification_type = notification->getType(); - handle = static_cast<LLSysHandler*>(mNotifyHandlers[notification_type].get()); - - if(!handle) - return false; + new LLScriptHandler(); + new LLTipHandler(); + new LLGroupHandler(); + new LLAlertHandler("Alerts", "alert", false); + new LLAlertHandler("AlertModal", "alertmodal", true); + new LLOfferHandler(); + new LLHintHandler(); + new LLBrowserNotification(); + new LLOutboxNotification(); - return handle->processNotification(notify); + mChatHandler = boost::shared_ptr<LLNearbyChatHandler>(new LLNearbyChatHandler()); } //-------------------------------------------------------------------------- void LLNotificationManager::onChat(const LLChat& msg, const LLSD &args) { - // check ENotificationType argument - switch(args["type"].asInteger()) - { - case NT_NEARBYCHAT: - { - LLNearbyChatHandler* handle = dynamic_cast<LLNearbyChatHandler*>(mNotifyHandlers["nearbychat"].get()); - - if(handle) - handle->processChat(msg, args); - } - break; - default: //no need to handle all enum types - break; - } + if(mChatHandler) + mChatHandler->processChat(msg, args); } -//-------------------------------------------------------------------------- -LLEventHandler* LLNotificationManager::getHandlerForNotification(std::string notification_type) -{ - std::map<std::string, boost::shared_ptr<LLEventHandler> >::iterator it = mNotifyHandlers.find(notification_type); - - if(it != mNotifyHandlers.end()) - return (*it).second.get(); - - return NULL; -} - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index 16e82e4cce..4d124e1379 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -56,20 +56,11 @@ public: void init(void); //TODO: combine processing and storage (*) - // this method reacts on system notifications and calls an appropriate handler - bool onNotification(const LLSD& notification); - // this method reacts on chat notifications and calls an appropriate handler void onChat(const LLChat& msg, const LLSD &args); - // get a handler for a certain type of notification - LLEventHandler* getHandlerForNotification(std::string notification_type); - - private: - //TODO (*) - std::map<std::string, boost::shared_ptr<LLEventHandler> > mNotifyHandlers; - // cruft std::map<std::string, LLChatHandler*> mChatHandlers; + boost::shared_ptr<class LLNearbyChatHandler> mChatHandler; }; } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 68fd65be0f..8010417d43 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -40,17 +40,16 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- -LLOfferHandler::LLOfferHandler(e_notification_type type, const LLSD& id) +LLOfferHandler::LLOfferHandler() +: LLSysHandler("Offer", "offer") { - mType = type; - // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel(); mChannel->setControlHovering(true); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) - channel->setOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1)); + channel->addOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1)); } //-------------------------------------------------------------------------- @@ -67,126 +66,118 @@ void LLOfferHandler::initChannel() } //-------------------------------------------------------------------------- -bool LLOfferHandler::processNotification(const LLSD& notify) +bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) { if(!mChannel) { return false; } - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if(!notification) - return false; - // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") - { + bool add_notif_to_im = notification->canLogToIM() && notification->hasFormElements(); + if( notification->getPayload().has("give_inventory_notification") + && !notification->getPayload()["give_inventory_notification"] ) + { + // This is an original inventory offer, so add a script floater + LLScriptFloaterManager::instance().onAddNotification(notification->getID()); + } + else + { + notification->setReusable(add_notif_to_im); - if( notification->getPayload().has("give_inventory_notification") - && !notification->getPayload()["give_inventory_notification"] ) - { - // This is an original inventory offer, so add a script floater - LLScriptFloaterManager::instance().onAddNotification(notification->getID()); - } - else + LLUUID session_id; + if (add_notif_to_im) { - notification->setReusable(LLHandlerUtil::isNotificationReusable(notification)); + const std::string name = LLHandlerUtil::getSubstitutionName(notification); - LLUUID session_id; - if (LLHandlerUtil::canSpawnIMSession(notification)) - { - const std::string name = LLHandlerUtil::getSubstitutionName(notification); + LLUUID from_id = notification->getPayload()["from_id"]; - LLUUID from_id = notification->getPayload()["from_id"]; + session_id = LLHandlerUtil::spawnIMSession(name, from_id); + } - session_id = LLHandlerUtil::spawnIMSession(name, from_id); - } + if (add_notif_to_im) + { + LLHandlerUtil::addNotifPanelToIM(notification); + } - bool show_toast = LLHandlerUtil::canSpawnToast(notification); - bool add_notid_to_im = LLHandlerUtil::canAddNotifPanelToIM(notification); - if (add_notid_to_im) + if (notification->getPayload().has("SUPPRESS_TOAST") + && notification->getPayload()["SUPPRESS_TOAST"]) + { + LLNotificationsUtil::cancel(notification); + } + else if(!notification->canLogToIM() || !LLHandlerUtil::isIMFloaterOpened(notification)) + { + LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); + // don't close notification on panel destroy since it will be used by IM floater + notify_box->setCloseNotificationOnDestroy(!add_notif_to_im); + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = notify_box; + p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); + // we not save offer notifications to the syswell floater that should be added to the IM floater + p.can_be_stored = !add_notif_to_im; + + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->addToast(p); + + // if we not add notification to IM - add it to notification well + if (!add_notif_to_im) { - LLHandlerUtil::addNotifPanelToIM(notification); + // send a signal to the counter manager + mNewNotificationSignal(); } + } - if (notification->getPayload().has("SUPPRESS_TOAST") - && notification->getPayload()["SUPPRESS_TOAST"]) - { - LLNotificationsUtil::cancel(notification); - } - else if(show_toast) + if (notification->canLogToIM()) + { + // log only to file if notif panel can be embedded to IM and IM is opened + if (add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) { - LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); - // don't close notification on panel destroy since it will be used by IM floater - notify_box->setCloseNotificationOnDestroy(!add_notid_to_im); - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.panel = notify_box; - p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); - // we not save offer notifications to the syswell floater that should be added to the IM floater - p.can_be_stored = !add_notid_to_im; - - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); - if(channel) - channel->addToast(p); - - // if we not add notification to IM - add it to notification well - if (!add_notid_to_im) - { - // send a signal to the counter manager - mNewNotificationSignal(); - } + LLHandlerUtil::logToIMP2P(notification, true); } - - if (LLHandlerUtil::canLogToIM(notification)) + else { - // log only to file if notif panel can be embedded to IM and IM is opened - if (add_notid_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) - { - LLHandlerUtil::logToIMP2P(notification, true); - } - else - { - LLHandlerUtil::logToIMP2P(notification); - } + LLHandlerUtil::logToIMP2P(notification); } } } - else if (notify["sigtype"].asString() == "delete") + + return false; +} + +/*virtual*/ void LLOfferHandler::onDelete(LLNotificationPtr notification) +{ + if( notification->getPayload().has("give_inventory_notification") + && !notification->getPayload()["give_inventory_notification"] ) + { + // Remove original inventory offer script floater + LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); + } + else { - if( notification->getPayload().has("give_inventory_notification") - && !notification->getPayload()["give_inventory_notification"] ) + if (notification->canLogToIM() + && notification->hasFormElements() + && !LLHandlerUtil::isIMFloaterOpened(notification)) { - // Remove original inventory offer script floater - LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); - } - else - { - if (LLHandlerUtil::canAddNotifPanelToIM(notification) - && !LLHandlerUtil::isIMFloaterOpened(notification)) - { - LLHandlerUtil::decIMMesageCounter(notification); - } - mChannel->killToastByNotificationID(notification->getID()); + LLHandlerUtil::decIMMesageCounter(notification); } + mChannel->killToastByNotificationID(notification->getID()); } - - return false; } //-------------------------------------------------------------------------- void LLOfferHandler::onDeleteToast(LLToast* toast) { - if (!LLHandlerUtil::canAddNotifPanelToIM(toast->getNotification())) + if (!toast->getNotification()->canLogToIM() || !toast->getNotification()->hasFormElements()) { // send a signal to the counter manager mDelNotificationSignal(); @@ -202,11 +193,10 @@ void LLOfferHandler::onRejectToast(LLUUID& id) { LLNotificationPtr notification = LLNotifications::instance().find(id); - if (notification - && LLNotificationManager::getInstance()->getHandlerForNotification( - notification->getType()) == this - // don't delete notification since it may be used by IM floater - && !LLHandlerUtil::canAddNotifPanelToIM(notification)) + if (notification + && mItems.find(notification) != mItems.end() + // don't delete notification since it may be used by IM floater + && (!notification->canLogToIM() || !notification->hasFormElements())) { LLNotifications::instance().cancel(notification); } diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index bbb4d03768..714f14963c 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -42,17 +42,16 @@ static const std::string SCRIPT_DIALOG_GROUP ("ScriptDialogGroup"); static const std::string SCRIPT_LOAD_URL ("LoadWebPage"); //-------------------------------------------------------------------------- -LLScriptHandler::LLScriptHandler(e_notification_type type, const LLSD& id) +LLScriptHandler::LLScriptHandler() +: LLSysHandler("Notifications", "notify") { - mType = type; - // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel(); mChannel->setControlHovering(true); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) - channel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1)); + channel->addOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1)); } @@ -70,69 +69,65 @@ void LLScriptHandler::initChannel() } //-------------------------------------------------------------------------- -bool LLScriptHandler::processNotification(const LLSD& notify) +bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) { if(!mChannel) { return false; } - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if(!notification) - return false; - // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - if(notify["sigtype"].asString() == "add") + if (notification->canLogToIM()) { - if (LLHandlerUtil::canLogToIM(notification)) - { - LLHandlerUtil::logToIMP2P(notification); - } + LLHandlerUtil::logToIMP2P(notification); + } - if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) - { - LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID()); - } - else - { - LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); - - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.panel = notify_box; - p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); - - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); - if(channel) - { - channel->addToast(p); - } - - // send a signal to the counter manager - mNewNotificationSignal(); - } + if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) + { + LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID()); } - else if (notify["sigtype"].asString() == "delete") + else { - if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) - { - LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); - } - else + LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); + + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = notify_box; + p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); + + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) { - mChannel->killToastByNotificationID(notification->getID()); + channel->addToast(p); } + + // send a signal to the counter manager + mNewNotificationSignal(); } + return false; } + +void LLScriptHandler::onDelete( LLNotificationPtr notification ) +{ + if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) + { + LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); + } + else + { + mChannel->killToastByNotificationID(notification->getID()); + } +} + + //-------------------------------------------------------------------------- void LLScriptHandler::onDeleteToast(LLToast* toast) @@ -158,9 +153,7 @@ void LLScriptHandler::onRejectToast(LLUUID& id) { LLNotificationPtr notification = LLNotifications::instance().find(id); - if (notification - && LLNotificationManager::getInstance()->getHandlerForNotification( - notification->getType()) == this) + if (notification && mItems.find(notification) != mItems.end()) { LLNotifications::instance().cancel(notification); } diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index fb0891c4c5..0b0ac040cb 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -41,16 +41,15 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- -LLTipHandler::LLTipHandler(e_notification_type type, const LLSD& id) +LLTipHandler::LLTipHandler() +: LLSysHandler("NotificationTips", "notifytip") { - mType = type; - // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel(); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) - channel->setOnRejectToastCallback(boost::bind(&LLTipHandler::onRejectToast, this, _1)); + channel->addOnRejectToastCallback(boost::bind(&LLTipHandler::onRejectToast, this, _1)); } //-------------------------------------------------------------------------- @@ -67,90 +66,74 @@ void LLTipHandler::initChannel() } //-------------------------------------------------------------------------- -bool LLTipHandler::processNotification(const LLSD& notify) +bool LLTipHandler::processNotification(const LLNotificationPtr& notification) { if(!mChannel) { return false; } - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if(!notification) - return false; - // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") + // archive message in nearby chat + if (notification->canLogToChat()) { - // archive message in nearby chat - if (LLHandlerUtil::canLogToNearbyChat(notification)) - { - LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); - - // don't show toast if Nearby Chat is opened - LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); - if (!nearby_chat_bar->isMinimized() && nearby_chat_bar->getVisible() && nearby_chat->getVisible()) - { - return false; - } - } + LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); - std::string session_name = notification->getPayload()["SESSION_NAME"]; - const std::string name = notification->getSubstitutions()["NAME"]; - if (session_name.empty()) - { - session_name = name; - } - LLUUID from_id = notification->getPayload()["from_id"]; - if (LLHandlerUtil::canLogToIM(notification)) - { - LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, - notification->getMessage(), from_id, from_id); - } - - if (LLHandlerUtil::canSpawnIMSession(notification)) - { - LLHandlerUtil::spawnIMSession(name, from_id); - } - - // don't spawn toast for inventory accepted/declined offers if respective IM window is open (EXT-5909) - if (!LLHandlerUtil::canSpawnToast(notification)) + // don't show toast if Nearby Chat is opened + LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); + LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); + if (!nearby_chat_bar->isMinimized() && nearby_chat_bar->getVisible() && nearby_chat->getVisible()) { return false; } + } - LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); - - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); - p.panel = notify_box; - p.is_tip = true; - p.can_be_stored = false; - - removeExclusiveNotifications(notification); + std::string session_name = notification->getPayload()["SESSION_NAME"]; + const std::string name = notification->getSubstitutions()["NAME"]; + if (session_name.empty()) + { + session_name = name; + } + LLUUID from_id = notification->getPayload()["from_id"]; + if (notification->canLogToIM()) + { + LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, + notification->getMessage(), from_id, from_id); + } - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); - if(channel) - channel->addToast(p); + if (notification->canLogToIM() && notification->hasFormElements()) + { + LLHandlerUtil::spawnIMSession(name, from_id); } - else if (notify["sigtype"].asString() == "delete") + + if (notification->canLogToIM() && LLHandlerUtil::isIMFloaterOpened(notification)) { - mChannel->killToastByNotificationID(notification->getID()); + return false; } - return false; -} -//-------------------------------------------------------------------------- -void LLTipHandler::onDeleteToast(LLToast* toast) -{ + LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); + + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); + p.panel = notify_box; + p.is_tip = true; + p.can_be_stored = false; + + removeExclusiveNotifications(notification); + + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->addToast(p); + + + return false; } //-------------------------------------------------------------------------- @@ -159,9 +142,7 @@ void LLTipHandler::onRejectToast(const LLUUID& id) { LLNotificationPtr notification = LLNotifications::instance().find(id); - if (notification - && LLNotificationManager::getInstance()->getHandlerForNotification( - notification->getType()) == this) + if (notification && mItems.find(notification) != mItems.end()) { LLNotifications::instance().cancel(notification); } diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index c9f8855fe6..2ea5b8e546 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -228,16 +228,16 @@ public: // Channel's signals // signal on storing of faded toasts event - typedef boost::function<void (LLPanel* info_panel, const LLUUID id)> store_tost_callback_t; - typedef boost::signals2::signal<void (LLPanel* info_panel, const LLUUID id)> store_tost_signal_t; - store_tost_signal_t mOnStoreToast; - boost::signals2::connection setOnStoreToastCallback(store_tost_callback_t cb) { return mOnStoreToast.connect(cb); } + typedef boost::signals2::signal<void (LLPanel* info_panel, const LLUUID id)> store_toast_signal_t; + boost::signals2::connection addOnStoreToastCallback(store_toast_signal_t::slot_type cb) { return mOnStoreToast.connect(cb); } // signal on rejecting of a toast event - typedef boost::function<void (LLUUID id)> reject_tost_callback_t; - typedef boost::signals2::signal<void (LLUUID id)> reject_tost_signal_t; - reject_tost_signal_t mRejectToastSignal; boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mRejectToastSignal.connect(cb); } + typedef boost::signals2::signal<void (LLUUID id)> reject_toast_signal_t; + boost::signals2::connection addOnRejectToastCallback(reject_toast_signal_t::slot_type cb) { return mRejectToastSignal.connect(cb); } private: + store_toast_signal_t mOnStoreToast; + reject_toast_signal_t mRejectToastSignal; + struct ToastElem { LLUUID id; diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 0cb6c85012..e8293ebe2b 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -437,9 +437,9 @@ LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key) : LLSysWellWindow(key) { // init connections to the list's update events - connectListUpdaterToSignal("notify"); - connectListUpdaterToSignal("groupnotify"); - connectListUpdaterToSignal("offer"); + connectListUpdaterToSignal("Notifications"); + connectListUpdaterToSignal("Group Notifications"); + connectListUpdaterToSignal("Offer"); } // static @@ -519,7 +519,7 @@ void LLNotificationWellWindow::initChannel() LLSysWellWindow::initChannel(); if(mChannel) { - mChannel->setOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2)); + mChannel->addOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2)); } } @@ -548,8 +548,7 @@ void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id) void LLNotificationWellWindow::connectListUpdaterToSignal(std::string notification_type) { - LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); - LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); + LLNotificationsUI::LLEventHandler* n_handler = dynamic_cast<LLNotificationsUI::LLEventHandler*>(LLNotifications::instance().getChannel(notification_type).get()); if(n_handler) { n_handler->setNotificationIDCallback(boost::bind(&LLNotificationWellWindow::removeItemByID, this, _1)); diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index 75178a6ef8..707d2d9765 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -51,7 +51,7 @@ const S32 LLToastGroupNotifyPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 7; -LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification) +LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(const LLNotificationPtr& notification) : LLToastPanel(notification), mInventoryOffer(NULL) { diff --git a/indra/newview/lltoastgroupnotifypanel.h b/indra/newview/lltoastgroupnotifypanel.h index 7794ec9f63..3b8b31eac1 100644 --- a/indra/newview/lltoastgroupnotifypanel.h +++ b/indra/newview/lltoastgroupnotifypanel.h @@ -53,7 +53,7 @@ public: // Non-transient messages. You can specify non-default button // layouts (like one for script dialogs) by passing various // numbers in for "layout". - LLToastGroupNotifyPanel(LLNotificationPtr& notification); + LLToastGroupNotifyPanel(const LLNotificationPtr& notification); /*virtual*/ ~LLToastGroupNotifyPanel(); protected: diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index de305bf3d9..dc5cc88dc4 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -52,7 +52,7 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL; LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal; -LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification, const LLRect& rect, bool show_images) : +LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) : LLToastPanel(notification), mTextBox(NULL), mInfoPanel(NULL), @@ -536,7 +536,7 @@ void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id } } -void LLToastNotifyPanel::disableRespondedOptions(LLNotificationPtr& notification) +void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) { LLSD response = notification->getResponse(); for (LLSD::map_const_iterator response_it = response.beginMap(); diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index 57711b3d80..db517ec858 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -60,7 +60,7 @@ public: * @deprecated if you intend to instantiate LLToastNotifyPanel - it's point to * implement right class for desired toast panel. @see LLGenericTipPanel as example. */ - LLToastNotifyPanel(LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); + LLToastNotifyPanel(const LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); virtual ~LLToastNotifyPanel(); LLPanel * getControlPanel() { return mControlPanel; } @@ -118,7 +118,7 @@ protected: /** * Process response data. Will disable selected options */ - void disableRespondedOptions(LLNotificationPtr& notification); + void disableRespondedOptions(const LLNotificationPtr& notification); bool mIsTip; bool mAddedDefaultBtn; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 3c6770df43..4f83d9096c 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2776,7 +2776,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) chat.mOwnerID = from_id; LLSD args; args["slurl"] = location; - args["type"] = LLNotificationsUI::NT_NEARBYCHAT; // Look for IRC-style emotes here so object name formatting is correct std::string prefix = message.substr(0, 4); @@ -3379,7 +3378,6 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) // pass owner_id to chat so that we can display the remote // object inspect for an object that is chatting with you LLSD args; - args["type"] = LLNotificationsUI::NT_NEARBYCHAT; chat.mOwnerID = owner_id; if (gSavedSettings.getBOOL("TranslateChat") && chat.mSourceType != CHAT_SOURCE_SYSTEM) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index e0653fec30..6d9b8b4eb3 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1548,11 +1548,11 @@ LLViewerWindow::LLViewerWindow(const Params& p) mViewerWindowListener(new LLViewerWindowListener(this)), mProgressView(NULL) { - LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")); - LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); + LLNotificationChannelPtr vw_alerts_channel(new LLNotificationChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"))); + LLNotificationChannelPtr vw_alerts_modal_channel(new LLNotificationChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"))); - LLNotifications::instance().getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert); - LLNotifications::instance().getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert); + vw_alerts_channel->connectChanged(&LLViewerWindow::onAlert); + vw_alerts_modal_channel->connectChanged(&LLViewerWindow::onAlert); LLNotifications::instance().setIgnoreAllNotifications(gSavedSettings.getBOOL("IgnoreAllNotifications")); llinfos << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << llendl; diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index af75d49353..da83ffbab4 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2904,6 +2904,7 @@ Would you like to trust this authority? icon="alertmodal.tga" name="GrantedModifyRights" persist="true" + log_to_im="true" type="notify"> [NAME] has given you permission to edit their objects. </notification> @@ -2912,6 +2913,7 @@ Would you like to trust this authority? icon="alertmodal.tga" name="RevokedModifyRights" persist="true" + log_to_im="true" type="notify"> Your privilege to modify [NAME]'s objects has been revoked </notification> @@ -5161,6 +5163,8 @@ The string [STRING_NAME] is missing from strings.xml <notification icon="notifytip.tga" name="IMSystemMessageTip" + log_to_im="true" + log_to_chat="true" type="notifytip"> [MESSAGE] </notification> @@ -5205,6 +5209,7 @@ Topic: [SUBJECT], Message: [MESSAGE] <notification icon="notifytip.tga" name="FriendOnline" + log_to_chat="true" type="notifytip"> <tag>friendship</tag> <nolink>[NAME]</nolink> is Online @@ -5213,6 +5218,7 @@ Topic: [SUBJECT], Message: [MESSAGE] <notification icon="notifytip.tga" name="FriendOffline" + log_to_chat="true" type="notifytip"> <tag>friendship</tag> <nolink>[NAME]</nolink> is Offline @@ -5459,6 +5465,8 @@ You don't have permission to copy this. <notification icon="notifytip.tga" name="InventoryAccepted" + log_to_im="true" + log_to_chat="true" type="notifytip"> [NAME] received your inventory offer. </notification> @@ -5466,6 +5474,8 @@ You don't have permission to copy this. <notification icon="notifytip.tga" name="InventoryDeclined" + log_to_im="true" + log_to_chat="true" type="notifytip"> [NAME] declined your inventory offer. </notification> @@ -5547,6 +5557,7 @@ Please select at least one type of content to search (General, Moderate, or Adul <notification icon="notify.tga" name="PaymentReceived" + log_to_im="true" persist="true" type="notify"> <tag>funds</tag> @@ -5556,6 +5567,7 @@ Please select at least one type of content to search (General, Moderate, or Adul <notification icon="notify.tga" name="PaymentSent" + log_to_im="true" persist="true" type="notify"> <tag>funds</tag> @@ -5700,6 +5712,7 @@ The objects on the selected parcel that are NOT owned by you have been returned <notification icon="notify.tga" name="ServerObjectMessage" + log_to_im="true" persist="true" type="notify"> Message from [NAME]: @@ -6070,6 +6083,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th <notification icon="notify.tga" name="UserGiveItem" + log_to_im ="true" type="offer"> [NAME_SLURL] has given you this [OBJECTTYPE]: [ITEM_SLURL] @@ -6125,6 +6139,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th <notification icon="notify.tga" name="TeleportOffered" + log_to_im="true" type="offer"> [NAME_SLURL] has offered to teleport you to their location: @@ -6145,6 +6160,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th <notification icon="notify.tga" name="TeleportOfferSent" + log_to_im="true" type="offer"> Teleport offer sent to [TO_NAME] </notification> @@ -6172,6 +6188,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th <notification icon="notify.tga" name="OfferFriendship" + log_to_im="true" type="offer"> <tag>friendship</tag> <tag>confirm</tag> @@ -6195,6 +6212,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th <notification icon="notify.tga" name="FriendshipOffered" + log_to_im="true" type="offer"> <tag>friendship</tag> You have offered friendship to [TO_NAME] @@ -6224,6 +6242,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th <notification icon="notify.tga" name="FriendshipAccepted" + log_to_im="true" type="offer"> <tag>friendship</tag> <nolink>[NAME]</nolink> accepted your friendship offer. @@ -6232,6 +6251,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th <notification icon="notify.tga" name="FriendshipDeclined" + log_to_im="true" persist="true" type="notify"> <tag>friendship</tag> @@ -6241,6 +6261,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th <notification icon="notify.tga" name="FriendshipAcceptedByMe" + log_to_im="true" type="offer"> <tag>friendship</tag> Friendship offer accepted. @@ -6249,6 +6270,7 @@ Friendship offer accepted. <notification icon="notify.tga" name="FriendshipDeclinedByMe" + log_to_im="true" type="offer"> <tag>friendship</tag> Friendship offer declined. -- cgit v1.2.3 From 2fa1c42aadbe2a29e1bcced9a487c0e5abf0602b Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 29 Mar 2012 23:48:29 -0700 Subject: CHUI-51 WIP notifications routig code cleanup phase 2, removal of extraneous signaling in favor of llnotificationchannels made notificationchannels work better with overrides and lifetime managed by creator --- indra/llcommon/llinstancetracker.h | 5 +- indra/llcommon/llrefcount.h | 19 +++++ indra/llcommon/llthread.h | 17 +++++ indra/llui/llnotifications.cpp | 92 +++++++++++++------------ indra/llui/llnotifications.h | 49 ++++++++----- indra/llui/llnotificationslistener.cpp | 8 +-- indra/newview/llchiclet.cpp | 26 +++---- indra/newview/llchiclet.h | 31 +++++++-- indra/newview/llfloaternotificationsconsole.cpp | 38 ++-------- indra/newview/llimhandler.cpp | 12 ---- indra/newview/llnotificationgrouphandler.cpp | 14 ---- indra/newview/llnotificationhandler.h | 23 +------ indra/newview/llnotificationhandlerutil.cpp | 88 ++++++++--------------- indra/newview/llnotificationmanager.cpp | 19 ++--- indra/newview/llnotificationmanager.h | 1 + indra/newview/llnotificationofferhandler.cpp | 42 ++--------- indra/newview/llnotificationscripthandler.cpp | 19 +---- indra/newview/llsyswellwindow.cpp | 37 +++++----- indra/newview/llsyswellwindow.h | 19 +++-- indra/newview/lltoastgroupnotifypanel.h | 3 - indra/newview/lltoastscripttextbox.h | 2 - 21 files changed, 241 insertions(+), 323 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 34d841a4e0..11f582372e 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -43,7 +43,7 @@ * semantics: one instance per process, rather than one instance per module as * sometimes happens with data simply declared static. */ -class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable +class LL_COMMON_API LLInstanceTrackerBase { protected: /// Get a process-unique void* pointer slot for the specified type_info @@ -209,6 +209,9 @@ protected: virtual const KEY& getKey() const { return mInstanceKey; } private: + LLInstanceTracker( const LLInstanceTracker& ); + const LLInstanceTracker& operator=( const LLInstanceTracker& ); + void add_(KEY key) { mInstanceKey = key; diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h index 8eb5d53f3f..32ae15435a 100644 --- a/indra/llcommon/llrefcount.h +++ b/indra/llcommon/llrefcount.h @@ -27,6 +27,7 @@ #define LLREFCOUNT_H #include <boost/noncopyable.hpp> +#include <boost/intrusive_ptr.hpp> #define LL_REF_COUNT_DEBUG 0 #if LL_REF_COUNT_DEBUG @@ -86,4 +87,22 @@ private: #endif }; +/** + * intrusive pointer support + * this allows you to use boost::intrusive_ptr with any LLRefCount-derived type + */ +namespace boost +{ + inline void intrusive_ptr_add_ref(LLRefCount* p) + { + p->ref(); + } + + inline void intrusive_ptr_release(LLRefCount* p) + { + p->unref(); + } +}; + + #endif diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index b52e70ab2e..cf39696b4f 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -30,6 +30,7 @@ #include "llapp.h" #include "llapr.h" #include "apr_thread_cond.h" +#include "boost/intrusive_ptr.hpp" class LLThread; class LLMutex; @@ -266,6 +267,22 @@ private: S32 mRef; }; +/** + * intrusive pointer support for LLThreadSafeRefCount + * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type + */ +namespace boost +{ + inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p) + { + p->ref(); + } + + inline void intrusive_ptr_release(LLThreadSafeRefCount* p) + { + p->unref(); + } +}; //============================================================================ // Simple responder for self destructing callbacks diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 038a86d20a..c45899a4bd 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -966,7 +966,7 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt std::string cmd = payload["sigtype"]; LLNotificationSet::iterator foundItem = mItems.find(pNotification); bool wasFound = (foundItem != mItems.end()); - bool passesFilter = mFilter(pNotification); + bool passesFilter = mFilter ? mFilter(pNotification) : true; // first, we offer the result of the filter test to the simple // signals for pass/fail. One of these is guaranteed to be called. @@ -1071,27 +1071,28 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt return abortProcessing; } +LLNotificationChannel::LLNotificationChannel(const Params& p) +: LLNotificationChannelBase(p.filter(), p.comparator()), + LLInstanceTracker<LLNotificationChannel, std::string>(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()), + mName(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()) +{ + BOOST_FOREACH(const std::string& source, p.sources) + { + connectToChannel(source); + } +} + + LLNotificationChannel::LLNotificationChannel(const std::string& name, const std::string& parent, LLNotificationFilter filter, - LLNotificationComparator comparator) : -LLNotificationChannelBase(filter, comparator), -mName(name), -mParent(parent) + LLNotificationComparator comparator) +: LLNotificationChannelBase(filter, comparator), + LLInstanceTracker<LLNotificationChannel, std::string>(name), + mName(name) { - // store myself in the channel map - LLNotifications::instance().addChannel(LLNotificationChannelPtr(this)); // bind to notification broadcast - if (parent.empty()) - { - LLNotifications::instance().connectChanged( - boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); - } - else - { - LLNotificationChannelPtr p = LLNotifications::instance().getChannel(parent); - p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); - } + connectToChannel(parent); } @@ -1134,6 +1135,21 @@ std::string LLNotificationChannel::summarize() return s; } +void LLNotificationChannel::connectToChannel( const std::string& channel_name ) +{ + if (channel_name.empty()) + { + LLNotifications::instance().connectChanged( + boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); + } + else + { + LLNotificationChannelPtr p = LLNotifications::instance().getChannel(channel_name); + p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); + } +} + + // --- // END OF LLNotificationChannel implementation @@ -1248,21 +1264,9 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload) return false; } - -void LLNotifications::addChannel(LLNotificationChannelPtr pChan) -{ - mChannels[pChan->getName()] = pChan; -} - LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelName) { - ChannelMap::iterator p = mChannels.find(channelName); - if(p == mChannels.end()) - { - llerrs << "Did not find channel named " << channelName << llendl; - return LLNotificationChannelPtr(); - } - return p->second; + return LLNotificationChannelPtr(LLNotificationChannel::getInstance(channelName)); } @@ -1278,20 +1282,20 @@ void LLNotifications::createDefaultChannels() { // now construct the various channels AFTER loading the notifications, // because the history channel is going to rewrite the stored notifications file - new LLNotificationChannel("Enabled", "", - !boost::bind(&LLNotifications::getIgnoreAllNotifications, this)); - new LLNotificationChannel("Expiration", "Enabled", - boost::bind(&LLNotifications::expirationFilter, this, _1)); - new LLNotificationChannel("Unexpired", "Enabled", - !boost::bind(&LLNotifications::expirationFilter, this, _1)); // use negated bind - new LLNotificationChannel("Unique", "Unexpired", - boost::bind(&LLNotifications::uniqueFilter, this, _1)); - new LLNotificationChannel("Ignore", "Unique", - filterIgnoredNotifications); - new LLNotificationChannel("VisibilityRules", "Ignore", - boost::bind(&LLNotifications::isVisibleByRules, this, _1)); - new LLNotificationChannel("Visible", "VisibilityRules", - &LLNotificationFilters::includeEverything); + mDefaultChannels.push_back(new LLNotificationChannel("Enabled", "", + !boost::bind(&LLNotifications::getIgnoreAllNotifications, this))); + mDefaultChannels.push_back(new LLNotificationChannel("Expiration", "Enabled", + boost::bind(&LLNotifications::expirationFilter, this, _1))); + mDefaultChannels.push_back(new LLNotificationChannel("Unexpired", "Enabled", + !boost::bind(&LLNotifications::expirationFilter, this, _1))); // use negated bind + mDefaultChannels.push_back(new LLNotificationChannel("Unique", "Unexpired", + boost::bind(&LLNotifications::uniqueFilter, this, _1))); + mDefaultChannels.push_back(new LLNotificationChannel("Ignore", "Unique", + filterIgnoredNotifications)); + mDefaultChannels.push_back(new LLNotificationChannel("VisibilityRules", "Ignore", + boost::bind(&LLNotifications::isVisibleByRules, this, _1))); + mDefaultChannels.push_back(new LLNotificationChannel("Visible", "VisibilityRules", + &LLNotificationFilters::includeEverything)); // create special persistent notification channel // this isn't a leak, don't worry about the empty "new" diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index f83365a97d..344108ecbf 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -94,10 +94,11 @@ // and we need this to manage the notification callbacks #include "llevents.h" #include "llfunctorregistry.h" -#include "llpointer.h" #include "llinitparam.h" #include "llnotificationslistener.h" #include "llnotificationptr.h" +#include "llpointer.h" +#include "llrefcount.h" class LLAvatarName; typedef enum e_notification_priority @@ -707,7 +708,8 @@ typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap; // all of the built-in tests should attach to the "Visible" channel // class LLNotificationChannelBase : - public LLEventTrackable + public LLEventTrackable, + public LLRefCount { LOG_CLASS(LLNotificationChannelBase); public: @@ -787,26 +789,48 @@ protected: // destroy it, but if it becomes necessary to do so, the shared_ptr model // will ensure that we don't leak resources. class LLNotificationChannel; -typedef boost::shared_ptr<LLNotificationChannel> LLNotificationChannelPtr; +typedef boost::intrusive_ptr<LLNotificationChannel> LLNotificationChannelPtr; // manages a list of notifications // Note that if this is ever copied around, we might find ourselves with multiple copies // of a queue with notifications being added to different nonequivalent copies. So we -// make it inherit from boost::noncopyable, and then create a map of shared_ptr to manage it. +// make it inherit from boost::noncopyable, and then create a map of LLPointer to manage it. // class LLNotificationChannel : boost::noncopyable, - public LLNotificationChannelBase + public LLNotificationChannelBase, + public LLInstanceTracker<LLNotificationChannel, std::string> { LOG_CLASS(LLNotificationChannel); public: + // Notification Channels have a filter, which determines which notifications + // will be added to this channel. + // Channel filters cannot change. + struct Params : public LLInitParam::Block<Params> + { + Mandatory<std::string> name; + Optional<LLNotificationFilter> filter; + Optional<LLNotificationComparator> comparator; + Multiple<std::string> sources; + + Params() + : comparator("", LLNotificationComparators::orderByUUID()) + {} + }; + + LLNotificationChannel(const Params& p = Params()); + + LLNotificationChannel(const std::string& name, const std::string& parent, + LLNotificationFilter filter, LLNotificationComparator comparator=LLNotificationComparators::orderByUUID()); + virtual ~LLNotificationChannel() {} typedef LLNotificationSet::iterator Iterator; std::string getName() const { return mName; } - std::string getParentChannelName() { return mParent; } + void connectToChannel(const std::string& channel_name); + bool isEmpty() const; Iterator begin(); @@ -818,14 +842,6 @@ public: std::string summarize(); - // Notification Channels have a filter, which determines which notifications - // will be added to this channel. - // Channel filters cannot change. - // Channels have a protected constructor so you can't make smart pointers that don't - // come from our internal reference; call NotificationChannel::build(args) - LLNotificationChannel(const std::string& name, const std::string& parent, - LLNotificationFilter filter, LLNotificationComparator comparator=LLNotificationComparators::orderByUUID()); - private: std::string mName; std::string mParent; @@ -912,10 +928,6 @@ public: void createDefaultChannels(); - typedef std::map<std::string, LLNotificationChannelPtr> ChannelMap; - ChannelMap mChannels; - - void addChannel(LLNotificationChannelPtr pChan); LLNotificationChannelPtr getChannel(const std::string& channelName); std::string getGlobalString(const std::string& key) const; @@ -954,6 +966,7 @@ private: bool mIgnoreAllNotifications; boost::scoped_ptr<LLNotificationsListener> mListener; + std::vector<LLNotificationChannelPtr> mDefaultChannels; }; /** diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp index 3bbeb3a778..e4e127336b 100644 --- a/indra/llui/llnotificationslistener.cpp +++ b/indra/llui/llnotificationslistener.cpp @@ -121,13 +121,13 @@ void LLNotificationsListener::listChannels(const LLSD& params) const { LLReqID reqID(params); LLSD response(reqID.makeResponse()); - for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()), - cmend(mNotifications.mChannels.end()); + for (LLNotificationChannel::instance_iter cmi(LLNotificationChannel::beginInstances()), + cmend(LLNotificationChannel::endInstances()); cmi != cmend; ++cmi) { LLSD channelInfo; - channelInfo["parent"] = cmi->second->getParentChannelName(); - response[cmi->first] = channelInfo; + //channelInfo["parent"] = cmi->second->getParentChannelName(); + response[cmi->getName()] = channelInfo; } LLEventPumps::instance().obtain(params["reply"]).post(response); } diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 9f19f8dd1c..67519a3ca6 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -335,29 +335,15 @@ void LLIMWellChiclet::messageCountChanged(const LLSD& session_data) /* LLNotificationChiclet implementation */ /************************************************************************/ LLNotificationChiclet::LLNotificationChiclet(const Params& p) -: LLSysWellChiclet(p) -, mUreadSystemNotifications(0) +: LLSysWellChiclet(p), + mUreadSystemNotifications(0) { - // connect counter handlers to the signals - connectCounterUpdatersToSignal("Notify"); - connectCounterUpdatersToSignal("Group Notify"); - connectCounterUpdatersToSignal("Offer"); - + mNotificationChannel.reset(new ChicletNotificationChannel(this)); // ensure that notification well window exists, to synchronously // handle toast add/delete events. LLNotificationWellWindow::getInstance()->setSysWellChiclet(this); } -void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type) -{ - LLNotificationsUI::LLEventHandler* n_handler = dynamic_cast<LLNotificationsUI::LLEventHandler*>(LLNotifications::instance().getChannel(notification_type).get()); - if(n_handler) - { - n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); - n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this)); - } -} - void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data) { std::string action = user_data.asString(); @@ -406,6 +392,12 @@ void LLNotificationChiclet::setCounter(S32 counter) updateWidget(getCounter() == 0); } + +bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notify ) +{ + return !(notify->canLogToIM() && notify->hasFormElements()); +} + ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 1f1069dcb4..dd0d47cccd 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -34,6 +34,7 @@ #include "lloutputmonitorctrl.h" #include "llgroupmgr.h" #include "llimview.h" +#include "llnotifications.h" class LLMenuGL; class LLIMFloater; @@ -911,11 +912,35 @@ protected: class LLNotificationChiclet : public LLSysWellChiclet { + LOG_CLASS(LLNotificationChiclet); + friend class LLUICtrlFactory; public: struct Params : public LLInitParam::Block<Params, LLSysWellChiclet::Params>{}; protected: + struct ChicletNotificationChannel : public LLNotificationChannel + { + ChicletNotificationChannel(LLNotificationChiclet* chiclet) + : LLNotificationChannel(LLNotificationChannel::Params().filter(filterNotification).name(chiclet->getSessionId().asString())), + mChiclet(chiclet) + { + // connect counter handlers to the signals + connectToChannel("IM Notifications"); + connectToChannel("Group Notifications"); + connectToChannel("Offer"); + } + + static bool filterNotification(LLNotificationPtr notify); + // connect counter updaters to the corresponding signals + /*virtual*/ void onAdd(LLNotificationPtr p) { mChiclet->setCounter(++mChiclet->mUreadSystemNotifications); } + /*virtual*/ void onDelete(LLNotificationPtr p) { mChiclet->setCounter(--mChiclet->mUreadSystemNotifications); } + + LLNotificationChiclet* const mChiclet; + }; + + boost::scoped_ptr<ChicletNotificationChannel> mNotificationChannel; + LLNotificationChiclet(const Params& p); /** @@ -933,12 +958,6 @@ protected: */ /*virtual*/ void createMenu(); - // connect counter updaters to the corresponding signals - void connectCounterUpdatersToSignal(const std::string& notification_type); - - // methods for updating a number of unread System notifications - void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications); } - void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications); } /*virtual*/ void setCounter(S32 counter); S32 mUreadSystemNotifications; }; diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index 90dbabebfb..4f35c325a8 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -44,21 +44,16 @@ public: BOOL postBuild(); private: - bool update(const LLSD& payload, bool passed_filter); + bool update(const LLSD& payload); static void toggleClick(void* user_data); static void onClickNotification(void* user_data); - static void onClickNotificationReject(void* user_data); LLNotificationChannelPtr mChannelPtr; - LLNotificationChannelPtr mChannelRejectsPtr; }; LLNotificationChannelPanel::LLNotificationChannelPanel(const LLNotificationChannelPanel::Params& p) : LLLayoutPanel(p) { mChannelPtr = LLNotifications::instance().getChannel(p.name); - mChannelRejectsPtr = LLNotificationChannelPtr( - new LLNotificationChannel(p.name() + "rejects", mChannelPtr->getParentChannelName(), - !boost::bind(mChannelPtr->getFilter(), _1))); buildFromFile( "panel_notifications_channel.xml"); } @@ -68,15 +63,11 @@ BOOL LLNotificationChannelPanel::postBuild() header_button->setLabel(mChannelPtr->getName()); header_button->setClickedCallback(toggleClick, this); - mChannelPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, true)); - mChannelRejectsPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, false)); + mChannelPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1)); LLScrollListCtrl* scroll = getChild<LLScrollListCtrl>("notifications_list"); scroll->setDoubleClickCallback(onClickNotification, this); scroll->setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mRight, 0)); - scroll = getChild<LLScrollListCtrl>("notification_rejects_list"); - scroll->setDoubleClickCallback(onClickNotificationReject, this); - scroll->setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mRight, 0)); return TRUE; } @@ -97,8 +88,6 @@ void LLNotificationChannelPanel::toggleClick(void *user_data) // turn off tab stop for collapsed panel self->getChild<LLScrollListCtrl>("notifications_list")->setTabStop(!header_button->getToggleState()); self->getChild<LLScrollListCtrl>("notifications_list")->setVisible(!header_button->getToggleState()); - self->getChild<LLScrollListCtrl>("notification_rejects_list")->setTabStop(!header_button->getToggleState()); - self->getChild<LLScrollListCtrl>("notification_rejects_list")->setVisible(!header_button->getToggleState()); } /*static*/ @@ -118,24 +107,7 @@ void LLNotificationChannelPanel::onClickNotification(void* user_data) } } -/*static*/ -void LLNotificationChannelPanel::onClickNotificationReject(void* user_data) -{ - LLNotificationChannelPanel* self = (LLNotificationChannelPanel*)user_data; - if (!self) return; - LLScrollListItem* firstselected = self->getChild<LLScrollListCtrl>("notification_rejects_list")->getFirstSelected(); - llassert(firstselected); - if (firstselected) - { - void* data = firstselected->getUserdata(); - if (data) - { - gFloaterView->getParentFloater(self)->addDependentFloater(new LLFloaterNotification((LLNotification*)data), TRUE); - } - } -} - -bool LLNotificationChannelPanel::update(const LLSD& payload, bool passed_filter) +bool LLNotificationChannelPanel::update(const LLSD& payload) { LLNotificationPtr notification = LLNotifications::instance().find(payload["id"].asUUID()); if (notification) @@ -151,9 +123,7 @@ bool LLNotificationChannelPanel::update(const LLSD& payload, bool passed_filter) row["columns"][2]["column"] = "date"; row["columns"][2]["type"] = "date"; - LLScrollListItem* sli = passed_filter ? - getChild<LLScrollListCtrl>("notifications_list")->addElement(row) : - getChild<LLScrollListCtrl>("notification_rejects_list")->addElement(row); + LLScrollListItem* sli = getChild<LLScrollListCtrl>("notifications_list")->addElement(row); sli->setUserdata(&(*notification)); } diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index a92c4fa387..1437d0747c 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -95,24 +95,12 @@ bool LLIMHandler::processNotification(const LLNotificationPtr& notification) p.notification = notification; p.panel = im_box; p.can_be_stored = false; - p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) channel->addToast(p); - // send a signal to the counter manager; - mNewNotificationSignal(); - return false; } -//-------------------------------------------------------------------------- -void LLIMHandler::onDeleteToast(LLToast* toast) -{ - // send a signal to the counter manager - mDelNotificationSignal(); -} - -//-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 2ce51fa094..97e382e42f 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -87,25 +87,11 @@ bool LLGroupHandler::processNotification(const LLNotificationPtr& notification) if(channel) channel->addToast(p); - // send a signal to the counter manager - mNewNotificationSignal(); - LLGroupActions::refresh_notices(); return false; } -//-------------------------------------------------------------------------- -void LLGroupHandler::onDeleteToast(LLToast* toast) -{ - // send a signal to the counter manager - mDelNotificationSignal(); - - // send a signal to a listener to let him perform some action - // in this case listener is a SysWellWindow and it will remove a corresponding item from its list - mNotificationIDSignal(toast->getNotificationID()); -} - //-------------------------------------------------------------------------- void LLGroupHandler::onRejectToast(LLUUID& id) { diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index ff9371f7df..419b8a14b6 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -67,19 +67,6 @@ class LLEventHandler public: virtual ~LLEventHandler() {}; - // callbacks for counters - typedef boost::function<void (void)> notification_callback_t; - typedef boost::signals2::signal<void (void)> notification_signal_t; - notification_signal_t mNewNotificationSignal; - notification_signal_t mDelNotificationSignal; - boost::signals2::connection setNewNotificationCallback(notification_callback_t cb) { return mNewNotificationSignal.connect(cb); } - boost::signals2::connection setDelNotification(notification_callback_t cb) { return mDelNotificationSignal.connect(cb); } - // callback for notification/toast - typedef boost::function<void (const LLUUID id)> notification_id_callback_t; - typedef boost::signals2::signal<void (const LLUUID id)> notification_id_signal_t; - notification_id_signal_t mNotificationIDSignal; - boost::signals2::connection setNotificationIDCallback(notification_id_callback_t cb) { return mNotificationIDSignal.connect(cb); } - protected: virtual void onDeleteToast(LLToast* toast) {} @@ -143,7 +130,6 @@ public: protected: bool processNotification(const LLNotificationPtr& p); - virtual void onDeleteToast(LLToast* toast); virtual void initChannel(); }; @@ -201,7 +187,6 @@ public: virtual bool processNotification(const LLNotificationPtr& p); protected: - virtual void onDeleteToast(LLToast* toast); virtual void initChannel(); // own handlers @@ -244,7 +229,6 @@ public: virtual bool processNotification(const LLNotificationPtr& p); protected: - virtual void onDeleteToast(LLToast* toast); virtual void initChannel(); // own handlers @@ -313,12 +297,7 @@ public: /** * Writes notification message to IM p2p session. */ - static void logToIMP2P(const LLNotificationPtr& notification); - - /** - * Writes notification message to IM p2p session. - */ - static void logToIMP2P(const LLNotificationPtr& notification, bool to_file_only); + static void logToIMP2P(const LLNotificationPtr& notification, bool to_file_only = false); /** * Writes group notice notification message to IM group session. diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index dca7fda151..3ebf0bcc9e 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -111,37 +111,18 @@ void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif) } } -const static std::string OBJECT_GIVE_ITEM("ObjectGiveItem"); - -static LLIMFloater* find_im_floater(const LLNotificationPtr& notification) -{ - LLUUID from_id = notification->getPayload()["from_id"]; - LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); - return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -} - // static bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) { bool res = false; - LLIMFloater* im_floater = find_im_floater(notification); - if (im_floater != NULL) - { - res = im_floater->getVisible() == TRUE; - } - - return res; -} - -static bool is_IM_floater_focused(const LLNotificationPtr& notification) -{ - bool res = false; + LLUUID from_id = notification->getPayload()["from_id"]; + LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); + LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); - LLIMFloater* im_floater = find_im_floater(notification); if (im_floater != NULL) { - res = im_floater->hasFocus() == TRUE; + res = im_floater->getVisible() == TRUE; } return res; @@ -208,12 +189,6 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type, } } -// static -void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification) -{ - logToIMP2P(notification, false); -} - void log_name_callback(const std::string& full_name, const std::string& from_name, const std::string& message, const LLUUID& from_id) @@ -225,25 +200,21 @@ void log_name_callback(const std::string& full_name, const std::string& from_nam // static void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_file_only) { - // don't create IM p2p session with objects, it's necessary condition to log - //if (notification->getName() != OBJECT_GIVE_ITEM) - { - LLUUID from_id = notification->getPayload()["from_id"]; + LLUUID from_id = notification->getPayload()["from_id"]; - if (from_id.isNull()) - { - llwarns << " from_id for notification " << notification->getName() << " is null " << llendl; - return; - } + if (from_id.isNull()) + { + llwarns << " from_id for notification " << notification->getName() << " is null " << llendl; + return; + } - if(to_file_only) - { - gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, "", notification->getMessage(), LLUUID())); - } - else - { - gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, INTERACTIVE_SYSTEM_FROM, notification->getMessage(), from_id)); - } + if(to_file_only) + { + gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, "", notification->getMessage(), LLUUID())); + } + else + { + gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, INTERACTIVE_SYSTEM_FROM, notification->getMessage(), from_id)); } } @@ -377,23 +348,20 @@ void LLHandlerUtil::updateVisibleIMFLoaterMesages(const LLNotificationPtr& notif void LLHandlerUtil::decIMMesageCounter(const LLNotificationPtr& notification) { const std::string name = LLHandlerUtil::getSubstitutionName(notification); - LLUUID from_id = notification->getPayload()["from_id"]; - LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); + LLUUID from_id = notification->getPayload()["from_id"]; + LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); - LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession( - session_id); + LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession(session_id); - if (session == NULL) + if (session) { - return; + LLSD arg; + arg["session_id"] = session_id; + session->mNumUnread--; + arg["num_unread"] = session->mNumUnread; + session->mParticipantUnreadMessageCount--; + arg["participant_unread"] = session->mParticipantUnreadMessageCount; + LLIMModel::getInstance()->mNewMsgSignal(arg); } - - LLSD arg; - arg["session_id"] = session_id; - session->mNumUnread--; - arg["num_unread"] = session->mNumUnread; - session->mParticipantUnreadMessageCount--; - arg["participant_unread"] = session->mParticipantUnreadMessageCount; - LLIMModel::getInstance()->mNewMsgSignal(arg); } diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 394ae2ac21..9beb8afac6 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -52,15 +52,16 @@ LLNotificationManager::~LLNotificationManager() //-------------------------------------------------------------------------- void LLNotificationManager::init() { - new LLScriptHandler(); - new LLTipHandler(); - new LLGroupHandler(); - new LLAlertHandler("Alerts", "alert", false); - new LLAlertHandler("AlertModal", "alertmodal", true); - new LLOfferHandler(); - new LLHintHandler(); - new LLBrowserNotification(); - new LLOutboxNotification(); + mChannels.push_back(new LLScriptHandler()); + mChannels.push_back(new LLTipHandler()); + mChannels.push_back(new LLGroupHandler()); + mChannels.push_back(new LLAlertHandler("Alerts", "alert", false)); + mChannels.push_back(new LLAlertHandler("AlertModal", "alertmodal", true)); + mChannels.push_back(new LLOfferHandler()); + mChannels.push_back(new LLHintHandler()); + mChannels.push_back(new LLBrowserNotification()); + mChannels.push_back(new LLOutboxNotification()); + mChannels.push_back(new LLIMHandler()); mChatHandler = boost::shared_ptr<LLNearbyChatHandler>(new LLNearbyChatHandler()); } diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index 4d124e1379..c8afdf9e46 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -61,6 +61,7 @@ public: private: boost::shared_ptr<class LLNearbyChatHandler> mChatHandler; + std::vector<LLNotificationChannelPtr> mChannels; }; } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 8010417d43..051075cff9 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -79,16 +79,17 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) initChannel(); } - bool add_notif_to_im = notification->canLogToIM() && notification->hasFormElements(); if( notification->getPayload().has("give_inventory_notification") - && !notification->getPayload()["give_inventory_notification"] ) + && notification->getPayload()["give_inventory_notification"].asBoolean() == false) { // This is an original inventory offer, so add a script floater LLScriptFloaterManager::instance().onAddNotification(notification->getID()); } else { + bool add_notif_to_im = notification->canLogToIM() && notification->hasFormElements(); + notification->setReusable(add_notif_to_im); LLUUID session_id; @@ -99,10 +100,6 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) LLUUID from_id = notification->getPayload()["from_id"]; session_id = LLHandlerUtil::spawnIMSession(name, from_id); - } - - if (add_notif_to_im) - { LLHandlerUtil::addNotifPanelToIM(notification); } @@ -120,33 +117,19 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) p.notif_id = notification->getID(); p.notification = notification; p.panel = notify_box; - p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); // we not save offer notifications to the syswell floater that should be added to the IM floater p.can_be_stored = !add_notif_to_im; LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) channel->addToast(p); - - // if we not add notification to IM - add it to notification well - if (!add_notif_to_im) - { - // send a signal to the counter manager - mNewNotificationSignal(); - } } if (notification->canLogToIM()) { // log only to file if notif panel can be embedded to IM and IM is opened - if (add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) - { - LLHandlerUtil::logToIMP2P(notification, true); - } - else - { - LLHandlerUtil::logToIMP2P(notification); - } + bool file_only = add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification); + LLHandlerUtil::logToIMP2P(notification, file_only); } } @@ -173,21 +156,6 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) } } -//-------------------------------------------------------------------------- - -void LLOfferHandler::onDeleteToast(LLToast* toast) -{ - if (!toast->getNotification()->canLogToIM() || !toast->getNotification()->hasFormElements()) - { - // send a signal to the counter manager - mDelNotificationSignal(); - } - - // send a signal to a listener to let him perform some action - // in this case listener is a SysWellWindow and it will remove a corresponding item from its list - mNotificationIDSignal(toast->getNotificationID()); -} - //-------------------------------------------------------------------------- void LLOfferHandler::onRejectToast(LLUUID& id) { diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 714f14963c..c74c967722 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -37,10 +37,6 @@ using namespace LLNotificationsUI; -static const std::string SCRIPT_DIALOG ("ScriptDialog"); -static const std::string SCRIPT_DIALOG_GROUP ("ScriptDialogGroup"); -static const std::string SCRIPT_LOAD_URL ("LoadWebPage"); - //-------------------------------------------------------------------------- LLScriptHandler::LLScriptHandler() : LLSysHandler("Notifications", "notify") @@ -87,7 +83,7 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) LLHandlerUtil::logToIMP2P(notification); } - if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) + if(notification->hasFormElements()) { LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID()); } @@ -106,9 +102,6 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) { channel->addToast(p); } - - // send a signal to the counter manager - mNewNotificationSignal(); } return false; @@ -117,7 +110,7 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) void LLScriptHandler::onDelete( LLNotificationPtr notification ) { - if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) + if(notification->hasFormElements()) { LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); } @@ -132,17 +125,11 @@ void LLScriptHandler::onDelete( LLNotificationPtr notification ) void LLScriptHandler::onDeleteToast(LLToast* toast) { - // send a signal to the counter manager - mDelNotificationSignal(); - // send a signal to a listener to let him perform some action // in this case listener is a SysWellWindow and it will remove a corresponding item from its list - mNotificationIDSignal(toast->getNotificationID()); - LLNotificationPtr notification = LLNotifications::getInstance()->find(toast->getNotificationID()); - if( notification && - (SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName()) ) + if( notification && notification->hasFormElements()) { LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); } diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index e8293ebe2b..18e0d9d0d2 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -433,13 +433,19 @@ BOOL LLIMWellWindow::ObjectRowPanel::handleRightMouseDown(S32 x, S32 y, MASK mas ////////////////////////////////////////////////////////////////////////// // PUBLIC METHODS +LLNotificationWellWindow::WellNotificationChannel::WellNotificationChannel(LLNotificationWellWindow* well_window) +: LLNotificationChannel(LLNotificationChannel::Params().name(well_window->getPathname())), + mWellWindow(well_window) +{ + connectToChannel("Notifications"); + connectToChannel("Group Notifications"); + connectToChannel("Offer"); +} + LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key) -: LLSysWellWindow(key) +: LLSysWellWindow(key) { - // init connections to the list's update events - connectListUpdaterToSignal("Notifications"); - connectListUpdaterToSignal("Group Notifications"); - connectListUpdaterToSignal("Offer"); + mNotificationUpdates.reset(new WellNotificationChannel(this)); } // static @@ -546,19 +552,6 @@ void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id) addItem(p); } -void LLNotificationWellWindow::connectListUpdaterToSignal(std::string notification_type) -{ - LLNotificationsUI::LLEventHandler* n_handler = dynamic_cast<LLNotificationsUI::LLEventHandler*>(LLNotifications::instance().getChannel(notification_type).get()); - if(n_handler) - { - n_handler->setNotificationIDCallback(boost::bind(&LLNotificationWellWindow::removeItemByID, this, _1)); - } - else - { - llwarns << "LLSysWellWindow::connectListUpdaterToSignal() - could not get a handler for '" << notification_type <<"' type of notifications" << llendl; - } -} - void LLNotificationWellWindow::onItemClick(LLSysWellItem* item) { LLUUID id = item->getID(); @@ -573,6 +566,12 @@ void LLNotificationWellWindow::onItemClose(LLSysWellItem* item) mChannel->killToastByNotificationID(id); } +void LLNotificationWellWindow::onAdd( LLNotificationPtr notify ) +{ + removeItemByID(notify->getID()); +} + + /************************************************************************/ @@ -866,4 +865,4 @@ bool LLIMWellWindow::confirmCloseAll(const LLSD& notification, const LLSD& respo return false; } -// EOF + diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 272e9cfcb1..caf30cfd67 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -34,6 +34,7 @@ #include "llscreenchannel.h" #include "llscrollcontainer.h" #include "llimview.h" +#include "llnotifications.h" #include "boost/shared_ptr.hpp" @@ -111,7 +112,7 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void setVisible(BOOL visible); - + /*virtual*/ void onAdd(LLNotificationPtr notify); // Operating with items void addItem(LLSysWellItem::Params p); @@ -119,6 +120,18 @@ public: void closeAll(); protected: + struct WellNotificationChannel : public LLNotificationChannel + { + WellNotificationChannel(LLNotificationWellWindow*); + void onAdd(LLNotificationPtr notify) + { + mWellWindow->removeItemByID(notify->getID()); + } + + LLNotificationWellWindow* mWellWindow; + }; + + LLNotificationChannelPtr mNotificationUpdates; /*virtual*/ const std::string& getAnchorViewName() { return NOTIFICATION_WELL_ANCHOR_NAME; } private: @@ -126,12 +139,8 @@ private: void initChannel(); void clearScreenChannels(); - void onStoreToast(LLPanel* info_panel, LLUUID id); - // connect counter and list updaters to the corresponding signals - void connectListUpdaterToSignal(std::string notification_type); - // Handlers void onItemClick(LLSysWellItem* item); void onItemClose(LLSysWellItem* item); diff --git a/indra/newview/lltoastgroupnotifypanel.h b/indra/newview/lltoastgroupnotifypanel.h index 3b8b31eac1..dfdc6ae559 100644 --- a/indra/newview/lltoastgroupnotifypanel.h +++ b/indra/newview/lltoastgroupnotifypanel.h @@ -47,9 +47,6 @@ class LLToastGroupNotifyPanel public: void close(); - static bool onNewNotification(const LLSD& notification); - - // Non-transient messages. You can specify non-default button // layouts (like one for script dialogs) by passing various // numbers in for "layout". diff --git a/indra/newview/lltoastscripttextbox.h b/indra/newview/lltoastscripttextbox.h index 8e69d8834d..7d33446248 100644 --- a/indra/newview/lltoastscripttextbox.h +++ b/indra/newview/lltoastscripttextbox.h @@ -39,8 +39,6 @@ class LLToastScriptTextbox public: void close(); - static bool onNewNotification(const LLSD& notification); - // Non-transient messages. You can specify non-default button // layouts (like one for script dialogs) by passing various // numbers in for "layout". -- cgit v1.2.3 From c2afd200a0d55c5137de6f89200a8d4b09ba8b6e Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 30 Mar 2012 18:36:43 -0700 Subject: CHUI-51 WIP notifications routing code cleanup object inventory offers don't increment system menu count added customizable merging behavior for duplicate "unique" notifications fixed overeager notification channels --- indra/llui/llnotifications.cpp | 43 ++++++++++++++++------------- indra/llui/llnotifications.h | 8 ++++++ indra/llui/llnotificationtemplate.h | 14 ++++++++++ indra/newview/llchiclet.cpp | 10 +++++-- indra/newview/llnotificationhandler.h | 33 +++++++++++----------- indra/newview/llnotificationhinthandler.cpp | 2 +- indra/newview/llscreenchannel.cpp | 9 +++++- 7 files changed, 80 insertions(+), 39 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index c45899a4bd..79135d2c60 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -246,7 +246,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica LLParamSDParser parser; parser.writeSD(mFormData, p.form_elements); - if (!mFormData.isArray()) + if (!mFormData.isArray() && !mFormData.isUndefined()) { // change existing contents to a one element array LLSD new_llsd_array = LLSD::emptyArray(); @@ -407,6 +407,7 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par mURLOption(p.url.option), mURLTarget(p.url.target), mUnique(p.unique.isProvided()), + mCombineBehavior(p.unique.combine), mPriority(p.priority), mPersist(p.persist), mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()), @@ -903,6 +904,10 @@ bool LLNotification::hasFormElements() const return mTemplatep->mForm->getNumElements() != 0; } +LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const +{ + return mTemplatep->mCombineBehavior; +} @@ -1242,22 +1247,25 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload) return false; } - // Update the existing unique notification with the data from this particular instance... - // This guarantees that duplicate notifications will be collapsed to the one - // most recently triggered - for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); - existing_it != mUniqueNotifications.end(); - ++existing_it) + if (pNotif->getCombineBehavior() == LLNotification::USE_NEWEST) { - LLNotificationPtr existing_notification = existing_it->second; - if (pNotif != existing_notification - && pNotif->isEquivalentTo(existing_notification)) + // Update the existing unique notification with the data from this particular instance... + // This guarantees that duplicate notifications will be collapsed to the one + // most recently triggered + for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); + existing_it != mUniqueNotifications.end(); + ++existing_it) { - // copy notification instance data over to oldest instance - // of this unique notification and update it - existing_notification->updateFrom(pNotif); - // then delete the new one - cancel(pNotif); + LLNotificationPtr existing_notification = existing_it->second; + if (pNotif != existing_notification + && pNotif->isEquivalentTo(existing_notification)) + { + // copy notification instance data over to oldest instance + // of this unique notification and update it + existing_notification->updateFrom(pNotif); + // then delete the new one + cancel(pNotif); + } } } @@ -1296,10 +1304,7 @@ void LLNotifications::createDefaultChannels() boost::bind(&LLNotifications::isVisibleByRules, this, _1))); mDefaultChannels.push_back(new LLNotificationChannel("Visible", "VisibilityRules", &LLNotificationFilters::includeEverything)); - - // create special persistent notification channel - // this isn't a leak, don't worry about the empty "new" - new LLPersistentNotificationChannel(); + mDefaultChannels.push_back(new LLPersistentNotificationChannel()); // connect action methods to these channels LLNotifications::instance().getChannel("Enabled")-> diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 344108ecbf..4e2b997156 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -297,6 +297,7 @@ LOG_CLASS(LLNotification); friend class LLNotifications; public: + // parameter object used to instantiate a new notification struct Params : public LLInitParam::Block<Params> { @@ -518,6 +519,13 @@ public: bool canLogToIM() const; bool hasFormElements() const; + typedef enum e_combine_behavior + { + USE_NEWEST, + USE_OLDEST + } ECombineBehavior; + + ECombineBehavior getCombineBehavior() const; const LLNotificationFormPtr getForm(); const LLDate getExpiration() const diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index 1df7205b23..8080acbf87 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -61,6 +61,17 @@ typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr; // from the appropriate local language directory). struct LLNotificationTemplate { + struct CombineBehaviorNames + : public LLInitParam::TypeValuesHelper<LLNotification::ECombineBehavior, CombineBehaviorNames> + { + static void declareValues() + { + declare("newest", LLNotification::USE_NEWEST); + declare("oldest", LLNotification::USE_OLDEST); + } + }; + + struct GlobalString : public LLInitParam::Block<GlobalString> { Mandatory<std::string> name, @@ -94,9 +105,11 @@ struct LLNotificationTemplate Optional<LLInitParam::Flag> dummy_val; public: Multiple<UniquenessContext> contexts; + Optional<LLNotification::ECombineBehavior, CombineBehaviorNames> combine; UniquenessConstraint() : contexts("context"), + combine("combine", LLNotification::USE_NEWEST), dummy_val("") {} }; @@ -249,6 +262,7 @@ struct LLNotificationTemplate // (used for things like progress indications, or repeating warnings // like "the grid is going down in N minutes") bool mUnique; + LLNotification::ECombineBehavior mCombineBehavior; // if we want to be unique only if a certain part of the payload or substitutions args // are constant specify the field names for the payload. The notification will only be // combined if all of the fields named in the context are identical in the diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 67519a3ca6..b4c70b6edb 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -393,9 +393,15 @@ void LLNotificationChiclet::setCounter(S32 counter) } -bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notify ) +bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification ) { - return !(notify->canLogToIM() && notify->hasFormElements()); + if( !(notification->canLogToIM() && notification->hasFormElements()) + && (!notification->getPayload().has("give_inventory_notification") + || notification->getPayload()["give_inventory_notification"])) + { + return true; + } + return false; } ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 419b8a14b6..21f3961d18 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -94,7 +94,7 @@ public: // base interface functions /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } /*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel) mChannel->killToastByNotificationID(p->getID());} virtual bool processNotification(const LLNotificationPtr& notify)=0; @@ -130,7 +130,7 @@ public: protected: bool processNotification(const LLNotificationPtr& p); - virtual void initChannel(); + /*virtual*/ void initChannel(); }; /** @@ -144,11 +144,12 @@ public: virtual ~LLTipHandler(); // base interface functions - virtual bool processNotification(const LLNotificationPtr& p); + /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: - virtual void onRejectToast(const LLUUID& id); - virtual void initChannel(); + /*virtual*/ void onRejectToast(const LLUUID& id); + /*virtual*/ void initChannel(); }; /** @@ -161,13 +162,13 @@ public: LLScriptHandler(); virtual ~LLScriptHandler(); - virtual void onDelete(LLNotificationPtr p); + /*virtual*/ void onDelete(LLNotificationPtr p); // base interface functions - virtual bool processNotification(const LLNotificationPtr& p); + /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: - virtual void onDeleteToast(LLToast* toast); - virtual void initChannel(); + /*virtual*/ void onDeleteToast(LLToast* toast); + /*virtual*/ void initChannel(); // own handlers void onRejectToast(LLUUID& id); @@ -184,7 +185,8 @@ public: virtual ~LLGroupHandler(); // base interface functions - virtual bool processNotification(const LLNotificationPtr& p); + /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: virtual void initChannel(); @@ -204,9 +206,7 @@ public: /*virtual*/ void onChange(LLNotificationPtr p); /*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } - - // base interface functions - virtual bool processNotification(const LLNotificationPtr& p); + /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: virtual void initChannel(); @@ -225,11 +225,12 @@ public: virtual ~LLOfferHandler(); // base interface functions + /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } /*virtual*/ void onDelete(LLNotificationPtr notification); - virtual bool processNotification(const LLNotificationPtr& p); + /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: - virtual void initChannel(); + /*virtual*/ void initChannel(); // own handlers void onRejectToast(LLUUID& id); @@ -246,7 +247,7 @@ public: virtual ~LLHintHandler() {} /*virtual*/ void onAdd(LLNotificationPtr p); - /*virtual*/ void onChange(LLNotificationPtr p); + /*virtual*/ void onLoad(LLNotificationPtr p); /*virtual*/ void onDelete(LLNotificationPtr p); }; diff --git a/indra/newview/llnotificationhinthandler.cpp b/indra/newview/llnotificationhinthandler.cpp index 47156a3915..271f418507 100644 --- a/indra/newview/llnotificationhinthandler.cpp +++ b/indra/newview/llnotificationhinthandler.cpp @@ -34,5 +34,5 @@ using namespace LLNotificationsUI; void LLHintHandler::onAdd(LLNotificationPtr p) { LLHints::show(p); } -void LLHintHandler::onChange(LLNotificationPtr p) { LLHints::show(p); } +void LLHintHandler::onLoad(LLNotificationPtr p) { LLHints::show(p); } void LLHintHandler::onDelete(LLNotificationPtr p) { LLHints::hide(p); } diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 5301955964..cc68c4c91a 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -251,7 +251,14 @@ void LLScreenChannel::addToast(const LLToast::Params& p) { bool store_toast = false, show_toast = false; - mDisplayToastsAlways ? show_toast = true : show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show); + if (mDisplayToastsAlways) + { + show_toast = true; + } + else + { + show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show); + } store_toast = !show_toast && p.can_be_stored && mCanStoreToasts; if(!show_toast && !store_toast) -- cgit v1.2.3 From 10503b13e0cd5b6f89d885982b72ed23ec131e85 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Thu, 5 Apr 2012 19:22:37 +0300 Subject: CHUI-77 WIP People panel layout change: filter pane moved inside the tab. --- .../newview/skins/default/xui/en/panel_people.xml | 587 ++++++++++----------- 1 file changed, 285 insertions(+), 302 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 98c7c49ff4..919661eff6 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -60,21 +60,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M <string name="AltMiniMapToolTipMsg" value="[REGION](Double-click to teleport, shift-drag to pan)"/> - <filter_editor - follows="left|top|right" - height="23" - layout="topleft" - left="10" - label="Filter" - max_length_chars="300" - name="filter_input" - text_color="Black" - text_pad_left="10" - top="3" - width="303" /> <tab_container follows="all" - height="383" + height="419" layout="topleft" left="3" name="tabs" @@ -82,10 +70,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M tab_min_width="70" tab_height="30" tab_position="top" - top_pad="10" + top="0" halign="center" width="319"> - <panel + <panel background_opaque="true" background_visible="true" bg_alpha_color="DkGray" @@ -99,13 +87,85 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="nearby_panel" top="0" width="313"> + <panel + follows="left|top|right" + height="27" + label="bottom_panel" + layout="topleft" + left="0" + name="nearby_buttons_panel" + top="0" + width="313"> + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="3" + label="Filter" + max_length_chars="300" + name="nearby_filter_input" + text_color="Black" + text_pad_left="10" + top="2" + width="167" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="10" + name="nearby_sort_btn" + top="1" + width="31" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Hierarchy_View_Disabled" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + name="nearby_view_btn" + top="1" + width="31" /> + <button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + name="nearby_add_btn" + top="1" + width="31" /> + <dnd_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TrashItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + left_pad="2" + layout="topleft" + name="nearby_del_btn" + top="1" + width="31"/> + </panel> <layout_stack clip="false" follows="all" height="355" layout="topleft" + left="0" mouse_opaque="false" orientation="vertical" + top_pad="0" width="313"> <layout_panel height="142" @@ -147,54 +207,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M width="306" /> </layout_panel> </layout_stack> - <panel - background_visible="true" - follows="left|right|bottom" - height="27" - label="bottom_panel" - layout="topleft" - left="3" - name="bottom_panel" - top_pad="0" - width="313"> - <menu_button - follows="bottom|left" - height="25" - image_hover_unselected="Toolbar_Left_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Left_Selected" - image_unselected="Toolbar_Left_Off" - layout="topleft" - left="0" - name="nearby_view_sort_btn" - tool_tip="Options" - top="1" - width="31" /> - <button - follows="bottom|left" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="1" - name="add_friend_btn" - tool_tip="Add selected Resident to your friends List" - width="31"> - <commit_callback - function="People.addFriend" /> - </button> - <icon - follows="bottom|left|right" - height="25" - image_name="Toolbar_Right_Off" - layout="topleft" - left_pad="1" - name="dummy_icon" - width="243" - /> - </panel> </panel> <panel background_opaque="true" @@ -210,6 +222,76 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="friends_panel" top="0" width="313"> + <panel + follows="left|top|right" + height="27" + label="bottom_panel" + layout="topleft" + left="0" + name="friends_buttons_panel" + top="0" + width="313"> + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="3" + label="Filter" + max_length_chars="300" + name="friends_filter_input" + text_color="Black" + text_pad_left="10" + top="2" + width="167" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="10" + name="friends_sort_btn" + top="1" + width="31" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Hierarchy_View_Disabled" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + name="friends_view_btn" + top="1" + width="31" /> + <button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + name="friends_add_btn" + top="1" + width="31" /> + <dnd_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TrashItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + left_pad="2" + layout="topleft" + name="friends_del_btn" + top="1" + width="31"/> + </panel> <accordion background_visible="true" bg_alpha_color="DkGray2" @@ -219,7 +301,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left="3" name="friends_accordion" - top="0" + top_pad="0" width="307"> <accordion_tab layout="topleft" @@ -257,153 +339,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M width="307" /> </accordion_tab> </accordion> - <panel - background_visible="true" - follows="left|right|bottom" - height="27" - label="bottom_panel" - layout="topleft" - left="3" - name="bottom_panel" - top_pad="0" - width="313"> - - <layout_stack - animate="false" - border_size="0" - follows="left|right|bottom" - height="25" - layout="topleft" - orientation="horizontal" - top_pad="1" - left="0" - name="bottom_panel" - width="308"> - <layout_panel - auto_resize="false" - height="25" - layout="topleft" - name="options_gear_btn_panel" - width="32"> - <menu_button - follows="bottom|left" - tool_tip="Show additional options" - height="25" - image_hover_unselected="Toolbar_Left_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Left_Selected" - image_unselected="Toolbar_Left_Off" - layout="topleft" - left="0" - name="friends_viewsort_btn" - top="0" - width="31" /> - </layout_panel> - <layout_panel - auto_resize="false" - height="25" - layout="topleft" - name="add_btn_panel" - width="32"> - <button - follows="bottom|left" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left="0" - name="add_btn" - tool_tip="Offer friendship to a Resident" - top="0" - width="31" /> - </layout_panel> - <layout_panel - auto_resize="true" - height="25" - layout="topleft" - name="dummy_panel" - width="210"> - <icon - follows="bottom|left|right" - height="25" - image_name="Toolbar_Middle_Off" - layout="topleft" - left="0" - top="0" - name="dummy_icon" - width="210" /> - </layout_panel> - <layout_panel - auto_resize="false" - height="25" - layout="topleft" - name="trash_btn_panel" - width="31"> - <dnd_button - follows="bottom|left" - height="25" - image_hover_unselected="Toolbar_Right_Over" - image_overlay="TrashItem_Off" - image_selected="Toolbar_Right_Selected" - image_unselected="Toolbar_Right_Off" - left="0" - layout="topleft" - name="del_btn" - tool_tip="Remove selected person from your Friends list" - top="0" - width="31"/> - </layout_panel> - </layout_stack><!-- - - <button - follows="bottom|left" - tool_tip="Options" - height="25" - image_hover_unselected="Toolbar_Left_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Left_Selected" - image_unselected="Toolbar_Left_Off" - layout="topleft" - left="0" - name="friends_viewsort_btn" - top="1" - width="31" /> - <button - follows="bottom|left" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="1" - name="add_btn" - tool_tip="Offer friendship to a Resident" - width="31" /> - <icon - follows="bottom|left|right" - height="25" - image_name="Toolbar_Middle_Off" - layout="topleft" - left_pad="1" - name="dummy_icon" - width="209" - /> - <button - follows="bottom|left" - height="25" - image_hover_unselected="Toolbar_Right_Over" - image_overlay="TrashItem_Off" - image_selected="Toolbar_Right_Selected" - image_unselected="Toolbar_Right_Off" - layout="topleft" - left_pad="1" - name="del_btn" - tool_tip="Remove selected person from your Friends list" - width="31" /> - --></panel> <text follows="all" height="450" @@ -431,72 +366,97 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M *NOTE: no_groups_msg & group_list attributes are not defined as translatable in VLT. See EXT-5931 Values are set from appropriate strings at the top of file via LLPeoplePanel::postBuild() --> - <group_list - allow_select="true" - follows="all" - height="356" - layout="topleft" - left="3" - name="group_list" - top="0" - width="307" /> <panel - background_visible="true" - follows="left|right|bottom" + follows="left|top|right" height="27" label="bottom_panel" layout="topleft" left="0" - name="bottom_panel" - top_pad="0" + name="groups_buttons_panel" + top="0" width="313"> - <menu_button - follows="bottom|left" - tool_tip="Options" - height="25" - image_hover_unselected="Toolbar_Left_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Left_Selected" - image_unselected="Toolbar_Left_Off" - layout="topleft" - left="3" - name="groups_viewsort_btn" - top="1" - width="31" /> - <button - follows="bottom|left" + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="3" + label="Filter" + max_length_chars="300" + name="groups_filter_input" + text_color="Black" + text_pad_left="10" + top="2" + width="134" /> + <menu_button + follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="10" + name="groups_sort_btn" + top="1" + width="31" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Hierarchy_View_Disabled" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" - left_pad="1" - name="plus_btn" - tool_tip="Join group/Create new group" + left_pad="2" + name="groups_view_btn" + top="1" width="31" /> <button - follows="bottom|left" + follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" image_overlay="Activate_Checkmark" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" - left_pad="1" - name="activate_btn" - tool_tip="Activate selected group" + left_pad="2" + name="groups_activate_btn" + top="1" width="31" /> - <icon - follows="bottom|left|right" - height="25" - image_name="Toolbar_Right_Off" - layout="topleft" - left_pad="1" - name="dummy_icon" - width="212" - /> + <button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + name="groups_add_btn" + top="1" + width="31" /> + <dnd_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TrashItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + left_pad="2" + layout="topleft" + name="groups_del_btn" + top="1" + width="31"/> </panel> + <group_list + allow_select="true" + follows="all" + height="356" + layout="topleft" + left="3" + name="group_list" + top_pad="0" + width="307" /> </panel> <panel background_opaque="true" @@ -512,64 +472,87 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="recent_panel" top="0" width="313"> - <avatar_list - allow_select="true" - follows="all" - height="356" - layout="topleft" - left="3" - multi_select="true" - name="avatar_list" - show_last_interaction_time="true" - top="0" - width="307" /> <panel - background_visible="true" - follows="left|right|bottom" + follows="left|top|right" height="27" label="bottom_panel" layout="topleft" - left="3" - name="bottom_panel" - top_pad="0" + left="0" + name="recent_buttons_panel" + top="0" width="313"> - <menu_button - follows="bottom|left" - tool_tip="Options" - height="25" - image_hover_unselected="Toolbar_Left_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Left_Selected" - image_unselected="Toolbar_Left_Off" - layout="topleft" - name="recent_viewsort_btn" - top="1" - width="31" /> - <button - follows="bottom|left" + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="3" + label="Filter" + max_length_chars="300" + name="recent_filter_input" + text_color="Black" + text_pad_left="10" + top="2" + width="167" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="10" + name="recent_sort_btn" + top="1" + width="31" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Hierarchy_View_Disabled" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + name="recent_view_btn" + top="1" + width="31" /> + <button + follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" image_overlay="AddItem_Off" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" - left_pad="1" - name="add_friend_btn" - tool_tip="Add selected Resident to your friends List" - width="31"> - <commit_callback - function="People.addFriend" /> - </button> - <icon - follows="bottom|left|right" - height="25" - image_name="Toolbar_Right_Off" - layout="topleft" - left_pad="1" - name="dummy_icon" - width="244" - /> + left_pad="2" + name="recent_add_btn" + top="1" + width="31" /> + <dnd_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TrashItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + left_pad="2" + layout="topleft" + name="recent_del_btn" + top="1" + width="31"/> </panel> + <avatar_list + allow_select="true" + follows="all" + height="356" + layout="topleft" + left="3" + multi_select="true" + name="avatar_list" + show_last_interaction_time="true" + top_pad="0" + width="307" /> </panel> </tab_container> <panel -- cgit v1.2.3 From e5c0cfdc5a0dd20afbec047049cbd920686cb55d Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Wed, 4 Apr 2012 22:04:38 +0300 Subject: CHUI-78 WIP Fixed parsing of menu_button.menu_position XUI parameter. --- indra/llui/llmenubutton.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index e2396e7fb2..84e63911a3 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -53,7 +53,7 @@ public: { // filename for it's toggleable menu Optional<std::string> menu_filename; - Optional<EMenuPosition> position; + Optional<EMenuPosition, MenuPositions> position; Params(); }; -- cgit v1.2.3 From 69cf10a1e9b969a1c87473a8b153281dc60e7b56 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Thu, 5 Apr 2012 17:29:25 +0300 Subject: CHUI-78 WIP Renamamed menu_button.position XUI attribute to menu_position for consistency with menu_filename. --- indra/llui/llmenubutton.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 50d59f79f4..cfae524f3b 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -44,8 +44,9 @@ void LLMenuButton::MenuPositions::declareValues() LLMenuButton::Params::Params() : menu_filename("menu_filename"), - position("position", MP_BOTTOM_LEFT) + position("menu_position", MP_BOTTOM_LEFT) { + addSynonym(position, "position"); } -- cgit v1.2.3 From 177c1f80bc132fdad4e46009b074c0609454332f Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Thu, 5 Apr 2012 20:37:28 +0300 Subject: CHUI-78 WIP Enabled LLMenuButton to manage its menu's lifetime. --- indra/llui/llmenubutton.cpp | 53 +++++++++++++++++++++++++++++++-------------- indra/llui/llmenubutton.h | 9 +++++++- 2 files changed, 45 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index cfae524f3b..2f5e29c36e 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -53,25 +53,18 @@ LLMenuButton::Params::Params() LLMenuButton::LLMenuButton(const LLMenuButton::Params& p) : LLButton(p), mIsMenuShown(false), - mMenuPosition(p.position) + mMenuPosition(p.position), + mOwnMenu(false) { std::string menu_filename = p.menu_filename; - if (!menu_filename.empty()) - { - LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); - if (!menu) - { - llwarns << "Error loading menu_button menu" << llendl; - return; - } - - menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2)); - - mMenuHandle = menu->getHandle(); + setMenu(menu_filename, mMenuPosition); + updateMenuOrigin(); +} - updateMenuOrigin(); - } +LLMenuButton::~LLMenuButton() +{ + cleanup(); } boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb ) @@ -95,12 +88,32 @@ LLToggleableMenu* LLMenuButton::getMenu() return dynamic_cast<LLToggleableMenu*>(mMenuHandle.get()); } -void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/) +void LLMenuButton::setMenu(const std::string& menu_filename, EMenuPosition position /*MP_TOP_LEFT*/) +{ + if (menu_filename.empty()) + { + return; + } + + LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (!menu) + { + llwarns << "Error loading menu_button menu" << llendl; + return; + } + + setMenu(menu, position, true); +} + +void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/, bool take_ownership /*false*/) { if (!menu) return; + cleanup(); // destroy the previous memnu if we own it + mMenuHandle = menu->getHandle(); mMenuPosition = position; + mOwnMenu = take_ownership; menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2)); } @@ -212,3 +225,11 @@ void LLMenuButton::onMenuVisibilityChange(const LLSD& param) mIsMenuShown = false; } } + +void LLMenuButton::cleanup() +{ + if (mMenuHandle.get() && mOwnMenu) + { + mMenuHandle.get()->die(); + } +} diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index 84e63911a3..67ec1983b3 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -34,6 +34,8 @@ class LLToggleableMenu; class LLMenuButton : public LLButton { + LOG_CLASS(LLMenuButton); + public: typedef enum e_menu_position { @@ -68,13 +70,15 @@ public: void hideMenu(); LLToggleableMenu* getMenu(); - void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT); + void setMenu(const std::string& menu_filename, EMenuPosition position = MP_TOP_LEFT); + void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT, bool take_ownership = false); void setMenuPosition(EMenuPosition position) { mMenuPosition = position; } protected: friend class LLUICtrlFactory; LLMenuButton(const Params&); + ~LLMenuButton(); void toggleMenu(); void updateMenuOrigin(); @@ -82,11 +86,14 @@ protected: void onMenuVisibilityChange(const LLSD& param); private: + void cleanup(); + LLHandle<LLView> mMenuHandle; bool mIsMenuShown; EMenuPosition mMenuPosition; S32 mX; S32 mY; + bool mOwnMenu; // true if we manage the menu lifetime }; -- cgit v1.2.3 From 2dc032e3e582d39a04c40b7cfb3366424491b491 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Thu, 5 Apr 2012 22:56:18 +0300 Subject: CHUI-78 WIP Added drop-down menus and connected callbacks to the new view/sort/add/remove buttons. --- indra/llui/llmenubutton.cpp | 5 + indra/newview/llpanelpeople.cpp | 137 +++++-------------- indra/newview/llpanelpeople.h | 16 +-- .../skins/default/xui/en/menu_group_plus.xml | 4 +- .../default/xui/en/menu_people_friends_sort.xml | 26 ++++ .../default/xui/en/menu_people_friends_view.xml | 26 ++++ .../xui/en/menu_people_friends_view_sort.xml | 47 ------- .../default/xui/en/menu_people_groups_view.xml | 17 +++ .../xui/en/menu_people_groups_view_sort.xml | 26 ---- .../default/xui/en/menu_people_nearby_sort.xml | 36 +++++ .../default/xui/en/menu_people_nearby_view.xml | 31 +++++ .../xui/en/menu_people_nearby_view_sort.xml | 57 -------- .../default/xui/en/menu_people_recent_sort.xml | 26 ++++ .../default/xui/en/menu_people_recent_view.xml | 18 +++ .../xui/en/menu_people_recent_view_sort.xml | 39 ------ .../newview/skins/default/xui/en/panel_people.xml | 152 ++++++++++++++++----- 16 files changed, 339 insertions(+), 324 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/menu_people_friends_sort.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_friends_view.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_groups_view.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_nearby_view.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_recent_sort.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_recent_view.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml (limited to 'indra') diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 2f5e29c36e..98f7e0540c 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -153,6 +153,11 @@ BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask) void LLMenuButton::toggleMenu() { + if (mValidateSignal && !(*mValidateSignal)(this, LLSD())) + { + return; + } + if(mMenuHandle.isDead()) return; LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get()); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 9c46f04abf..238834aa92 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -501,17 +501,38 @@ LLPanelPeople::LLPanelPeople() mNearbyList(NULL), mRecentList(NULL), mGroupList(NULL), - mNearbyGearButton(NULL), - mFriendsGearButton(NULL), - mGroupsGearButton(NULL), - mRecentGearButton(NULL), mMiniMap(NULL) { mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::updateFriendList, this)); mNearbyListUpdater = new LLNearbyListUpdater(boost::bind(&LLPanelPeople::updateNearbyList, this)); mRecentListUpdater = new LLRecentListUpdater(boost::bind(&LLPanelPeople::updateRecentList, this)); mButtonsUpdater = new LLButtonsUpdater(boost::bind(&LLPanelPeople::updateButtons, this)); - mCommitCallbackRegistrar.add("People.addFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this)); + + mCommitCallbackRegistrar.add("People.AddFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this)); + mCommitCallbackRegistrar.add("People.AddFriendWizard", boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked, this)); + mCommitCallbackRegistrar.add("People.DelFriend", boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked, this)); + mCommitCallbackRegistrar.add("People.Group.Activate", boost::bind(&LLPanelPeople::onActivateButtonClicked, this)); + mCommitCallbackRegistrar.add("People.Group.Minus", boost::bind(&LLPanelPeople::onGroupMinusButtonClicked, this)); + mCommitCallbackRegistrar.add("People.ViewProfile", boost::bind(&LLPanelPeople::onViewProfileButtonClicked, this)); + mCommitCallbackRegistrar.add("People.GroupInfo", boost::bind(&LLPanelPeople::onGroupInfoButtonClicked, this)); + mCommitCallbackRegistrar.add("People.Chat", boost::bind(&LLPanelPeople::onChatButtonClicked, this)); + mCommitCallbackRegistrar.add("People.IM", boost::bind(&LLPanelPeople::onImButtonClicked, this)); + mCommitCallbackRegistrar.add("People.Call", boost::bind(&LLPanelPeople::onCallButtonClicked, this)); + mCommitCallbackRegistrar.add("People.GroupCall", boost::bind(&LLPanelPeople::onGroupCallButtonClicked, this)); + mCommitCallbackRegistrar.add("People.Teleport", boost::bind(&LLPanelPeople::onTeleportButtonClicked, this)); + mCommitCallbackRegistrar.add("People.Share", boost::bind(&LLPanelPeople::onShareButtonClicked, this)); + + mCommitCallbackRegistrar.add("People.Group.Plus.Action", boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked, this, _2)); + mCommitCallbackRegistrar.add("People.Friends.ViewSort.Action", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked, this, _2)); + mCommitCallbackRegistrar.add("People.Nearby.ViewSort.Action", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked, this, _2)); + mCommitCallbackRegistrar.add("People.Groups.ViewSort.Action", boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked, this, _2)); + mCommitCallbackRegistrar.add("People.Recent.ViewSort.Action", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked, this, _2)); + + mEnableCallbackRegistrar.add("People.Friends.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck, this, _2)); + mEnableCallbackRegistrar.add("People.Recent.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck, this, _2)); + mEnableCallbackRegistrar.add("People.Nearby.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck, this, _2)); + + mEnableCallbackRegistrar.add("People.Group.Plus.Validate", boost::bind(&LLPanelPeople::onGroupPlusButtonValidate, this)); } LLPanelPeople::~LLPanelPeople() @@ -525,13 +546,6 @@ LLPanelPeople::~LLPanelPeople() { LLVoiceClient::getInstance()->removeObserver(this); } - - if (mGroupPlusMenuHandle.get()) mGroupPlusMenuHandle.get()->die(); - if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); - if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); - if (mGroupsViewSortMenuHandle.get()) mGroupsViewSortMenuHandle.get()->die(); - if (mRecentViewSortMenuHandle.get()) mRecentViewSortMenuHandle.get()->die(); - } void LLPanelPeople::onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LLSD& param, LLAvatarList* avatar_list) @@ -601,14 +615,6 @@ BOOL LLPanelPeople::postBuild() setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false); setSortOrder(mNearbyList, (ESortOrder)gSavedSettings.getU32("NearbyPeopleSortOrder"), false); - LLPanel* groups_panel = getChild<LLPanel>(GROUP_TAB_NAME); - groups_panel->childSetAction("activate_btn", boost::bind(&LLPanelPeople::onActivateButtonClicked, this)); - groups_panel->childSetAction("plus_btn", boost::bind(&LLPanelPeople::onGroupPlusButtonClicked, this)); - - LLPanel* friends_panel = getChild<LLPanel>(FRIENDS_TAB_NAME); - friends_panel->childSetAction("add_btn", boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked, this)); - friends_panel->childSetAction("del_btn", boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked, this)); - mOnlineFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1)); mAllFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1)); mNearbyList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1)); @@ -637,70 +643,9 @@ BOOL LLPanelPeople::postBuild() accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _1, _2, mOnlineFriendList)); - buttonSetAction("view_profile_btn", boost::bind(&LLPanelPeople::onViewProfileButtonClicked, this)); - buttonSetAction("group_info_btn", boost::bind(&LLPanelPeople::onGroupInfoButtonClicked, this)); - buttonSetAction("chat_btn", boost::bind(&LLPanelPeople::onChatButtonClicked, this)); - buttonSetAction("im_btn", boost::bind(&LLPanelPeople::onImButtonClicked, this)); - buttonSetAction("call_btn", boost::bind(&LLPanelPeople::onCallButtonClicked, this)); - buttonSetAction("group_call_btn", boost::bind(&LLPanelPeople::onGroupCallButtonClicked, this)); - buttonSetAction("teleport_btn", boost::bind(&LLPanelPeople::onTeleportButtonClicked, this)); - buttonSetAction("share_btn", boost::bind(&LLPanelPeople::onShareButtonClicked, this)); - // Must go after setting commit callback and initializing all pointers to children. mTabContainer->selectTabByName(NEARBY_TAB_NAME); - // Create menus. - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - - registrar.add("People.Group.Plus.Action", boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked, this, _2)); - registrar.add("People.Group.Minus.Action", boost::bind(&LLPanelPeople::onGroupMinusButtonClicked, this)); - registrar.add("People.Friends.ViewSort.Action", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked, this, _2)); - registrar.add("People.Nearby.ViewSort.Action", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked, this, _2)); - registrar.add("People.Groups.ViewSort.Action", boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked, this, _2)); - registrar.add("People.Recent.ViewSort.Action", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked, this, _2)); - - enable_registrar.add("People.Group.Minus.Enable", boost::bind(&LLPanelPeople::isRealGroup, this)); - enable_registrar.add("People.Friends.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck, this, _2)); - enable_registrar.add("People.Recent.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck, this, _2)); - enable_registrar.add("People.Nearby.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck, this, _2)); - - mNearbyGearButton = getChild<LLMenuButton>("nearby_view_sort_btn"); - mFriendsGearButton = getChild<LLMenuButton>("friends_viewsort_btn"); - mGroupsGearButton = getChild<LLMenuButton>("groups_viewsort_btn"); - mRecentGearButton = getChild<LLMenuButton>("recent_viewsort_btn"); - - LLMenuGL* plus_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mGroupPlusMenuHandle = plus_menu->getHandle(); - - LLToggleableMenu* nearby_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_nearby_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(nearby_view_sort) - { - mNearbyViewSortMenuHandle = nearby_view_sort->getHandle(); - mNearbyGearButton->setMenu(nearby_view_sort); - } - - LLToggleableMenu* friend_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_friends_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(friend_view_sort) - { - mFriendsViewSortMenuHandle = friend_view_sort->getHandle(); - mFriendsGearButton->setMenu(friend_view_sort); - } - - LLToggleableMenu* group_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(group_view_sort) - { - mGroupsViewSortMenuHandle = group_view_sort->getHandle(); - mGroupsGearButton->setMenu(group_view_sort); - } - - LLToggleableMenu* recent_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_recent_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(recent_view_sort) - { - mRecentViewSortMenuHandle = recent_view_sort->getHandle(); - mRecentGearButton->setMenu(recent_view_sort); - } - LLVoiceClient::getInstance()->addObserver(this); // call this method in case some list is empty and buttons can be in inconsistent state @@ -835,13 +780,6 @@ void LLPanelPeople::buttonSetEnabled(const std::string& btn_name, bool enabled) button->setEnabled(enabled); } -void LLPanelPeople::buttonSetAction(const std::string& btn_name, const commit_signal_t::slot_type& cb) -{ - // To make sure we're referencing the right widget (a child of the button bar). - LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name); - button->setClickedCallback(cb); -} - void LLPanelPeople::updateButtons() { std::string cur_tab = getActiveTabName(); @@ -877,7 +815,7 @@ void LLPanelPeople::updateButtons() LLPanel* groups_panel = mTabContainer->getCurrentPanel(); groups_panel->getChildView("activate_btn")->setEnabled(item_selected && !cur_group_active); // "none" or a non-active group selected - groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); + groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected } else { @@ -893,10 +831,12 @@ void LLPanelPeople::updateButtons() LLPanel* cur_panel = mTabContainer->getCurrentPanel(); if (cur_panel) { - cur_panel->getChildView("add_friend_btn")->setEnabled(!is_friend); + if (cur_panel->hasChild("add_friend_btn", TRUE)) + cur_panel->getChildView("add_friend_btn")->setEnabled(item_selected && !is_friend); + if (friends_tab_active) { - cur_panel->getChildView("del_btn")->setEnabled(multiple_selected); + cur_panel->getChildView("friends_del_btn")->setEnabled(multiple_selected); } } } @@ -1031,11 +971,6 @@ void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save } } -bool LLPanelPeople::isRealGroup() -{ - return getCurrentItemID() != LLUUID::null; -} - void LLPanelPeople::onFilterEdit(const std::string& search_string) { mFilterSubStringOrig = search_string; @@ -1226,19 +1161,15 @@ void LLPanelPeople::onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAv LLAvatarActions::requestFriendshipDialog(ids[0], names[0].getCompleteName()); } -void LLPanelPeople::onGroupPlusButtonClicked() +bool LLPanelPeople::onGroupPlusButtonValidate() { if (!gAgent.canJoinGroups()) { LLNotificationsUtil::add("JoinedTooManyGroups"); - return; + return false; } - LLMenuGL* plus_menu = (LLMenuGL*)mGroupPlusMenuHandle.get(); - if (!plus_menu) - return; - - showGroupMenu(plus_menu); + return true; } void LLPanelPeople::onGroupMinusButtonClicked() diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 46c58cd139..684dcdeb6d 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -82,7 +82,6 @@ private: void getCurrentItemIDs(uuid_vec_t& selected_uuids) const; void buttonSetVisible(std::string btn_name, BOOL visible); void buttonSetEnabled(const std::string& btn_name, bool enabled); - void buttonSetAction(const std::string& btn_name, const commit_signal_t::slot_type& cb); void showGroupMenu(LLMenuGL* menu); void setSortOrder(LLAvatarList* list, ESortOrder order, bool save = true); @@ -104,7 +103,7 @@ private: void onActivateButtonClicked(); void onAvatarListDoubleClicked(LLUICtrl* ctrl); void onAvatarListCommitted(LLAvatarList* list); - void onGroupPlusButtonClicked(); + bool onGroupPlusButtonValidate(); void onGroupMinusButtonClicked(); void onGroupPlusMenuItemClicked(const LLSD& userdata); @@ -113,8 +112,6 @@ private: void onGroupsViewSortMenuItemClicked(const LLSD& userdata); void onRecentViewSortMenuItemClicked(const LLSD& userdata); - //returns false only if group is "none" - bool isRealGroup(); bool onFriendsViewSortMenuItemCheck(const LLSD& userdata); bool onRecentViewSortMenuItemCheck(const LLSD& userdata); bool onNearbyViewSortMenuItemCheck(const LLSD& userdata); @@ -144,22 +141,11 @@ private: LLGroupList* mGroupList; LLNetMap* mMiniMap; - LLHandle<LLView> mGroupPlusMenuHandle; - LLHandle<LLView> mNearbyViewSortMenuHandle; - LLHandle<LLView> mFriendsViewSortMenuHandle; - LLHandle<LLView> mGroupsViewSortMenuHandle; - LLHandle<LLView> mRecentViewSortMenuHandle; - Updater* mFriendListUpdater; Updater* mNearbyListUpdater; Updater* mRecentListUpdater; Updater* mButtonsUpdater; - LLMenuButton* mNearbyGearButton; - LLMenuButton* mFriendsGearButton; - LLMenuButton* mGroupsGearButton; - LLMenuButton* mRecentGearButton; - std::string mFilterSubString; std::string mFilterSubStringOrig; }; diff --git a/indra/newview/skins/default/xui/en/menu_group_plus.xml b/indra/newview/skins/default/xui/en/menu_group_plus.xml index fce7414d80..eca9e7f3c9 100644 --- a/indra/newview/skins/default/xui/en/menu_group_plus.xml +++ b/indra/newview/skins/default/xui/en/menu_group_plus.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<menu name="menu_group_plus" +<toggleable_menu name="menu_group_plus" left="0" bottom="0" visible="false" mouse_opaque="false"> <menu_item_call name="item_join" label="Join Group..."> @@ -8,4 +8,4 @@ <menu_item_call name="item_new" label="New Group..."> <menu_item_call.on_click function="People.Group.Plus.Action" userdata="new_group" /> </menu_item_call> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_sort.xml new file mode 100644 index 0000000000..532e295386 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_friends_sort.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_group_plus" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_check + label="Sort by Name" + name="sort_name"> + <menu_item_check.on_click + function="People.Friends.ViewSort.Action" + parameter="sort_name" /> + <menu_item_check.on_check + function="People.Friends.ViewSort.CheckItem" + parameter="sort_name" /> + </menu_item_check> + <menu_item_check + label="Sort by Status" + name="sort_status"> + <menu_item_check.on_click + function="People.Friends.ViewSort.Action" + parameter="sort_status" /> + <menu_item_check.on_check + function="People.Friends.ViewSort.CheckItem" + parameter="sort_status" /> + </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml new file mode 100644 index 0000000000..be23e91587 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_group_plus" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_check name="view_icons" label="View People Icons"> + <menu_item_check.on_click + function="People.Friends.ViewSort.Action" + parameter="view_icons" /> + <menu_item_check.on_check + function="CheckControl" + parameter="FriendsListShowIcons" /> + </menu_item_check> + <menu_item_check name="view_permissions" label="View Permissions Granted"> + <menu_item_check.on_click + function="People.Friends.ViewSort.Action" + parameter="view_permissions" /> + <menu_item_check.on_check + function="CheckControl" + parameter="FriendsListShowPermissions" /> + </menu_item_check> + <menu_item_separator layout="topleft" /> + <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> + <menu_item_call.on_click function="People.Friends.ViewSort.Action" parameter="panel_block_list_sidetray" /> + </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml deleted file mode 100644 index b452f96e7a..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml +++ /dev/null @@ -1,47 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu - name="menu_group_plus" - left="0" bottom="0" visible="false" - mouse_opaque="false"> - <menu_item_check - label="Sort by Name" - name="sort_name"> - <menu_item_check.on_click - function="People.Friends.ViewSort.Action" - parameter="sort_name" /> - <menu_item_check.on_check - function="People.Friends.ViewSort.CheckItem" - parameter="sort_name" /> - </menu_item_check> - <menu_item_check - label="Sort by Status" - name="sort_status"> - <menu_item_check.on_click - function="People.Friends.ViewSort.Action" - parameter="sort_status" /> - <menu_item_check.on_check - function="People.Friends.ViewSort.CheckItem" - parameter="sort_status" /> - </menu_item_check> - <menu_item_separator layout="topleft" /> - <menu_item_check name="view_icons" label="View People Icons"> - <menu_item_check.on_click - function="People.Friends.ViewSort.Action" - parameter="view_icons" /> - <menu_item_check.on_check - function="CheckControl" - parameter="FriendsListShowIcons" /> - </menu_item_check> - <menu_item_check name="view_permissions" label="View Permissions Granted"> - <menu_item_check.on_click - function="People.Friends.ViewSort.Action" - parameter="view_permissions" /> - <menu_item_check.on_check - function="CheckControl" - parameter="FriendsListShowPermissions" /> - </menu_item_check> - <menu_item_separator layout="topleft" /> - <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> - <menu_item_call.on_click function="People.Friends.ViewSort.Action" parameter="panel_block_list_sidetray" /> - </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view.xml new file mode 100644 index 0000000000..73f79f1e70 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_groups_view.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_group_plus" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_check + label="Display Group Icons" + layout="topleft" + name="Display Group Icons"> + <menu_item_check.on_click + function="People.Groups.ViewSort.Action" + parameter="show_icons" /> + <menu_item_check.on_check + function="CheckControl" + parameter="GroupListShowIcons" /> + </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml deleted file mode 100644 index c710fe3b9b..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu - name="menu_group_plus" - left="0" bottom="0" visible="false" - mouse_opaque="false"> - <menu_item_check - label="Display Group Icons" - layout="topleft" - name="Display Group Icons"> - <menu_item_check.on_click - function="People.Groups.ViewSort.Action" - parameter="show_icons" /> - <menu_item_check.on_check - function="CheckControl" - parameter="GroupListShowIcons" /> - </menu_item_check> - <menu_item_call - label="Leave Selected Group" - layout="topleft" - name="Leave Selected Group"> - <menu_item_call.on_click - function="People.Group.Minus.Action"/> - <menu_item_call.on_enable - function="People.Group.Minus.Enable"/> - </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml new file mode 100644 index 0000000000..cf7f4f4fce --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_group_plus" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_check + label="Sort by Recent Speakers" + name="sort_by_recent_speakers"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="sort_by_recent_speakers"/> + <menu_item_check.on_check + function="People.Nearby.ViewSort.CheckItem" + parameter="sort_by_recent_speakers"/> + </menu_item_check> + <menu_item_check + label="Sort by Name" + name="sort_name"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="sort_name"/> + <menu_item_check.on_check + function="People.Nearby.ViewSort.CheckItem" + parameter="sort_name"/> + </menu_item_check> + <menu_item_check + label="Sort by Distance" + name="sort_distance"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="sort_distance"/> + <menu_item_check.on_check + function="People.Nearby.ViewSort.CheckItem" + parameter="sort_distance"/> + </menu_item_check> + </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml new file mode 100644 index 0000000000..187dd3bcb5 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_group_plus" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_check name="view_icons" label="View People Icons"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="view_icons" /> + <menu_item_check.on_check + function="CheckControl" + parameter="NearbyListShowIcons" /> + </menu_item_check> + <menu_item_check name ="view_map" label="View Map"> + <menu_item_check.on_check + function="CheckControl" + parameter="NearbyListShowMap" /> + <menu_item_check.on_click + function="ToggleControl" + parameter="NearbyListShowMap" /> + </menu_item_check> + <menu_item_separator + layout="topleft" /> + <menu_item_call + name="show_blocked_list" + label="Show Blocked Residents & Objects"> + <menu_item_call.on_click + function="People.Nearby.ViewSort.Action" + userdata="panel_block_list_sidetray" /> + </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml deleted file mode 100644 index 614dd693c5..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu - name="menu_group_plus" - left="0" bottom="0" visible="false" - mouse_opaque="false"> - <menu_item_check - label="Sort by Recent Speakers" - name="sort_by_recent_speakers"> - <menu_item_check.on_click - function="People.Nearby.ViewSort.Action" - parameter="sort_by_recent_speakers"/> - <menu_item_check.on_check - function="People.Nearby.ViewSort.CheckItem" - parameter="sort_by_recent_speakers"/> - </menu_item_check> - <menu_item_check - label="Sort by Name" - name="sort_name"> - <menu_item_check.on_click - function="People.Nearby.ViewSort.Action" - parameter="sort_name"/> - <menu_item_check.on_check - function="People.Nearby.ViewSort.CheckItem" - parameter="sort_name"/> - </menu_item_check> - <menu_item_check - label="Sort by Distance" - name="sort_distance"> - <menu_item_check.on_click - function="People.Nearby.ViewSort.Action" - parameter="sort_distance"/> - <menu_item_check.on_check - function="People.Nearby.ViewSort.CheckItem" - parameter="sort_distance"/> - </menu_item_check> - <menu_item_separator layout="topleft" /> - <menu_item_check name="view_icons" label="View People Icons"> - <menu_item_check.on_click - function="People.Nearby.ViewSort.Action" - parameter="view_icons" /> - <menu_item_check.on_check - function="CheckControl" - parameter="NearbyListShowIcons" /> - </menu_item_check> - <menu_item_check name ="view_map" label="View Map"> - <menu_item_check.on_check - function="CheckControl" - parameter="NearbyListShowMap" /> - <menu_item_check.on_click - function="ToggleControl" - parameter="NearbyListShowMap" /> - </menu_item_check> - <menu_item_separator layout="topleft" /> - <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> - <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="panel_block_list_sidetray" /> - </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_sort.xml new file mode 100644 index 0000000000..f14be88780 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_recent_sort.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_group_plus" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_check + label="Sort by Most Recent" + name="sort_most"> + <menu_item_check.on_click + function="People.Recent.ViewSort.Action" + parameter="sort_recent" /> + <menu_item_check.on_check + function="People.Recent.ViewSort.CheckItem" + parameter="sort_recent" /> + </menu_item_check> + <menu_item_check + label="Sort by Name" + name="sort_name"> + <menu_item_check.on_click + function="People.Recent.ViewSort.Action" + parameter="sort_name" /> + <menu_item_check.on_check + function="People.Recent.ViewSort.CheckItem" + parameter="sort_name" /> + </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml new file mode 100644 index 0000000000..5520bc993c --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_group_plus" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_check name="view_icons" label="View People Icons"> + <menu_item_check.on_click + function="People.Recent.ViewSort.Action" + parameter="view_icons" /> + <menu_item_check.on_check + function="CheckControl" + parameter="RecentListShowIcons" /> + </menu_item_check> + <menu_item_separator layout="topleft" /> + <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> + <menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="panel_block_list_sidetray" /> + </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml deleted file mode 100644 index 485a5a658c..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu - name="menu_group_plus" - left="0" bottom="0" visible="false" - mouse_opaque="false"> - <menu_item_check - label="Sort by Most Recent" - name="sort_most"> - <menu_item_check.on_click - function="People.Recent.ViewSort.Action" - parameter="sort_recent" /> - <menu_item_check.on_check - function="People.Recent.ViewSort.CheckItem" - parameter="sort_recent" /> - </menu_item_check> - <menu_item_check - label="Sort by Name" - name="sort_name"> - <menu_item_check.on_click - function="People.Recent.ViewSort.Action" - parameter="sort_name" /> - <menu_item_check.on_check - function="People.Recent.ViewSort.CheckItem" - parameter="sort_name" /> - </menu_item_check> - <menu_item_separator layout="topleft" /> - <menu_item_check name="view_icons" label="View People Icons"> - <menu_item_check.on_click - function="People.Recent.ViewSort.Action" - parameter="view_icons" /> - <menu_item_check.on_check - function="CheckControl" - parameter="RecentListShowIcons" /> - </menu_item_check> - <menu_item_separator layout="topleft" /> - <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> - <menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="panel_block_list_sidetray" /> - </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 919661eff6..f61b0b3dbd 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -73,6 +73,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M top="0" halign="center" width="319"> + +<!-- ================================= NEARBY tab =========================== --> + <panel background_opaque="true" background_visible="true" @@ -117,19 +120,23 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="10" - name="nearby_sort_btn" + menu_filename="menu_people_nearby_view.xml" + menu_position="bottomleft" + name="nearby_view_btn" top="1" width="31" /> <menu_button follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Hierarchy_View_Disabled" + image_overlay="Inv_Underpants" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="2" - name="nearby_view_btn" + menu_filename="menu_people_nearby_sort.xml" + menu_position="bottomleft" + name="nearby_sort_btn" top="1" width="31" /> <button @@ -141,10 +148,14 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="2" - name="nearby_add_btn" + name="add_friend_btn" top="1" - width="31" /> + width="31"> + <commit_callback + function="People.AddFriend" /> + </button> <dnd_button + enabled="false" follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" @@ -155,7 +166,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" name="nearby_del_btn" top="1" - width="31"/> + width="31"> + <commit_callback + function="People.DelFriend" /> + </dnd_button> </panel> <layout_stack clip="false" @@ -208,6 +222,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M </layout_panel> </layout_stack> </panel> + +<!-- ================================= FRIENDS tab ========================== --> + <panel background_opaque="true" background_visible="true" @@ -252,19 +269,23 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="10" - name="friends_sort_btn" + menu_filename="menu_people_friends_view.xml" + menu_position="bottomleft" + name="friends_view_btn" top="1" width="31" /> <menu_button follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Hierarchy_View_Disabled" + image_overlay="Inv_Underpants" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="2" - name="friends_view_btn" + menu_filename="menu_people_friends_sort.xml" + menu_position="bottomleft" + name="friends_sort_btn" top="1" width="31" /> <button @@ -278,7 +299,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left_pad="2" name="friends_add_btn" top="1" - width="31" /> + width="31"> + <commit_callback + function="People.AddFriendWizard" /> + </button> <dnd_button follows="right" height="25" @@ -290,7 +314,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" name="friends_del_btn" top="1" - width="31"/> + width="31"> + <commit_callback + function="People.DelFriend" /> + </dnd_button> </panel> <accordion background_visible="true" @@ -348,6 +375,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M width="293" wrap="true" /> </panel> + +<!-- ================================= GROUPS tab =========================== --> + <panel background_opaque="true" background_visible="true" @@ -396,19 +426,22 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="10" - name="groups_sort_btn" + menu_filename="menu_people_groups_view.xml" + menu_position="bottomleft" + name="groups_view_btn" top="1" width="31" /> <menu_button + enabled="false" follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Hierarchy_View_Disabled" + image_overlay="Inv_Underpants" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="2" - name="groups_view_btn" + name="groups_sort_btn" top="1" width="31" /> <button @@ -420,10 +453,13 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="2" - name="groups_activate_btn" + name="activate_btn" top="1" - width="31" /> - <button + width="31"> + <commit_callback + function="People.Group.Activate" /> + </button> + <menu_button follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" @@ -432,9 +468,14 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="2" - name="groups_add_btn" + menu_filename="menu_group_plus.xml" + menu_position="bottomleft" + name="minus_btn" top="1" - width="31" /> + width="31"> + <validate_callback + function="People.Group.Plus.Validate" /> + </menu_button> <dnd_button follows="right" height="25" @@ -444,9 +485,12 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" left_pad="2" layout="topleft" - name="groups_del_btn" + name="minus_btn" top="1" - width="31"/> + width="31"> + <commit_callback + function="People.Group.Minus" /> + </dnd_button> </panel> <group_list allow_select="true" @@ -458,6 +502,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M top_pad="0" width="307" /> </panel> + +<!-- ================================= RECENT tab =========================== --> + <panel background_opaque="true" background_visible="true" @@ -502,19 +549,23 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="10" - name="recent_sort_btn" + menu_filename="menu_people_recent_view.xml" + menu_position="bottomleft" + name="recent_view_btn" top="1" width="31" /> <menu_button follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Hierarchy_View_Disabled" + image_overlay="Inv_Underpants" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="2" - name="recent_view_btn" + menu_filename="menu_people_recent_sort.xml" + menu_position="bottomleft" + name="recent_sort_btn" top="1" width="31" /> <button @@ -526,10 +577,14 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="2" - name="recent_add_btn" + name="add_friend_btn" top="1" - width="31" /> + width="31"> + <commit_callback + function="People.AddFriend" /> + </button> <dnd_button + enabled="false" follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" @@ -540,7 +595,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" name="recent_del_btn" top="1" - width="31"/> + width="31"> + <commit_callback + function="People.DelFriend" /> + </dnd_button> </panel> <avatar_list allow_select="true" @@ -592,7 +650,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="view_profile_btn" tool_tip="Show picture, groups, and other Residents information" top="0" - width="67" /> + width="67"> + <commit_callback + function="People.ViewProfile" /> + </button> </layout_panel> <layout_panel @@ -612,7 +673,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="im_btn" tool_tip="Open instant message session" top="0" - width="40" /> + width="40"> + <commit_callback + function="People.IM" /> + </button> </layout_panel> <layout_panel @@ -632,7 +696,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="call_btn" tool_tip="Call this Resident" top="0" - width="51" /> + width="51"> + <commit_callback + function="People.Call" /> + </button> </layout_panel> <layout_panel @@ -652,7 +719,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="share_btn" tool_tip="Share an inventory item" top="0" - width="65" /> + width="65"> + <commit_callback + function="People.Share" /> + </button> </layout_panel> <layout_panel @@ -672,7 +742,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="teleport_btn" tool_tip="Offer teleport" top="0" - width="76" /> + width="76"> + <commit_callback + function="People.Teleport" /> + </button> </layout_panel> </layout_stack> @@ -706,7 +779,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="group_info_btn" tool_tip="Show group information" top="0" - width="107" /> + width="107"> + <commit_callback + function="People.GroupInfo" /> + </button> </layout_panel> <layout_panel @@ -728,7 +804,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="chat_btn" tool_tip="Open chat session" top="0" - width="100" /> + width="100"> + <commit_callback + function="People.Chat" /> + </button> </layout_panel> <layout_panel @@ -750,7 +829,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="group_call_btn" tool_tip="Call this group" top="0" - width="95" /> + width="95"> + <commit_callback + function="People.GroupCall" /> + </button> </layout_panel> </layout_stack> </panel> -- cgit v1.2.3 From 9626ab8fec34f73cd60822bd34376c1cb94e11d7 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 5 Apr 2012 16:10:07 -0700 Subject: CHUI-89 FIX Make nametags appear consistently next to avatar heads nametags now track avatar head avatar_skeleton now loaded as param block vector3 param block parsing support fixes for param block recursion --- indra/llxuixml/llinitparam.h | 227 +++++---- indra/llxuixml/llxuiparser.cpp | 27 + indra/llxuixml/llxuiparser.h | 2 + indra/newview/llhudnametag.cpp | 279 +++-------- indra/newview/llhudnametag.h | 2 - indra/newview/llspatialpartition.cpp | 4 +- indra/newview/llviewermenu.cpp | 9 - indra/newview/llvoavatar.cpp | 948 ++++++++++++++++------------------- indra/newview/llvoavatar.h | 15 +- indra/newview/pipeline.cpp | 5 - 10 files changed, 689 insertions(+), 829 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index ab20957760..6fffb73acd 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -377,8 +377,9 @@ namespace LLInitParam class Lazy { public: + Lazy() - : mPtr(NULL) + : mPtr(NULL) {} ~Lazy() @@ -386,6 +387,11 @@ namespace LLInitParam delete mPtr; } + Lazy(const T& value) + { + mPtr = new T(value); + } + Lazy(const Lazy& other) { if (other.mPtr) @@ -424,12 +430,17 @@ namespace LLInitParam const T& get() const { - return ensureInstance(); + return *ensureInstance(); } T& get() { - return ensureInstance(); + return *ensureInstance(); + } + + operator const T&() const + { + return get(); } private: @@ -520,8 +531,8 @@ namespace LLInitParam void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const; - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); } // take all provided params from other and apply to self bool overwriteFrom(const BaseBlock& other) @@ -539,6 +550,15 @@ namespace LLInitParam ParamDescriptorPtr findParamDescriptor(const Param& param); + // take all provided params from other and apply to self + bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); + + static BlockDescriptor& getBlockDescriptor() + { + static BlockDescriptor sBlockDescriptor; + return sBlockDescriptor; + } + protected: void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size); @@ -547,25 +567,11 @@ namespace LLInitParam { return mergeBlock(block_data, source, overwrite); } - // take all provided params from other and apply to self - bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); - - static BlockDescriptor& selfBlockDescriptor() - { - static BlockDescriptor sBlockDescriptor; - return sBlockDescriptor; - } private: const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const; }; - template<typename T> - struct ParamCompare<BaseBlock::Lazy<T>, false > - { - static bool equals(const BaseBlock::Lazy<T>& a, const BaseBlock::Lazy<T>& b) { return !a.empty() || !b.empty(); } - }; - class Param { public: @@ -607,26 +613,16 @@ namespace LLInitParam // these templates allow us to distinguish between template parameters // that derive from BaseBlock and those that don't - template<typename T, typename Void = void> + template<typename T, typename BLOCK_IDENTIFIER = void> struct IsBlock { static const bool value = false; - struct EmptyBase {}; - typedef EmptyBase base_class_t; }; template<typename T> struct IsBlock<T, typename T::baseblock_base_class_t> { static const bool value = true; - typedef BaseBlock base_class_t; - }; - - template<typename T> - struct IsBlock<BaseBlock::Lazy<T>, typename T::baseblock_base_class_t > - { - static const bool value = true; - typedef BaseBlock base_class_t; }; template<typename T, typename NAME_VALUE_LOOKUP, bool VALUE_IS_BLOCK = IsBlock<T>::value> @@ -817,13 +813,13 @@ namespace LLInitParam public: typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t; typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; - typedef typename param_value_t::value_assignment_t value_assignment_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; + typedef typename param_value_t::value_assignment_t value_assignment_t; using param_value_t::operator(); - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) - : Param(block_descriptor.mCurrentBlockPtr) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const T& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + : Param(block_descriptor.mCurrentBlockPtr), + param_value_t(value) { if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { @@ -837,8 +833,6 @@ namespace LLInitParam min_count, max_count)); BaseBlock::addParam(block_descriptor, param_descriptor, name); } - - setValue(value); } bool isProvided() const { return Param::anyProvided(); } @@ -857,14 +851,14 @@ namespace LLInitParam } // try to parse a known named value - if(name_value_lookup_t::valueNamesExist()) + if(param_value_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) + if (param_value_t::getValueFromName(name, typed_param.getValue())) { typed_param.setValueName(name); typed_param.setProvided(); @@ -917,9 +911,9 @@ namespace LLInitParam // tell parser about our actual type parser.inspectValue<T>(name_stack, min_count, max_count, NULL); // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) - if (name_value_lookup_t::getPossibleValues()) + if (param_value_t::getPossibleValues()) { - parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); + parser.inspectValue<std::string>(name_stack, min_count, max_count, param_value_t::getPossibleValues()); } } @@ -969,11 +963,10 @@ namespace LLInitParam typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; typedef typename param_value_t::value_assignment_t value_assignment_t; typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true> self_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; using param_value_t::operator(); - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const T& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr), param_value_t(value) { @@ -1002,14 +995,14 @@ namespace LLInitParam return true; } - if(name_value_lookup_t::valueNamesExist()) + if(param_value_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) + if (param_value_t::getValueFromName(name, typed_param.getValue())) { typed_param.setValueName(name); typed_param.setProvided(); @@ -1041,7 +1034,7 @@ namespace LLInitParam } else { - typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param)); + typed_param.serializeBlock(parser, name_stack, &static_cast<const BaseBlock&>(*static_cast<const self_t*>(diff_param))); } } @@ -1115,7 +1108,7 @@ namespace LLInitParam if (src_typed_param.anyProvided()) { - if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::selfBlockDescriptor(), src_typed_param, overwrite)) + if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::getBlockDescriptor(), src_typed_param, overwrite)) { dst_typed_param.clearValueName(); dst_typed_param.setProvided(true); @@ -1138,9 +1131,8 @@ namespace LLInitParam typedef const container_t& value_assignment_t; typedef typename param_value_t::value_t value_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const container_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) { std::copy(value.begin(), value.end(), std::back_inserter(mValues)); @@ -1176,14 +1168,14 @@ namespace LLInitParam } // try to parse a known named value - if(name_value_lookup_t::valueNamesExist()) + if(param_value_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value)) + if (param_value_t::getValueFromName(name, value)) { typed_param.add(value); typed_param.mValues.back().setValueName(name); @@ -1234,9 +1226,9 @@ namespace LLInitParam static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) { parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL); - if (name_value_lookup_t::getPossibleValues()) + if (param_value_t::getPossibleValues()) { - parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); + parser.inspectValue<std::string>(name_stack, min_count, max_count, param_value_t::getPossibleValues()); } } @@ -1261,12 +1253,12 @@ namespace LLInitParam setProvided(); } - void add(const typename name_value_lookup_t::name_t& name) + void add(const typename param_value_t::name_t& name) { value_t value; // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value)) + if (param_value_t::getValueFromName(name, value)) { add(value); mValues.back().setValueName(name); @@ -1330,9 +1322,8 @@ namespace LLInitParam typedef typename std::vector<param_value_t> container_t; typedef const container_t& value_assignment_t; typedef typename param_value_t::value_t value_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const container_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) { std::copy(value.begin(), value.end(), back_inserter(mValues)); @@ -1372,14 +1363,14 @@ namespace LLInitParam typed_param.setProvided(); return true; } - else if(name_value_lookup_t::valueNamesExist()) + else if(param_value_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value.getValue())) + if (param_value_t::getValueFromName(name, value.getValue())) { typed_param.mValues.back().setValueName(name); typed_param.setProvided(); @@ -1447,12 +1438,12 @@ namespace LLInitParam setProvided(); } - void add(const typename name_value_lookup_t::name_t& name) + void add(const typename param_value_t::name_t& name) { value_t value; // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value)) + if (param_value_t::getValueFromName(name, value)) { add(value); mValues.back().setValueName(name); @@ -1526,13 +1517,13 @@ namespace LLInitParam // take all provided params from other and apply to self bool overwriteFrom(const self_t& other) { - return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true); + return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, true); } // take all provided params that are not already provided, and apply to self bool fillFrom(const self_t& other) { - return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false); + return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false); } bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) @@ -1550,7 +1541,7 @@ namespace LLInitParam bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite) { mCurChoice = other.mCurChoice; - return base_block_t::mergeBlock(selfBlockDescriptor(), other, overwrite); + return base_block_t::mergeBlock(getBlockDescriptor(), other, overwrite); } // clear out old choice when param has changed @@ -1571,14 +1562,14 @@ namespace LLInitParam base_block_t::paramChanged(changed_param, user_provided); } - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); } protected: ChoiceBlock() : mCurChoice(0) { - BaseBlock::init(selfBlockDescriptor(), base_block_t::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); + BaseBlock::init(getBlockDescriptor(), base_block_t::getBlockDescriptor(), sizeof(DERIVED_BLOCK)); } // Alternatives are mutually exclusive wrt other Alternatives in the same block. @@ -1596,13 +1587,13 @@ namespace LLInitParam using super_t::operator =; - explicit Alternative(const char* name = "", value_assignment_t val = defaultValue<T>()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1), + explicit Alternative(const char* name = "", const T& val = defaultValue<T>()) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1), mOriginalValue(val) { // assign initial choice to first declared option - DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr); - if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) + DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr); + if (LL_UNLIKELY(DERIVED_BLOCK::getBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) { if(blockp->mCurChoice == 0) { @@ -1654,8 +1645,8 @@ namespace LLInitParam T mOriginalValue; }; - protected: - static BlockDescriptor& selfBlockDescriptor() + public: + static BlockDescriptor& getBlockDescriptor() { static BlockDescriptor sBlockDescriptor; return sBlockDescriptor; @@ -1683,23 +1674,23 @@ namespace LLInitParam // take all provided params from other and apply to self bool overwriteFrom(const self_t& other) { - return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true); + return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, true); } // take all provided params that are not already provided, and apply to self bool fillFrom(const self_t& other) { - return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false); + return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false); } - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); } protected: Block() { //#pragma message("Parsing LLInitParam::Block") - BaseBlock::init(selfBlockDescriptor(), BASE_BLOCK::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); + BaseBlock::init(getBlockDescriptor(), BASE_BLOCK::getBlockDescriptor(), sizeof(DERIVED_BLOCK)); } // @@ -1715,8 +1706,8 @@ namespace LLInitParam using super_t::operator(); using super_t::operator =; - explicit Optional(const char* name = "", value_assignment_t val = defaultValue<T>()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1) + explicit Optional(const char* name = "", const T& val = defaultValue<T>()) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1) { //#pragma message("Parsing LLInitParam::Block::Optional") } @@ -1746,8 +1737,8 @@ namespace LLInitParam using super_t::operator =; // mandatory parameters require a name to be parseable - explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue<T>()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1) + explicit Mandatory(const char* name = "", const T& val = defaultValue<T>()) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, &validate, 1, 1) {} Mandatory& operator =(value_assignment_t val) @@ -1782,7 +1773,7 @@ namespace LLInitParam typedef typename super_t::const_iterator const_iterator; explicit Multiple(const char* name = "") - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) {} Multiple& operator =(value_assignment_t val) @@ -1808,9 +1799,9 @@ namespace LLInitParam { public: explicit Deprecated(const char* name) - : Param(DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr) + : Param(DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr) { - BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); + BlockDescriptor& block_descriptor = DERIVED_BLOCK::getBlockDescriptor(); if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( @@ -1841,13 +1832,14 @@ namespace LLInitParam // different semantics for documentation purposes, but functionally identical typedef Deprecated Ignored; - protected: - static BlockDescriptor& selfBlockDescriptor() + public: + static BlockDescriptor& getBlockDescriptor() { static BlockDescriptor sBlockDescriptor; return sBlockDescriptor; } + protected: template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, bool is_block> void changeDefault(TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>& param, typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_assignment_t value) @@ -1887,7 +1879,7 @@ namespace LLInitParam { *static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue(); // merge individual parameters into destination - return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite); + return super_t::mergeBlock(super_t::getBlockDescriptor(), other, overwrite); } return false; } @@ -1955,14 +1947,36 @@ namespace LLInitParam mutable bool mValidated; // lazy validation flag }; - template<typename T, bool IS_BLOCK> + template<typename T, typename BLOCK_IDENTIFIER> + struct IsBlock<ParamValue<BaseBlock::Lazy<T>, TypeValues<BaseBlock::Lazy<T> > > , BLOCK_IDENTIFIER> + { + static const bool value = true;//IsBlock<T>::value; + }; + + template<typename T> + struct ParamCompare<BaseBlock::Lazy<T>, false> + { + static bool equals(const T&a, const T &b) + { + return a == b; + } + + static bool equals(const BaseBlock::Lazy<T>& a, const BaseBlock::Lazy<T>& b) + { + if (a.empty() || b.empty()) return false; + return a.get() == b.get(); + } + }; + + + template<typename T, bool VALUE_IS_BLOCK> class ParamValue <BaseBlock::Lazy<T>, - TypeValues<T>, - IS_BLOCK> - : public IsBlock<T>::base_class_t + TypeValues<BaseBlock::Lazy<T> >, + VALUE_IS_BLOCK> + : public TypeValues<T> { public: - typedef ParamValue <BaseBlock::Lazy<T>, TypeValues<T>, false> self_t; + typedef ParamValue <BaseBlock::Lazy<T>, TypeValues<BaseBlock::Lazy<T> >, false> self_t; typedef const T& value_assignment_t; typedef T value_t; @@ -1971,11 +1985,16 @@ namespace LLInitParam mValidated(false) {} - ParamValue(value_assignment_t other) + ParamValue(const BaseBlock::Lazy<T>& other) : mValue(other), mValidated(false) {} + ParamValue(const T& value) + : mValue(value), + mValidated(false) + {} + void setValue(value_assignment_t val) { mValue.set(val); @@ -1991,6 +2010,11 @@ namespace LLInitParam return mValue.get(); } + operator const BaseBlock&() const + { + return mValue.get(); + } + operator value_assignment_t() const { return mValue.get(); @@ -2020,7 +2044,22 @@ namespace LLInitParam return mValue.get().inspectBlock(p, name_stack, min_count, max_count); } - protected: + bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) + { + return mValue.get().mergeBlock(block_data, source.getValue(), overwrite); + } + + bool validateBlock(bool emit_errors = true) const + { + return mValue.get().validateBlock(emit_errors); + } + + static BlockDescriptor& getBlockDescriptor() + { + return T::getBlockDescriptor(); + } + + mutable bool mValidated; // lazy validation flag private: diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index afc76024d1..3c89fa3aaf 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -42,6 +42,7 @@ #include <boost/spirit/include/classic_core.hpp> #include "lluicolor.h" +#include "v3math.h" using namespace BOOST_SPIRIT_CLASSIC_NS; @@ -670,6 +671,7 @@ LLXUIParser::LLXUIParser() registerParserFuncs<S32>(readS32Value, writeS32Value); registerParserFuncs<F32>(readF32Value, writeF32Value); registerParserFuncs<F64>(readF64Value, writeF64Value); + registerParserFuncs<LLVector3>(readVector3Value, writeVector3Value); registerParserFuncs<LLColor4>(readColor4Value, writeColor4Value); registerParserFuncs<LLUIColor>(readUIColorValue, writeUIColorValue); registerParserFuncs<LLUUID>(readUUIDValue, writeUUIDValue); @@ -1144,6 +1146,31 @@ bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, name_stack_ return false; } +bool LLXUIParser::readVector3Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast<LLXUIParser&>(parser); + LLVector3* vecp = (LLVector3*)val_ptr; + if(self.mCurReadNode->getFloatValue(3, vecp->mV) >= 3) + { + return true; + } + + return false; +} + +bool LLXUIParser::writeVector3Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast<LLXUIParser&>(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + LLVector3 vector = *((LLVector3*)val_ptr); + node->setFloatValue(3, vector.mV); + return true; + } + return false; +} + bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr) { LLXUIParser& self = static_cast<LLXUIParser&>(parser); diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h index d7cd256967..e48663e5cc 100644 --- a/indra/llxuixml/llxuiparser.h +++ b/indra/llxuixml/llxuiparser.h @@ -127,6 +127,7 @@ private: static bool readS32Value(Parser& parser, void* val_ptr); static bool readF32Value(Parser& parser, void* val_ptr); static bool readF64Value(Parser& parser, void* val_ptr); + static bool readVector3Value(Parser& parser, void* val_ptr); static bool readColor4Value(Parser& parser, void* val_ptr); static bool readUIColorValue(Parser& parser, void* val_ptr); static bool readUUIDValue(Parser& parser, void* val_ptr); @@ -144,6 +145,7 @@ private: static bool writeS32Value(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeF32Value(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeF64Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeVector3Value(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t&); diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 482294c8a6..cf55954d7d 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -187,45 +187,42 @@ BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3& + (y_pixel_vec * screen_offset.mV[VY]); - //if (mUseBubble) - { - LLVector3 bg_pos = render_position - + (F32)mOffsetY * y_pixel_vec - - (width_vec / 2.f) - - (height_vec); - //LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); + LLVector3 bg_pos = render_position + + (F32)mOffsetY * y_pixel_vec + - (width_vec / 2.f) + - (height_vec); + //LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); - LLVector3 v[] = - { - bg_pos, - bg_pos + width_vec, - bg_pos + width_vec + height_vec, - bg_pos + height_vec, - }; + LLVector3 v[] = + { + bg_pos, + bg_pos + width_vec, + bg_pos + width_vec + height_vec, + bg_pos + height_vec, + }; - if (debug_render) - { - gGL.begin(LLRender::LINE_STRIP); - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[2].mV); - gGL.vertex3fv(v[3].mV); - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[2].mV); - gGL.end(); - } + if (debug_render) + { + gGL.begin(LLRender::LINE_STRIP); + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[2].mV); + gGL.vertex3fv(v[3].mV); + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[2].mV); + gGL.end(); + } - LLVector3 dir = end-start; - F32 a, b, t; + LLVector3 dir = end-start; + F32 a, b, t; - if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE) || - LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, a, b, t, FALSE) ) + if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE) || + LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, a, b, t, FALSE) ) + { + if (t <= 1.f) { - if (t <= 1.f) - { - intersection = start + dir*t; - return TRUE; - } + intersection = start + dir*t; + return TRUE; } } @@ -241,12 +238,6 @@ void LLHUDNameTag::render() } } -void LLHUDNameTag::renderForSelect() -{ - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - renderText(TRUE); -} - void LLHUDNameTag::renderText(BOOL for_select) { if (!mVisible || mHidden) @@ -336,142 +327,53 @@ void LLHUDNameTag::renderText(BOOL for_select) LLCoordGL screen_pos; LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE); - LLVector2 screen_offset; -// if (!mUseBubble) -// { -// screen_offset = mPositionOffset; -// } -// else -// { - screen_offset = updateScreenPos(mPositionOffset); -// } + LLVector2 screen_offset = updateScreenPos(mPositionOffset); LLVector3 render_position = mPositionAgent + (x_pixel_vec * screen_offset.mV[VX]) + (y_pixel_vec * screen_offset.mV[VY]); -// if (mUseBubble) + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + LLUI::pushMatrix(); { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - LLUI::pushMatrix(); - { - LLVector3 bg_pos = render_position - + (F32)mOffsetY * y_pixel_vec - - (width_vec / 2.f) - - (height_vec); - LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); + LLVector3 bg_pos = render_position + + (F32)mOffsetY * y_pixel_vec + - (width_vec / 2.f) + - (height_vec); + LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); - if (for_select) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - S32 name = mSourceObject->mGLName; - LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name); - gGL.color4ubv(coloru.mV); - gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); - LLUI::popMatrix(); - return; - } - else - { - gGL.getTexUnit(0)->bind(imagep->getImage()); + if (for_select) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + S32 name = mSourceObject->mGLName; + LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name); + gGL.color4ubv(coloru.mV); + gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); + LLUI::popMatrix(); + return; + } + else + { + gGL.getTexUnit(0)->bind(imagep->getImage()); - gGL.color4fv(bg_color.mV); - gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); + gGL.color4fv(bg_color.mV); + gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); - if ( mLabelSegments.size()) - { - LLUI::pushMatrix(); - { - gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); - LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; - LLVector3 label_offset = height_vec - label_height; - LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); - gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); - } - LLUI::popMatrix(); - } - } - - BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f; - BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f); - - // draw line segments pointing to parent object - if (!mOffscreen && (outside_width || outside_height)) + if ( mLabelSegments.size()) { LLUI::pushMatrix(); { - gGL.color4fv(bg_color.mV); - LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec); - target_pos += (width_vec / 2.f); - target_pos += mVertAlignment == ALIGN_VERT_CENTER ? (height_vec * 0.5f) : LLVector3::zero; - target_pos -= 3.f * x_pixel_vec; - target_pos -= 6.f * y_pixel_vec; - LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]); - gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec); + gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); + LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; + LLVector3 label_offset = height_vec - label_height; + LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); + gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); } LLUI::popMatrix(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE); - - LLVector3 box_center_offset; - box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f); - LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]); - gGL.color4fv(bg_color.mV); - LLUI::setLineWidth(2.0); - gGL.begin(LLRender::LINES); - { - if (outside_width) - { - LLVector3 vert; - // draw line in x then y - if (mPositionOffset.mV[VX] < 0.f) - { - // start at right edge - vert = width_vec * 0.5f; - gGL.vertex3fv(vert.mV); - } - else - { - // start at left edge - vert = width_vec * -0.5f; - gGL.vertex3fv(vert.mV); - } - vert = -mPositionOffset.mV[VX] * x_pixel_vec; - gGL.vertex3fv(vert.mV); - gGL.vertex3fv(vert.mV); - vert -= mPositionOffset.mV[VY] * y_pixel_vec; - vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); - gGL.vertex3fv(vert.mV); - } - else - { - LLVector3 vert; - // draw line in y then x - if (mPositionOffset.mV[VY] < 0.f) - { - // start at top edge - vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); - gGL.vertex3fv(vert.mV); - } - else - { - // start at bottom edge - vert = (height_vec * -0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); - gGL.vertex3fv(vert.mV); - } - vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec; - vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); - gGL.vertex3fv(vert.mV); - } - } - gGL.end(); - LLUI::setLineWidth(1.0); - } } - LLUI::popMatrix(); } + LLUI::popMatrix(); F32 y_offset = (F32)mOffsetY; @@ -874,29 +776,26 @@ void LLHUDNameTag::updateAll() for (r_it = sVisibleTextObjects.rbegin(); r_it != sVisibleTextObjects.rend(); ++r_it) { LLHUDNameTag* textp = (*r_it); -// if (textp->mUseBubble) -// { - if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE) - { - textp->setLOD(3); - } - else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE) - { - textp->setLOD(2); - } - else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE) - { - textp->setLOD(1); - } - else - { - textp->setLOD(0); - } - textp->updateSize(); - // find on-screen position and initialize collision rectangle - textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero); - current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight()); -// } + if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE) + { + textp->setLOD(3); + } + else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE) + { + textp->setLOD(2); + } + else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE) + { + textp->setLOD(1); + } + else + { + textp->setLOD(0); + } + textp->updateSize(); + // find on-screen position and initialize collision rectangle + textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero); + current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight()); } LLStat* camera_vel_stat = LLViewerCamera::getInstance()->getVelocityStat(); @@ -914,20 +813,12 @@ void LLHUDNameTag::updateAll() { LLHUDNameTag* src_textp = (*src_it); -// if (!src_textp->mUseBubble) -// { -// continue; -// } VisibleTextObjectIterator dst_it = src_it; ++dst_it; for (; dst_it != sVisibleTextObjects.end(); ++dst_it) { LLHUDNameTag* dst_textp = (*dst_it); -// if (!dst_textp->mUseBubble) -// { -// continue; -// } if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect)) { LLRectf intersect_rect = src_textp->mSoftScreenRect; @@ -976,10 +867,6 @@ void LLHUDNameTag::updateAll() VisibleTextObjectIterator this_object_it; for (this_object_it = sVisibleTextObjects.begin(); this_object_it != sVisibleTextObjects.end(); ++this_object_it) { -// if (!(*this_object_it)->mUseBubble) -// { -// continue; -// } (*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC)); } } @@ -1037,10 +924,6 @@ void LLHUDNameTag::addPickable(std::set<LLViewerObject*> &pick_list) VisibleTextObjectIterator text_it; for (text_it = sVisibleTextObjects.begin(); text_it != sVisibleTextObjects.end(); ++text_it) { -// if (!(*text_it)->mUseBubble) -// { -// continue; -// } pick_list.insert((*text_it)->mSourceObject); } } diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h index 3325c22def..72647d5b26 100644 --- a/indra/newview/llhudnametag.h +++ b/indra/newview/llhudnametag.h @@ -118,7 +118,6 @@ public: /*virtual*/ void markDead(); friend class LLHUDObject; /*virtual*/ F32 getDistance() const { return mLastDistance; } - //void setUseBubble(BOOL use_bubble) { mUseBubble = use_bubble; } S32 getLOD() { return mLOD; } BOOL getVisible() { return mVisible; } BOOL getHidden() const { return mHidden; } @@ -136,7 +135,6 @@ protected: LLHUDNameTag(const U8 type); /*virtual*/ void render(); - /*virtual*/ void renderForSelect(); void renderText(BOOL for_select); static void updateAll(); void setLOD(S32 lod); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 5d196a465f..1333862855 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2774,7 +2774,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color) { - gGL.diffuseColor4fv(color.mV); + gGL.color4fv(color.mV); gGL.begin(LLRender::LINES); { gGL.vertex3fv((position - LLVector3(size, 0.f, 0.f)).mV); @@ -3904,7 +3904,7 @@ void renderAgentTarget(LLVOAvatar* avatar) if (avatar->isSelf()) { renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); - renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); + renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(0, 1, 0, 0.8f)); renderCrossHairs(avatar->mRoot.getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f)); renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f)); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 99540ccce9..ae32683c99 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3190,15 +3190,6 @@ bool enable_freeze_eject(const LLSD& avatar_id) return new_value; } - -void login_done(S32 which, void *user) -{ - llinfos << "Login done " << which << llendl; - - LLPanelLogin::closePanel(); -} - - bool callback_leave_group(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index bc7f5a9744..f00363bfa6 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -62,6 +62,7 @@ #include "llhudmanager.h" #include "llhudnametag.h" #include "llhudtext.h" // for mText/mDebugText +#include "llinitparam.h" #include "llkeyframefallmotion.h" #include "llkeyframestandmotion.h" #include "llkeyframewalkmotion.h" @@ -193,6 +194,9 @@ const S32 MAX_BUBBLE_CHAT_LENGTH = DB_CHAT_MSG_STR_LEN; const S32 MAX_BUBBLE_CHAT_UTTERANCES = 12; const F32 CHAT_FADE_TIME = 8.0; const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f; +const F32 NAMETAG_UPDATE_THRESHOLD = 0.3f; +const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f; +const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.15f; const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); @@ -224,55 +228,62 @@ struct LLTextureMaskData **/ //------------------------------------------------------------------------ -// LLVOBoneInfo +// LLVOAvatarBoneInfo // Trans/Scale/Rot etc. info about each avatar bone. Used by LLVOAvatarSkeleton. //------------------------------------------------------------------------ -class LLVOAvatarBoneInfo +struct LLVOAvatarCollisionVolumeInfo : public LLInitParam::Block<LLVOAvatarCollisionVolumeInfo> { - friend class LLVOAvatar; - friend class LLVOAvatarSkeletonInfo; -public: - LLVOAvatarBoneInfo() : mIsJoint(FALSE) {} - ~LLVOAvatarBoneInfo() - { - std::for_each(mChildList.begin(), mChildList.end(), DeletePointer()); - } - BOOL parseXml(LLXmlTreeNode* node); + LLVOAvatarCollisionVolumeInfo() + : name("name"), + pos("pos"), + rot("rot"), + scale("scale") + {} + + Mandatory<std::string> name; + Mandatory<LLVector3> pos, + rot, + scale; +}; + +struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock<LLVOAvatarChildJoint> +{ + Alternative<Lazy<struct LLVOAvatarBoneInfo> > bone; + Alternative<LLVOAvatarCollisionVolumeInfo> collision_volume; + + LLVOAvatarChildJoint() + : bone("bone"), + collision_volume("collision_volume") + {} +}; + +struct LLVOAvatarBoneInfo : public LLInitParam::Block<LLVOAvatarBoneInfo, LLVOAvatarCollisionVolumeInfo> +{ + LLVOAvatarBoneInfo() + : pivot("pivot") + {} -private: - std::string mName; - BOOL mIsJoint; - LLVector3 mPos; - LLVector3 mRot; - LLVector3 mScale; - LLVector3 mPivot; - typedef std::vector<LLVOAvatarBoneInfo*> child_list_t; - child_list_t mChildList; + Mandatory<LLVector3> pivot; + Multiple<LLVOAvatarChildJoint> children; }; //------------------------------------------------------------------------ // LLVOAvatarSkeletonInfo // Overall avatar skeleton //------------------------------------------------------------------------ -class LLVOAvatarSkeletonInfo +struct LLVOAvatarSkeletonInfo : public LLInitParam::Block<LLVOAvatarSkeletonInfo> { - friend class LLVOAvatar; -public: - LLVOAvatarSkeletonInfo() : - mNumBones(0), mNumCollisionVolumes(0) {} - ~LLVOAvatarSkeletonInfo() - { - std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); - } - BOOL parseXml(LLXmlTreeNode* node); - S32 getNumBones() const { return mNumBones; } - S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; } + LLVOAvatarSkeletonInfo() + : skeleton_root(""), + num_bones("num_bones"), + num_collision_volumes("num_collision_volumes"), + version("version") + {} -private: - S32 mNumBones; - S32 mNumCollisionVolumes; - typedef std::vector<LLVOAvatarBoneInfo*> bone_info_list_t; - bone_info_list_t mBoneInfoList; + Mandatory<std::string> version; + Mandatory<S32> num_bones, + num_collision_volumes; + Mandatory<LLVOAvatarChildJoint> skeleton_root; }; //----------------------------------------------------------------------------- @@ -597,7 +608,7 @@ private: // Static Data //----------------------------------------------------------------------------- LLXmlTree LLVOAvatar::sXMLTree; -LLXmlTree LLVOAvatar::sSkeletonXMLTree; +LLXMLNodePtr LLVOAvatar::sSkeletonXMLTree; LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL; LLVOAvatar::LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL; LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL; @@ -1123,18 +1134,6 @@ void LLVOAvatar::initClass() llerrs << "Error parsing skeleton file: " << skeleton_path << llendl; } - // Process XML data - - // avatar_skeleton.xml - if (sAvatarSkeletonInfo) - { //this can happen if a login attempt failed - delete sAvatarSkeletonInfo; - } - sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; - if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) - { - llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl; - } // parse avatar_lad.xml if (sAvatarXmlInfo) { //this can happen if a login attempt failed @@ -1183,7 +1182,7 @@ void LLVOAvatar::initClass() void LLVOAvatar::cleanupClass() { deleteAndClear(sAvatarXmlInfo); - sSkeletonXMLTree.cleanup(); + sSkeletonXMLTree = NULL; sXMLTree.cleanup(); } @@ -1655,33 +1654,39 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename) //------------------------------------------------------------------------- // parse the file //------------------------------------------------------------------------- - BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE ); + + LLXMLNodePtr skeleton_xml; + BOOL parsesuccess = LLXMLNode::parseFile(filename, skeleton_xml, NULL); - if (!parsesuccess) + if (!parsesuccess || skeleton_xml.isNull()) { llerrs << "Can't parse skeleton file: " << filename << llendl; return FALSE; } - // now sanity check xml file - LLXmlTreeNode* root = sSkeletonXMLTree.getRoot(); - if (!root) + // Process XML data + if (sAvatarSkeletonInfo) + { //this can happen if a login attempt failed + delete sAvatarSkeletonInfo; + } + sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; + + LLXUIParser parser; + parser.readXUI(skeleton_xml, *sAvatarSkeletonInfo, filename); + if (!sAvatarSkeletonInfo->validateBlock()) { - llerrs << "No root node found in avatar skeleton file: " << filename << llendl; - return FALSE; + llerrs << "Error parsing skeleton XML file: " << filename << llendl; } - if( !root->hasName( "linden_skeleton" ) ) + if( !skeleton_xml->hasName( "linden_skeleton" ) ) { llerrs << "Invalid avatar skeleton file header: " << filename << llendl; return FALSE; } - std::string version; - static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); - if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) + if (sAvatarSkeletonInfo->version() != "1.0") { - llerrs << "Invalid avatar skeleton file version: " << version << " in file: " << filename << llendl; + llerrs << "Invalid avatar skeleton file version: " << sAvatarSkeletonInfo->version() << " in file: " << filename << llendl; return FALSE; } @@ -1690,14 +1695,13 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename) //----------------------------------------------------------------------------- // setupBone() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num) +//----------------------------------------------------------- +BOOL LLVOAvatar::setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num) { LLMemType mt(LLMemType::MTYPE_AVATAR); LLViewerJoint* joint = NULL; - - if (info->mIsJoint) + if (info.bone.isChosen()) { joint = (LLViewerJoint*)getCharacterJoint(joint_num); if (!joint) @@ -1705,7 +1709,23 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent llwarns << "Too many bones" << llendl; return FALSE; } - joint->setName( info->mName ); + joint->setName( info.bone().name ); + joint->setPosition(info.bone().pos); + joint->setRotation(mayaQ(info.bone().rot().mV[VX], info.bone().rot().mV[VY], info.bone().rot().mV[VZ], LLQuaternion::XYZ)); + joint->setScale(info.bone().scale); + joint->setSkinOffset( info.bone().pivot ); + joint_num++; + + for (LLInitParam::ParamIterator<LLVOAvatarChildJoint>::const_iterator child_it = info.bone().children.begin(), + end_it = info.bone().children.end(); + child_it != end_it; + ++child_it) + { + if (!setupBone(*child_it, joint, volume_num, joint_num)) + { + return FALSE; + } + } } else // collision volume { @@ -1715,7 +1735,11 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent return FALSE; } joint = (LLViewerJoint*)(&mCollisionVolumes[volume_num]); - joint->setName( info->mName ); + joint->setName( info.collision_volume.name); + joint->setPosition(info.collision_volume.pos); + joint->setRotation(mayaQ(info.collision_volume.rot().mV[VX], info.collision_volume.rot().mV[VY], info.collision_volume.rot().mV[VZ], LLQuaternion::XYZ)); + joint->setScale(info.collision_volume.scale); + volume_num++; } // add to parent @@ -1724,34 +1748,8 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent parent->addChild( joint ); } - joint->setPosition(info->mPos); - joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY], - info->mRot.mV[VZ], LLQuaternion::XYZ)); - joint->setScale(info->mScale); - joint->setDefaultFromCurrentXform(); - if (info->mIsJoint) - { - joint->setSkinOffset( info->mPivot ); - joint_num++; - } - else // collision volume - { - volume_num++; - } - - // setup children - LLVOAvatarBoneInfo::child_list_t::const_iterator iter; - for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter) - { - LLVOAvatarBoneInfo *child_info = *iter; - if (!setupBone(child_info, joint, volume_num, joint_num)) - { - return FALSE; - } - } - return TRUE; } @@ -1765,35 +1763,31 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) //------------------------------------------------------------------------- // allocate joints //------------------------------------------------------------------------- - if (!allocateCharacterJoints(info->mNumBones)) + if (!allocateCharacterJoints(info->num_bones)) { - llerrs << "Can't allocate " << info->mNumBones << " joints" << llendl; + llerrs << "Can't allocate " << info->num_bones() << " joints" << llendl; return FALSE; } //------------------------------------------------------------------------- // allocate volumes //------------------------------------------------------------------------- - if (info->mNumCollisionVolumes) + if (info->num_collision_volumes) { - if (!allocateCollisionVolumes(info->mNumCollisionVolumes)) + if (!allocateCollisionVolumes(info->num_collision_volumes)) { - llerrs << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << llendl; + llerrs << "Can't allocate " << info->num_collision_volumes() << " collision volumes" << llendl; return FALSE; } } S32 current_joint_num = 0; S32 current_volume_num = 0; - LLVOAvatarSkeletonInfo::bone_info_list_t::const_iterator iter; - for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter) + + if (!setupBone(info->skeleton_root, NULL, current_volume_num, current_joint_num)) { - LLVOAvatarBoneInfo *info = *iter; - if (!setupBone(info, NULL, current_volume_num, current_joint_num)) - { - llerrs << "Error parsing bone in skeleton file" << llendl; - return FALSE; - } + llerrs << "Error parsing bone in skeleton file" << llendl; + return FALSE; } return TRUE; @@ -2922,43 +2916,43 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) return; } - BOOL new_name = FALSE; - if (visible_chat != mVisibleChat) - { - mVisibleChat = visible_chat; - new_name = TRUE; - } + BOOL new_name = FALSE; + if (visible_chat != mVisibleChat) + { + mVisibleChat = visible_chat; + new_name = TRUE; + } - if (sRenderGroupTitles != mRenderGroupTitles) - { - mRenderGroupTitles = sRenderGroupTitles; - new_name = TRUE; - } + if (sRenderGroupTitles != mRenderGroupTitles) + { + mRenderGroupTitles = sRenderGroupTitles; + new_name = TRUE; + } - // First Calculate Alpha - // If alpha > 0, create mNameText if necessary, otherwise delete it - F32 alpha = 0.f; - if (mAppAngle > 5.f) + // First Calculate Alpha + // If alpha > 0, create mNameText if necessary, otherwise delete it + F32 alpha = 0.f; + if (mAppAngle > 5.f) + { + const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; + if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) { - const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; - if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) - { - alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; - } - else - { - // ...not fading, full alpha - alpha = 1.f; - } + alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; } - else if (mAppAngle > 2.f) + else { - // far away is faded out also - alpha = (mAppAngle-2.f)/3.f; + // ...not fading, full alpha + alpha = 1.f; } + } + else if (mAppAngle > 2.f) + { + // far away is faded out also + alpha = (mAppAngle-2.f)/3.f; + } if (alpha <= 0.f) - { + { if (mNameText) { mNameText->markDead(); @@ -2968,31 +2962,30 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) return; } - if (!mNameText) - { + if (!mNameText) + { mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject( LLHUDObject::LL_HUD_NAME_TAG) ); //mNameText->setMass(10.f); - mNameText->setSourceObject(this); + mNameText->setSourceObject(this); mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); - mNameText->setVisibleOffScreen(TRUE); - mNameText->setMaxLines(11); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - sNumVisibleChatBubbles++; - new_name = TRUE; - } + mNameText->setVisibleOffScreen(TRUE); + mNameText->setMaxLines(11); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + sNumVisibleChatBubbles++; + new_name = TRUE; + } - LLVector3 name_position = idleUpdateNameTagPosition(root_pos_last); - mNameText->setPositionAgent(name_position); + idleUpdateNameTagPosition(root_pos_last); idleUpdateNameTagText(new_name); idleUpdateNameTagAlpha(new_name, alpha); } void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) - { - LLNameValue *title = getNVPair("Title"); - LLNameValue* firstname = getNVPair("FirstName"); - LLNameValue* lastname = getNVPair("LastName"); +{ + LLNameValue *title = getNVPair("Title"); + LLNameValue* firstname = getNVPair("FirstName"); + LLNameValue* lastname = getNVPair("LastName"); // Avatars must have a first and last name if (!firstname || !lastname) return; @@ -3006,34 +2999,29 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) is_muted = false; } else - { + { is_muted = LLMuteList::getInstance()->isMuted(getID()); } bool is_friend = LLAvatarTracker::instance().isBuddy(getID()); bool is_cloud = getIsCloud(); - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { - if (is_appearance != mNameAppearance) - { - if (is_appearance) - { - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezEnteredAppearanceNotification",args); - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' entered appearance mode." << llendl; - } - else - { - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezLeftAppearanceNotification",args); - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left appearance mode." << llendl; - } - } - } + if (gSavedSettings.getBOOL("DebugAvatarRezTime") + && is_appearance != mNameAppearance) + { + LLSD args; + args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); + args["NAME"] = getFullname(); + if (is_appearance) + { + LLNotificationsUtil::add("AvatarRezEnteredAppearanceNotification",args); + llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' entered appearance mode." << llendl; + } + else + { + LLNotificationsUtil::add("AvatarRezLeftAppearanceNotification",args); + llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left appearance mode." << llendl; + } + } // Rebuild name tag if state change detected if (mNameString.empty() @@ -3043,39 +3031,39 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) || is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute - || is_appearance != mNameAppearance + || is_appearance != mNameAppearance || is_friend != mNameFriend || is_cloud != mNameCloud) - { + { LLColor4 name_tag_color = getNameTagColor(is_friend); clearNameTag(); if (is_away || is_muted || is_busy || is_appearance) - { + { std::string line; - if (is_away) - { - line += LLTrans::getString("AvatarAway"); + if (is_away) + { + line += LLTrans::getString("AvatarAway"); line += ", "; - } - if (is_busy) - { + } + if (is_busy) + { line += LLTrans::getString("AvatarBusy"); line += ", "; } if (is_muted) - { + { line += LLTrans::getString("AvatarMuted"); - line += ", "; - } + line += ", "; + } if (is_appearance) { line += LLTrans::getString("AvatarEditingAppearance"); line += ", "; - } + } if (is_cloud) - { + { line += LLTrans::getString("LoadingData"); line += ", "; } @@ -3087,12 +3075,12 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) if (sRenderGroupTitles && title && title->getString() && title->getString()[0] != '\0') - { + { std::string title_str = title->getString(); LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerifSmall()); - } + } static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames"); static LLUICachedControl<bool> show_usernames("NameTagShowUsernames"); @@ -3106,119 +3094,118 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) // and force a rebuild LLAvatarNameCache::get(getID(), boost::bind(&LLVOAvatar::clearNameTag, this)); - } + } // Might be blank if name not available yet, that's OK if (show_display_names) { addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerif()); - } + } // Suppress SLID display if display name matches exactly (ugh) if (show_usernames && !av_name.mIsDisplayNameDefault) - { + { // *HACK: Desaturate the color LLColor4 username_color = name_tag_color * 0.83f; addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerifSmall()); } - } + } else - { + { const LLFontGL* font = LLFontGL::getFontSansSerif(); - std::string full_name = - LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); + std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font); - } + } - mNameAway = is_away; - mNameBusy = is_busy; - mNameMute = is_muted; - mNameAppearance = is_appearance; - mNameFriend = is_friend; - mNameCloud = is_cloud; - mTitle = title ? title->getString() : ""; - LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); - new_name = TRUE; - } + mNameAway = is_away; + mNameBusy = is_busy; + mNameMute = is_muted; + mNameAppearance = is_appearance; + mNameFriend = is_friend; + mNameCloud = is_cloud; + mTitle = title ? title->getString() : ""; + LLStringFn::replace_ascii_controlchars(mTitle, LL_UNKNOWN_CHAR); + new_name = TRUE; + } if (mVisibleChat) - { - mNameText->setFont(LLFontGL::getFontSansSerif()); + { + mNameText->setFont(LLFontGL::getFontSansSerif()); mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - - char line[MAX_STRING]; /* Flawfinder: ignore */ - line[0] = '\0'; - std::deque<LLChat>::iterator chat_iter = mChats.begin(); - mNameText->clearString(); - - LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); - LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); - LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); - if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) - { - ++chat_iter; - } + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - for(; chat_iter != mChats.end(); ++chat_iter) - { - F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); - LLFontGL::StyleFlags style; - switch(chat_iter->mChatType) - { - case CHAT_TYPE_WHISPER: - style = LLFontGL::ITALIC; - break; - case CHAT_TYPE_SHOUT: - style = LLFontGL::BOLD; - break; - default: - style = LLFontGL::NORMAL; - break; - } - if (chat_fade_amt < 1.f) - { - F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); - } - else if (chat_fade_amt < 2.f) - { - F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); - } - else if (chat_fade_amt < 3.f) - { - // *NOTE: only remove lines down to minimum number - mNameText->addLine(chat_iter->mText, old_chat, style); - } - } - mNameText->setVisibleOffScreen(TRUE); + char line[MAX_STRING]; /* Flawfinder: ignore */ + line[0] = '\0'; + std::deque<LLChat>::iterator chat_iter = mChats.begin(); + mNameText->clearString(); - if (mTyping) - { - S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; - switch(dot_count) - { - case 1: - mNameText->addLine(".", new_chat); - break; - case 2: - mNameText->addLine("..", new_chat); - break; - case 3: - mNameText->addLine("...", new_chat); - break; - } + LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); + LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); + LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); + if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) + { + ++chat_iter; + } - } + for(; chat_iter != mChats.end(); ++chat_iter) + { + F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); + LLFontGL::StyleFlags style; + switch(chat_iter->mChatType) + { + case CHAT_TYPE_WHISPER: + style = LLFontGL::ITALIC; + break; + case CHAT_TYPE_SHOUT: + style = LLFontGL::BOLD; + break; + default: + style = LLFontGL::NORMAL; + break; } - else + if (chat_fade_amt < 1.f) { + F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); + } + else if (chat_fade_amt < 2.f) + { + F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); + } + else if (chat_fade_amt < 3.f) + { + // *NOTE: only remove lines down to minimum number + mNameText->addLine(chat_iter->mText, old_chat, style); + } + } + mNameText->setVisibleOffScreen(TRUE); + + if (mTyping) + { + S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; + switch(dot_count) + { + case 1: + mNameText->addLine(".", new_chat); + break; + case 2: + mNameText->addLine("..", new_chat); + break; + case 3: + mNameText->addLine("...", new_chat); + break; + } + + } + } + else + { // ...not using chat bubbles, just names mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - mNameText->setVisibleOffScreen(FALSE); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + mNameText->setVisibleOffScreen(FALSE); } } @@ -3241,8 +3228,8 @@ void LLVOAvatar::clearNameTag() { mNameString.clear(); if (mNameText) - { - mNameText->setLabel(""); + { + mNameText->setLabel(""); mNameText->setString( "" ); } } @@ -3270,34 +3257,45 @@ void LLVOAvatar::invalidateNameTags() if (avatar->isDead()) continue; avatar->clearNameTag(); - } } // Compute name tag position during idle update -LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) +void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) { LLQuaternion root_rot = mRoot.getWorldRotation(); + LLQuaternion inv_root_rot = ~root_rot; LLVector3 pixel_right_vec; LLVector3 pixel_up_vec; LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec); LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin(); camera_to_av.normalize(); - LLVector3 local_camera_at = camera_to_av * ~root_rot; + LLVector3 local_camera_at = camera_to_av * inv_root_rot; LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis(); local_camera_up.normalize(); - local_camera_up = local_camera_up * ~root_rot; + local_camera_up = local_camera_up * inv_root_rot; + + LLVector3 avatar_ellipsoid(mBodySize.mV[VX] * 0.4f, + mBodySize.mV[VY] * 0.4f, + mBodySize.mV[VZ] * NAMETAG_VERT_OFFSET_WEIGHT); - local_camera_up.scaleVec(mBodySize * 0.5f); - local_camera_at.scaleVec(mBodySize * 0.5f); + local_camera_up.scaleVec(avatar_ellipsoid); + local_camera_at.scaleVec(avatar_ellipsoid); - LLVector3 name_position = mRoot.getWorldPosition(); - name_position[VZ] -= mPelvisToFoot; - name_position[VZ] += (mBodySize[VZ]* 0.55f); + LLVector3 head_offset = (mHeadp->getLastWorldPosition() - mRoot.getLastWorldPosition()) * inv_root_rot; + + if (dist_vec(head_offset, mTargetRootToHeadOffset) > NAMETAG_UPDATE_THRESHOLD) + { + mTargetRootToHeadOffset = head_offset; + } + + mCurRootToHeadOffset = lerp(mCurRootToHeadOffset, mTargetRootToHeadOffset, LLCriticalDamp::getInterpolant(0.2f)); + + LLVector3 name_position = mRoot.getLastWorldPosition() + (mCurRootToHeadOffset * root_rot); name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av)); - name_position += pixel_up_vec * 15.f; + name_position += pixel_up_vec * NAMETAG_VERTICAL_SCREEN_OFFSET; - return name_position; + mNameText->setPositionAgent(name_position); } void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha) @@ -3333,7 +3331,7 @@ LLColor4 LLVOAvatar::getNameTagColor(bool is_friend) else { color_name = "NameTagMismatch"; - } + } } else { @@ -3370,9 +3368,9 @@ bool LLVOAvatar::isVisuallyMuted() static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit"); static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); - return LLMuteList::getInstance()->isMuted(getID()) || - (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || - (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); + return LLMuteList::getInstance()->isMuted(getID()) + || (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) + || (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); } //------------------------------------------------------------------------ @@ -3413,8 +3411,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } } - LLVector3d root_pos_global; - if (!mIsBuilt) { return FALSE; @@ -3428,7 +3424,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) { mTimeVisible.reset(); } - //-------------------------------------------------------------------- // the rest should only be done occasionally for far away avatars @@ -3823,10 +3818,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) if ( playSound ) { -// F32 gain = clamp_rescale( mSpeedAccum, -// AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED, -// AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); - const F32 STEP_VOLUME = 0.1f; const LLUUID& step_sound_id = getStepSound(); @@ -4043,13 +4034,6 @@ void LLVOAvatar::updateVisibility() { releaseMeshData(); } - // this breaks off-screen chat bubbles - //if (mNameText) - //{ - // mNameText->markDead(); - // mNameText = NULL; - // sNumVisibleChatBubbles--; - //} } mVisible = visible; @@ -4065,46 +4049,6 @@ bool LLVOAvatar::shouldAlphaMask() } -U32 LLVOAvatar::renderSkinnedAttachments() -{ - /*U32 num_indices = 0; - - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; - - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - const LLViewerObject* attached_object = (*attachment_iter); - if (attached_object && !attached_object->isHUDAttachment()) - { - const LLDrawable* drawable = attached_object->mDrawable; - if (drawable) - { - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - LLFace* face = drawable->getFace(i); - if (face->isState(LLFace::RIGGED)) - { - - } - } - } - } - - return num_indices;*/ - return 0; -} - //----------------------------------------------------------------------------- // renderSkinned() //----------------------------------------------------------------------------- @@ -4125,11 +4069,11 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) { //LOD changed or new mesh created, allocate new vertex buffer if needed if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4) { - updateMeshData(); + updateMeshData(); mDirtyMesh = 0; - mNeedsSkin = TRUE; - mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); - } + mNeedsSkin = TRUE; + mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); + } } if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) @@ -5790,36 +5734,34 @@ BOOL LLVOAvatar::updateJointLODs() F32 avatar_num_factor = clamp_rescale((F32)sNumVisibleAvatars, 8, 25, 1.f, avatar_num_min_factor); F32 area_scale = 0.16f; + if (isSelf()) { - if (isSelf()) - { - if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook()) - { - mAdjustedPixelArea = MAX_PIXEL_AREA; - } - else - { - mAdjustedPixelArea = mPixelArea*area_scale; - } - } - else if (mIsDummy) + if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook()) { mAdjustedPixelArea = MAX_PIXEL_AREA; } else { - // reported avatar pixel area is dependent on avatar render load, based on number of visible avatars - mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; + mAdjustedPixelArea = mPixelArea*area_scale; } + } + else if (mIsDummy) + { + mAdjustedPixelArea = MAX_PIXEL_AREA; + } + else + { + // reported avatar pixel area is dependent on avatar render load, based on number of visible avatars + mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; + } - // now select meshes to render based on adjusted pixel area - BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); - if (res) - { - sNumLODChangesThisFrame++; - dirtyMesh(2); - return TRUE; - } + // now select meshes to render based on adjusted pixel area + BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); + if (res) + { + sNumLODChangesThisFrame++; + dirtyMesh(2); + return TRUE; } return FALSE; @@ -6109,25 +6051,18 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO ) if ( pVObj ) { const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); - if ( pSkinData ) - { - const int jointCnt = pSkinData->mJointNames.size(); - bool fullRig = ( jointCnt>=20 ) ? true : false; - if ( fullRig ) + if (pSkinData + && pSkinData->mJointNames.size() > 20 // full rig + && pSkinData->mAlternateBindMatrix.size() > 0) + { + LLVOAvatar::resetJointPositionsToDefault(); + //Need to handle the repositioning of the cam, updating rig data etc during outfit editing + //This handles the case where we detach a replacement rig. + if ( gAgentCamera.cameraCustomizeAvatar() ) { - const int bindCnt = pSkinData->mAlternateBindMatrix.size(); - if ( bindCnt > 0 ) - { - LLVOAvatar::resetJointPositionsToDefault(); - //Need to handle the repositioning of the cam, updating rig data etc during outfit editing - //This handles the case where we detach a replacement rig. - if ( gAgentCamera.cameraCustomizeAvatar() ) - { - gAgent.unpauseAnimation(); - //Still want to refocus on head bone - gAgentCamera.changeCameraToCustomizeAvatar(); - } - } + gAgent.unpauseAnimation(); + //Still want to refocus on head bone + gAgentCamera.changeCameraToCustomizeAvatar(); } } } @@ -6281,11 +6216,7 @@ void LLVOAvatar::getOffObject() at_axis.mV[VZ] = 0.f; at_axis.normalize(); gAgent.resetAxes(at_axis); - - //reset orientation -// mRoot.setRotation(avWorldRot); gAgentCamera.setThirdPersonHeadOffset(LLVector3(0.f, 0.f, 1.f)); - gAgentCamera.setSitCamera(LLUUID::null); } } @@ -6335,7 +6266,6 @@ LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) const } else { -// return LLColor4( .5f, .5f, .5f, .5f ); return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color } } @@ -7067,10 +6997,6 @@ LLBBox LLVOAvatar::getHUDBBox() const return bbox; } -void LLVOAvatar::rebuildHUD() -{ -} - //----------------------------------------------------------------------------- // onFirstTEMessageReceived() //----------------------------------------------------------------------------- @@ -7192,7 +7118,10 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) && baked_index != BAKED_SKIRT) { setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, - LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, + TRUE, + LLViewerTexture::BOOST_NONE, + LLViewerTexture::LOD_TEXTURE)); } } @@ -7483,11 +7412,6 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_ // Called when baked texture is loaded and also when we start up with a baked texture void LLVOAvatar::useBakedTexture( const LLUUID& id ) { - /* if(id == head_baked->getID()) - mHeadBakedLoaded = TRUE; - mLastHeadBakedID = id; - mHeadMesh0.setTexture( head_baked ); - mHeadMesh1.setTexture( head_baked ); */ for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); @@ -7718,111 +7642,111 @@ LLVOAvatar::LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo() std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer()); } -//----------------------------------------------------------------------------- -// LLVOAvatarBoneInfo::parseXml() -//----------------------------------------------------------------------------- -BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) -{ - if (node->hasName("bone")) - { - mIsJoint = TRUE; - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!node->getFastAttributeString(name_string, mName)) - { - llwarns << "Bone without name" << llendl; - return FALSE; - } - } - else if (node->hasName("collision_volume")) - { - mIsJoint = FALSE; - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!node->getFastAttributeString(name_string, mName)) - { - mName = "Collision Volume"; - } - } - else - { - llwarns << "Invalid node " << node->getName() << llendl; - return FALSE; - } - - static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); - if (!node->getFastAttributeVector3(pos_string, mPos)) - { - llwarns << "Bone without position" << llendl; - return FALSE; - } - - static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); - if (!node->getFastAttributeVector3(rot_string, mRot)) - { - llwarns << "Bone without rotation" << llendl; - return FALSE; - } - - static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); - if (!node->getFastAttributeVector3(scale_string, mScale)) - { - llwarns << "Bone without scale" << llendl; - return FALSE; - } - - if (mIsJoint) - { - static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); - if (!node->getFastAttributeVector3(pivot_string, mPivot)) - { - llwarns << "Bone without pivot" << llendl; - return FALSE; - } - } - - // parse children - LLXmlTreeNode* child; - for( child = node->getFirstChild(); child; child = node->getNextChild() ) - { - LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo; - if (!child_info->parseXml(child)) - { - delete child_info; - return FALSE; - } - mChildList.push_back(child_info); - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// LLVOAvatarSkeletonInfo::parseXml() -//----------------------------------------------------------------------------- -BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) -{ - static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); - if (!node->getFastAttributeS32(num_bones_string, mNumBones)) - { - llwarns << "Couldn't find number of bones." << llendl; - return FALSE; - } - - static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); - node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); - - LLXmlTreeNode* child; - for( child = node->getFirstChild(); child; child = node->getNextChild() ) - { - LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo; - if (!info->parseXml(child)) - { - delete info; - llwarns << "Error parsing bone in skeleton file" << llendl; - return FALSE; - } - mBoneInfoList.push_back(info); - } - return TRUE; -} +////----------------------------------------------------------------------------- +//// LLVOAvatarBoneInfo::parseXml() +////----------------------------------------------------------------------------- +//BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) +//{ +// if (node->hasName("bone")) +// { +// mIsJoint = TRUE; +// static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); +// if (!node->getFastAttributeString(name_string, mName)) +// { +// llwarns << "Bone without name" << llendl; +// return FALSE; +// } +// } +// else if (node->hasName("collision_volume")) +// { +// mIsJoint = FALSE; +// static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); +// if (!node->getFastAttributeString(name_string, mName)) +// { +// mName = "Collision Volume"; +// } +// } +// else +// { +// llwarns << "Invalid node " << node->getName() << llendl; +// return FALSE; +// } +// +// static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); +// if (!node->getFastAttributeVector3(pos_string, mPos)) +// { +// llwarns << "Bone without position" << llendl; +// return FALSE; +// } +// +// static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); +// if (!node->getFastAttributeVector3(rot_string, mRot)) +// { +// llwarns << "Bone without rotation" << llendl; +// return FALSE; +// } +// +// static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); +// if (!node->getFastAttributeVector3(scale_string, mScale)) +// { +// llwarns << "Bone without scale" << llendl; +// return FALSE; +// } +// +// if (mIsJoint) +// { +// static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); +// if (!node->getFastAttributeVector3(pivot_string, mPivot)) +// { +// llwarns << "Bone without pivot" << llendl; +// return FALSE; +// } +// } +// +// // parse children +// LLXmlTreeNode* child; +// for( child = node->getFirstChild(); child; child = node->getNextChild() ) +// { +// LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo; +// if (!child_info->parseXml(child)) +// { +// delete child_info; +// return FALSE; +// } +// mChildList.push_back(child_info); +// } +// return TRUE; +//} +// +////----------------------------------------------------------------------------- +//// LLVOAvatarSkeletonInfo::parseXml() +////----------------------------------------------------------------------------- +//BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) +//{ +// static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); +// if (!node->getFastAttributeS32(num_bones_string, mNumBones)) +// { +// llwarns << "Couldn't find number of bones." << llendl; +// return FALSE; +// } +// +// static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); +// node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); +// +// LLXmlTreeNode* child; +// for( child = node->getFirstChild(); child; child = node->getNextChild() ) +// { +// LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo; +// if (!info->parseXml(child)) +// { +// delete info; +// llwarns << "Error parsing bone in skeleton file" << llendl; +// return FALSE; +// } +// mBoneInfoList.push_back(info); +// } +// return TRUE; +//} //----------------------------------------------------------------------------- // parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index dd0317f555..e84acd51ff 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -66,8 +66,9 @@ class LLVoiceVisualizer; class LLHUDNameTag; class LLHUDEffectSpiral; class LLTexGlobalColor; -class LLVOAvatarBoneInfo; -class LLVOAvatarSkeletonInfo; +struct LLVOAvatarBoneInfo; +struct LLVOAvatarChildJoint; +struct LLVOAvatarSkeletonInfo; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLVOAvatar @@ -232,7 +233,7 @@ public: void idleUpdateWindEffect(); void idleUpdateNameTag(const LLVector3& root_pos_last); void idleUpdateNameTagText(BOOL new_name); - LLVector3 idleUpdateNameTagPosition(const LLVector3& root_pos_last); + void idleUpdateNameTagPosition(const LLVector3& root_pos_last); void idleUpdateNameTagAlpha(BOOL new_name, F32 alpha); LLColor4 getNameTagColor(bool is_friend); void clearNameTag(); @@ -317,6 +318,8 @@ public: F32 mLastPelvisToFoot; F32 mPelvisFixup; F32 mLastPelvisFixup; + LLVector3 mCurRootToHeadOffset; + LLVector3 mTargetRootToHeadOffset; LLVector3 mHeadOffset; // current head position LLViewerJoint mRoot; @@ -325,7 +328,7 @@ protected: void buildCharacter(); virtual BOOL loadAvatar(); - BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); + BOOL setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info); private: BOOL mIsBuilt; // state of deferred character building @@ -369,7 +372,7 @@ public: //-------------------------------------------------------------------- private: static LLXmlTree sXMLTree; // avatar config file - static LLXmlTree sSkeletonXMLTree; // avatar skeleton file + static LLXMLNodePtr sSkeletonXMLTree; // avatar skeleton file /** Skeleton ** ** @@ -387,7 +390,6 @@ public: U32 renderRigid(); U32 renderSkinned(EAvatarRenderPass pass); F32 getLastSkinTime() { return mLastSkinTime; } - U32 renderSkinnedAttachments(); U32 renderTransparent(BOOL first_pass); void renderCollisionVolumes(); static void deleteCachedImages(bool clearAll=true); @@ -735,7 +737,6 @@ public: public: BOOL hasHUDAttachment() const; LLBBox getHUDBBox() const; - void rebuildHUD(); void resetHUDAttachments(); BOOL canAttachMoreObjects() const; BOOL canAttachMoreObjects(U32 n) const; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index c523a78b22..fc499bfe9c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -4678,11 +4678,6 @@ void LLPipeline::rebuildPools() } max_count--; } - - if (isAgentAvatarValid()) - { - gAgentAvatarp->rebuildHUD(); - } } void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) -- cgit v1.2.3 From 2eb0096dd7f173debc27c155c57969ae5cb67682 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 5 Apr 2012 17:50:22 -0700 Subject: added support for LLInitParam::Lazy<scalar> to support lazy-initialized non-param-block values --- indra/llxuixml/llinitparam.h | 94 +++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 6fffb73acd..6c054b934b 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -369,11 +369,30 @@ namespace LLInitParam class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed }; + struct IS_BLOCK {}; + struct NOT_BLOCK {}; + + // these templates allow us to distinguish between template parameters + // that derive from BaseBlock and those that don't + template<typename T, typename BLOCK_IDENTIFIER = void> + struct IsBlock + { + static const bool value = false; + typedef NOT_BLOCK value_t; + }; + + template<typename T> + struct IsBlock<T, typename T::baseblock_base_class_t> + { + static const bool value = true; + typedef IS_BLOCK value_t; + }; + class BaseBlock { public: //TODO: implement in terms of owned_ptr - template<typename T> + template<typename T, bool IS_BLOCK = true> class Lazy { public: @@ -404,7 +423,7 @@ namespace LLInitParam } } - Lazy<T>& operator = (const Lazy<T>& other) + Lazy& operator = (const Lazy& other) { if (other.mPtr) { @@ -462,6 +481,7 @@ namespace LLInitParam mutable T* mPtr; }; + // "Multiple" constraint types, put here in root class to avoid ambiguity during use struct AnyAmount { @@ -611,19 +631,6 @@ namespace LLInitParam }; - // these templates allow us to distinguish between template parameters - // that derive from BaseBlock and those that don't - template<typename T, typename BLOCK_IDENTIFIER = void> - struct IsBlock - { - static const bool value = false; - }; - - template<typename T> - struct IsBlock<T, typename T::baseblock_base_class_t> - { - static const bool value = true; - }; template<typename T, typename NAME_VALUE_LOOKUP, bool VALUE_IS_BLOCK = IsBlock<T>::value> class ParamValue : public NAME_VALUE_LOOKUP @@ -805,7 +812,7 @@ namespace LLInitParam template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>, bool HAS_MULTIPLE_VALUES = false, - bool VALUE_IS_BLOCK = IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> + bool VALUE_IS_BLOCK = IsBlock<T>::value> class TypedParam : public Param, public ParamValue<T, NAME_VALUE_LOOKUP> @@ -1034,7 +1041,7 @@ namespace LLInitParam } else { - typed_param.serializeBlock(parser, name_stack, &static_cast<const BaseBlock&>(*static_cast<const self_t*>(diff_param))); + typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param)); } } @@ -1582,7 +1589,7 @@ namespace LLInitParam friend class ChoiceBlock<DERIVED_BLOCK>; typedef Alternative<T, NAME_VALUE_LOOKUP> self_t; - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<T>::value> super_t; typedef typename super_t::value_assignment_t value_assignment_t; using super_t::operator =; @@ -1700,7 +1707,7 @@ namespace LLInitParam class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<T>::value> super_t; typedef typename super_t::value_assignment_t value_assignment_t; using super_t::operator(); @@ -1729,7 +1736,7 @@ namespace LLInitParam class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<T>::value> super_t; typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t; typedef typename super_t::value_assignment_t value_assignment_t; @@ -1765,7 +1772,7 @@ namespace LLInitParam class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBlock<T>::value> super_t; typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t; typedef typename super_t::container_t container_t; typedef typename super_t::value_assignment_t value_assignment_t; @@ -1948,20 +1955,21 @@ namespace LLInitParam }; template<typename T, typename BLOCK_IDENTIFIER> - struct IsBlock<ParamValue<BaseBlock::Lazy<T>, TypeValues<BaseBlock::Lazy<T> > > , BLOCK_IDENTIFIER> + struct IsBlock<BaseBlock::Lazy<T, true>, BLOCK_IDENTIFIER> { - static const bool value = true;//IsBlock<T>::value; + static const bool value = true; }; - template<typename T> - struct ParamCompare<BaseBlock::Lazy<T>, false> + template<typename T, typename BLOCK_IDENTIFIER> + struct IsBlock<BaseBlock::Lazy<T, false>, BLOCK_IDENTIFIER> { - static bool equals(const T&a, const T &b) - { - return a == b; - } + static const bool value = false; + }; - static bool equals(const BaseBlock::Lazy<T>& a, const BaseBlock::Lazy<T>& b) + template<typename T, bool IS_BLOCK> + struct ParamCompare<BaseBlock::Lazy<T, IS_BLOCK>, false> + { + static bool equals(const BaseBlock::Lazy<T, IS_BLOCK>& a, const BaseBlock::Lazy<T, IS_BLOCK>& b) { if (a.empty() || b.empty()) return false; return a.get() == b.get(); @@ -1969,14 +1977,14 @@ namespace LLInitParam }; - template<typename T, bool VALUE_IS_BLOCK> - class ParamValue <BaseBlock::Lazy<T>, - TypeValues<BaseBlock::Lazy<T> >, - VALUE_IS_BLOCK> + template<typename T> + class ParamValue <BaseBlock::Lazy<T, true>, + TypeValues<BaseBlock::Lazy<T, true> >, + true> : public TypeValues<T> { public: - typedef ParamValue <BaseBlock::Lazy<T>, TypeValues<BaseBlock::Lazy<T> >, false> self_t; + typedef ParamValue <BaseBlock::Lazy<T, true>, TypeValues<BaseBlock::Lazy<T, true> >, true> self_t; typedef const T& value_assignment_t; typedef T value_t; @@ -1985,7 +1993,7 @@ namespace LLInitParam mValidated(false) {} - ParamValue(const BaseBlock::Lazy<T>& other) + ParamValue(const BaseBlock::Lazy<T, true>& other) : mValue(other), mValidated(false) {} @@ -2010,11 +2018,6 @@ namespace LLInitParam return mValue.get(); } - operator const BaseBlock&() const - { - return mValue.get(); - } - operator value_assignment_t() const { return mValue.get(); @@ -2030,11 +2033,14 @@ namespace LLInitParam return mValue.get().deserializeBlock(p, name_stack_range, new_name); } - void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const { if (mValue.empty()) return; - mValue.get().serializeBlock(p, name_stack, diff_block); + const BaseBlock* base_block = (diff_block && !diff_block->mValue.empty()) + ? &(diff_block->mValue.get()) + : NULL; + mValue.get().serializeBlock(p, name_stack, base_block); } bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const @@ -2063,7 +2069,7 @@ namespace LLInitParam mutable bool mValidated; // lazy validation flag private: - BaseBlock::Lazy<T> mValue; + BaseBlock::Lazy<T, true> mValue; }; template <> -- cgit v1.2.3 From 6dd7029942dcc381d670657e0c4bb7d8dcd24594 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 5 Apr 2012 18:11:45 -0700 Subject: optimized Lazy<T> params - don't generate block when checking validity or merging --- indra/llxuixml/llinitparam.h | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 6c054b934b..1f0dec5d94 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -436,6 +436,12 @@ namespace LLInitParam return *this; } + bool operator==(const Lazy& other) const + { + if (empty() || other.empty()) return false; + return *mPtr == *other.mPtr; + } + bool empty() const { return mPtr == NULL; @@ -1966,17 +1972,6 @@ namespace LLInitParam static const bool value = false; }; - template<typename T, bool IS_BLOCK> - struct ParamCompare<BaseBlock::Lazy<T, IS_BLOCK>, false> - { - static bool equals(const BaseBlock::Lazy<T, IS_BLOCK>& a, const BaseBlock::Lazy<T, IS_BLOCK>& b) - { - if (a.empty() || b.empty()) return false; - return a.get() == b.get(); - } - }; - - template<typename T> class ParamValue <BaseBlock::Lazy<T, true>, TypeValues<BaseBlock::Lazy<T, true> >, @@ -2045,19 +2040,17 @@ namespace LLInitParam bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const { - if (mValue.empty()) return false; - return mValue.get().inspectBlock(p, name_stack, min_count, max_count); } bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) { - return mValue.get().mergeBlock(block_data, source.getValue(), overwrite); + return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite); } bool validateBlock(bool emit_errors = true) const { - return mValue.get().validateBlock(emit_errors); + return mValue.empty() || mValue.get().validateBlock(emit_errors); } static BlockDescriptor& getBlockDescriptor() -- cgit v1.2.3 From 7996857500004ed9b717e049423c52be96db9191 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Thu, 12 Apr 2012 00:43:37 +0300 Subject: CHUI-80 FIXED Implemented volume indicator pop-up. It is invoked by clicking on any speaking indicator except yours. --- indra/newview/CMakeLists.txt | 2 + indra/newview/llavataractions.cpp | 26 +++ indra/newview/llavataractions.h | 10 + indra/newview/llfloatervoicevolume.cpp | 209 +++++++++++++++++++++ indra/newview/llfloatervoicevolume.h | 35 ++++ indra/newview/llinspectavatar.cpp | 3 +- indra/newview/lloutputmonitorctrl.cpp | 12 ++ indra/newview/lloutputmonitorctrl.h | 1 + indra/newview/llviewerfloaterreg.cpp | 2 + .../skins/default/xui/en/floater_voice_volume.xml | 59 ++++++ 10 files changed, 357 insertions(+), 2 deletions(-) create mode 100644 indra/newview/llfloatervoicevolume.cpp create mode 100644 indra/newview/llfloatervoicevolume.h create mode 100644 indra/newview/skins/default/xui/en/floater_voice_volume.xml (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f85b943c70..6197856512 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -244,6 +244,7 @@ set(viewer_SOURCE_FILES llfloateruipreview.cpp llfloaterurlentry.cpp llfloatervoiceeffect.cpp + llfloatervoicevolume.cpp llfloaterwebcontent.cpp llfloaterwebprofile.cpp llfloaterwhitelistentry.cpp @@ -800,6 +801,7 @@ set(viewer_HEADER_FILES llfloateruipreview.h llfloaterurlentry.h llfloatervoiceeffect.h + llfloatervoicevolume.h llfloaterwebcontent.h llfloaterwebprofile.h llfloaterwhitelistentry.h diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 9a7cdcfa21..ac14ec2cc0 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -808,6 +808,26 @@ void LLAvatarActions::toggleBlock(const LLUUID& id) } } +// static +void LLAvatarActions::toggleMuteVoice(const LLUUID& id) +{ + std::string name; + gCacheName->getFullName(id, name); // needed for mute + + LLMuteList* mute_list = LLMuteList::getInstance(); + bool is_muted = mute_list->isMuted(id, LLMute::flagVoiceChat); + + LLMute mute(id, name, LLMute::AGENT); + if (!is_muted) + { + mute_list->add(mute, LLMute::flagVoiceChat); + } + else + { + mute_list->remove(mute, LLMute::flagVoiceChat); + } +} + // static bool LLAvatarActions::canOfferTeleport(const LLUUID& id) { @@ -1022,6 +1042,12 @@ bool LLAvatarActions::isBlocked(const LLUUID& id) return LLMuteList::getInstance()->isMuted(id, name); } +// static +bool LLAvatarActions::isVoiceMuted(const LLUUID& id) +{ + return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat); +} + // static bool LLAvatarActions::canBlock(const LLUUID& id) { diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 748b7cb3d1..e5dad74fc8 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -123,6 +123,11 @@ public: */ static void toggleBlock(const LLUUID& id); + /** + * Block/unblock the avatar voice. + */ + static void toggleMuteVoice(const LLUUID& id); + /** * Return true if avatar with "id" is a friend */ @@ -133,6 +138,11 @@ public: */ static bool isBlocked(const LLUUID& id); + /** + * @return true if the avatar voice is blocked + */ + static bool isVoiceMuted(const LLUUID& id); + /** * @return true if you can block the avatar */ diff --git a/indra/newview/llfloatervoicevolume.cpp b/indra/newview/llfloatervoicevolume.cpp new file mode 100644 index 0000000000..87b388b30a --- /dev/null +++ b/indra/newview/llfloatervoicevolume.cpp @@ -0,0 +1,209 @@ +/** + * @file llfloatervoicevolume.cpp + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatervoicevolume.h" + +// Linden libraries +#include "llavatarname.h" +#include "llavatarnamecache.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "lltextbox.h" + +// viewer files +#include "llagent.h" +#include "llavataractions.h" +#include "llinspect.h" +#include "lltransientfloatermgr.h" +#include "llvoiceclient.h" + +class LLAvatarName; + +////////////////////////////////////////////////////////////////////////////// +// LLFloaterVoiceVolume +////////////////////////////////////////////////////////////////////////////// + +// Avatar Inspector, a small information window used when clicking +// on avatar names in the 2D UI and in the ambient inspector widget for +// the 3D world. +class LLFloaterVoiceVolume : public LLInspect, LLTransientFloater +{ + friend class LLFloaterReg; + +public: + // avatar_id - Avatar ID for which to show information + // Inspector will be positioned relative to current mouse position + LLFloaterVoiceVolume(const LLSD& avatar_id); + virtual ~LLFloaterVoiceVolume(); + + /*virtual*/ BOOL postBuild(void); + + // Because floater is single instance, need to re-parse data on each spawn + // (for example, inspector about same avatar but in different position) + /*virtual*/ void onOpen(const LLSD& avatar_id); + + /*virtual*/ LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; } + +private: + // Set the volume slider to this user's current client-side volume setting, + // hiding/disabling if the user is not nearby. + void updateVolumeControls(); + + void onClickMuteVolume(); + void onVolumeChange(const LLSD& data); + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + +private: + LLUUID mAvatarID; + // Need avatar name information to spawn friend add request + LLAvatarName mAvatarName; +}; + +LLFloaterVoiceVolume::LLFloaterVoiceVolume(const LLSD& sd) +: LLInspect(LLSD()) // single_instance, doesn't really need key +, mAvatarID() // set in onOpen() *Note: we used to show partner's name but we dont anymore --angela 3rd Dec* +, mAvatarName() +{ + LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::GLOBAL, this); + LLTransientFloater::init(this); +} + +LLFloaterVoiceVolume::~LLFloaterVoiceVolume() +{ + LLTransientFloaterMgr::getInstance()->removeControlView(this); +} + +/*virtual*/ +BOOL LLFloaterVoiceVolume::postBuild(void) +{ + getChild<LLUICtrl>("mute_btn")->setCommitCallback( + boost::bind(&LLFloaterVoiceVolume::onClickMuteVolume, this) ); + + getChild<LLUICtrl>("volume_slider")->setCommitCallback( + boost::bind(&LLFloaterVoiceVolume::onVolumeChange, this, _2)); + + return TRUE; +} + + +// Multiple calls to showInstance("floater_voice_volume", foo) will provide different +// LLSD for foo, which we will catch here. +//virtual +void LLFloaterVoiceVolume::onOpen(const LLSD& data) +{ + // Start open animation + LLInspect::onOpen(data); + + // Extract appropriate avatar id + mAvatarID = data["avatar_id"]; + + LLUI::positionViewNearMouse(this); + + getChild<LLUICtrl>("avatar_name")->setValue(""); + updateVolumeControls(); + + LLAvatarNameCache::get(mAvatarID, + boost::bind(&LLFloaterVoiceVolume::onAvatarNameCache, this, _1, _2)); +} + +void LLFloaterVoiceVolume::updateVolumeControls() +{ + bool voice_enabled = LLVoiceClient::getInstance()->getVoiceEnabled(mAvatarID); + + LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); + LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); + + // Do not display volume slider and mute button if it + // is ourself or we are not in a voice channel together + if (!voice_enabled || (mAvatarID == gAgent.getID())) + { + mute_btn->setVisible(false); + volume_slider->setVisible(false); + } + else + { + mute_btn->setVisible(true); + volume_slider->setVisible(true); + + // By convention, we only display and toggle voice mutes, not all mutes + bool is_muted = LLAvatarActions::isVoiceMuted(mAvatarID); + bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); + + mute_btn->setEnabled(!is_linden); + mute_btn->setValue(is_muted); + + volume_slider->setEnabled(!is_muted); + + F32 volume; + if (is_muted) + { + // it's clearer to display their volume as zero + volume = 0.f; + } + else + { + // actual volume + volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); + } + volume_slider->setValue((F64)volume); + } + +} + +void LLFloaterVoiceVolume::onClickMuteVolume() +{ + LLAvatarActions::toggleMuteVoice(mAvatarID); + updateVolumeControls(); +} + +void LLFloaterVoiceVolume::onVolumeChange(const LLSD& data) +{ + F32 volume = (F32)data.asReal(); + LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); +} + +void LLFloaterVoiceVolume::onAvatarNameCache( + const LLUUID& agent_id, + const LLAvatarName& av_name) +{ + if (agent_id != mAvatarID) + { + return; + } + + getChild<LLUICtrl>("avatar_name")->setValue(av_name.getCompleteName()); + mAvatarName = av_name; +} + +////////////////////////////////////////////////////////////////////////////// +// LLFloaterVoiceVolumeUtil +////////////////////////////////////////////////////////////////////////////// +void LLFloaterVoiceVolumeUtil::registerFloater() +{ + LLFloaterReg::add("floater_voice_volume", "floater_voice_volume.xml", + &LLFloaterReg::build<LLFloaterVoiceVolume>); +} diff --git a/indra/newview/llfloatervoicevolume.h b/indra/newview/llfloatervoicevolume.h new file mode 100644 index 0000000000..8fcf7f250b --- /dev/null +++ b/indra/newview/llfloatervoicevolume.h @@ -0,0 +1,35 @@ +/** + * @file llfloatervoicevolume.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERVOICEVOLUME_H +#define LL_LLFLOATERVOICEVOLUME_H + +namespace LLFloaterVoiceVolumeUtil +{ + // Register with LLFloaterReg + void registerFloater(); +} + +#endif // LL_LLFLOATERVOICEVOLUME_H diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 17d0b0ffbb..b2a8c6e3e6 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -558,8 +558,7 @@ void LLInspectAvatar::updateVolumeSlider() getChild<LLUICtrl>("volume_slider")->setVisible(true); // By convention, we only display and toggle voice mutes, not all mutes - bool is_muted = LLMuteList::getInstance()-> - isMuted(mAvatarID, LLMute::flagVoiceChat); + bool is_muted = LLAvatarActions::isVoiceMuted(mAvatarID); LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 85626d8783..096e714981 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -28,6 +28,7 @@ #include "lloutputmonitorctrl.h" // library includes +#include "llfloaterreg.h" #include "llui.h" // viewer includes @@ -241,6 +242,17 @@ void LLOutputMonitorCtrl::draw() gl_rect_2d(0, monh, monw, 0, sColorBound, FALSE); } +// virtual +BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) +{ + if (mSpeakerId != gAgentID) + { + LLFloaterReg::showInstance("floater_voice_volume", LLSD().with("avatar_id", mSpeakerId)); + } + + return TRUE; +} + void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/) { if (speaker_id.isNull() && mSpeakerId.notNull()) diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 2d23753d46..7b02e84744 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -68,6 +68,7 @@ public: // llview overrides virtual void draw(); + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); void setPower(F32 val); F32 getPower(F32 val) const { return mPower; } diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index bb870f7651..685ef44921 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -110,6 +110,7 @@ #include "llfloatertranslationsettings.h" #include "llfloateruipreview.h" #include "llfloatervoiceeffect.h" +#include "llfloatervoicevolume.h" #include "llfloaterwhitelistentry.h" #include "llfloaterwindowsize.h" #include "llfloaterworldmap.h" @@ -220,6 +221,7 @@ void LLViewerFloaterReg::registerFloaters() LLInspectGroupUtil::registerFloater(); LLInspectObjectUtil::registerFloater(); LLInspectRemoteObjectUtil::registerFloater(); + LLFloaterVoiceVolumeUtil::registerFloater(); LLNotificationsUI::registerFloater(); LLFloaterDisplayNameUtil::registerFloater(); diff --git a/indra/newview/skins/default/xui/en/floater_voice_volume.xml b/indra/newview/skins/default/xui/en/floater_voice_volume.xml new file mode 100644 index 0000000000..9346295d5b --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_voice_volume.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- + Not can_close / no title to avoid window chrome + Single instance - only have one at a time, recycle it each spawn +--> +<floater + legacy_header_height="25" + bevel_style="in" + bg_opaque_image="Inspector_Background" + can_close="false" + can_minimize="false" + height="90" + layout="topleft" + name="floater_voice_volume" + single_instance="true" + sound_flags="0" + title="VOICE VOLUME" + visible="true" + width="245"> + <text + follows="top|left|right" + font="SansSerifSmall" + height="21" + left="10" + name="avatar_name" + parse_urls="false" + top="35" + text_color="White" + translate="false" + use_ellipses="true" + value="TestString PleaseIgnore" + width="225" /> + <slider + follows="top|left" + height="23" + increment="0.01" + left="1" + max_val="0.95" + min_val="0.05" + name="volume_slider" + show_text="false" + tool_tip="Voice volume" + top_pad="0" + value="0.5" + width="200" /> + <button + follows="top|left" + height="16" + image_disabled="Audio_Off" + image_disabled_selected="AudioMute_Off" + image_hover_selected="AudioMute_Over" + image_selected="AudioMute_Off" + image_unselected="Audio_Off" + is_toggle="true" + left_pad="0" + top_delta="4" + name="mute_btn" + width="16" /> +</floater> -- cgit v1.2.3 From 4f526f12e6332307c8d3105e5a4f6e35f2dbd3d7 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Fri, 6 Apr 2012 19:29:53 +0300 Subject: CHUI-77 WIP Moved setting filter label to XML. --- indra/newview/llpanelpeople.cpp | 5 ----- indra/newview/skins/default/xui/en/panel_people.xml | 14 ++++---------- 2 files changed, 4 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 238834aa92..2d665e9bf3 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -1016,11 +1016,6 @@ void LLPanelPeople::onTabSelected(const LLSD& param) updateButtons(); showFriendsAccordionsIfNeeded(); - - if (GROUP_TAB_NAME == tab_name) - mFilterEditor->setLabel(getString("groups_filter_label")); - else - mFilterEditor->setLabel(getString("people_filter_label")); } void LLPanelPeople::onAvatarListDoubleClicked(LLUICtrl* ctrl) diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index f61b0b3dbd..5da87456f1 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -38,12 +38,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="no_filtered_friends_msg"> Didn't find what you're looking for? Try [secondlife:///app/search/people/[SEARCH_TERM] Search]. </string> - <string - name="people_filter_label" - value="Filter People" /> - <string - name="groups_filter_label" - value="Filter Groups" /> <!-- *WORKAROUND: for group_list.no_items_msg & group_list.no_filtered_items_msg attributes. They are not defined as translatable in VLT. See EXT-5931 @@ -104,7 +98,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M height="23" layout="topleft" left="3" - label="Filter" + label="Filter People" max_length_chars="300" name="nearby_filter_input" text_color="Black" @@ -253,7 +247,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M height="23" layout="topleft" left="3" - label="Filter" + label="Filter People" max_length_chars="300" name="friends_filter_input" text_color="Black" @@ -410,7 +404,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M height="23" layout="topleft" left="3" - label="Filter" + label="Filter Groups" max_length_chars="300" name="groups_filter_input" text_color="Black" @@ -533,7 +527,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M height="23" layout="topleft" left="3" - label="Filter" + label="Filter People" max_length_chars="300" name="recent_filter_input" text_color="Black" -- cgit v1.2.3 From fff9567a67ded34471fd17af9c50bc1d307e7b19 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 6 Apr 2012 09:40:59 -0700 Subject: further LLInitParam cleanup changed bool template parameter to IS_BLOCK and NOT_BLOCK types moved addParam to BlockDescriptor moved init outside of param element constructors for faster construction --- indra/llui/llsdparam.cpp | 6 +- indra/llui/lluiimage.h | 4 +- indra/llxuixml/llinitparam.cpp | 59 +++++++------- indra/llxuixml/llinitparam.h | 177 ++++++++++++++++++++++++----------------- 4 files changed, 137 insertions(+), 109 deletions(-) (limited to 'indra') diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index 0e29873bb0..828f809452 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -313,7 +313,7 @@ namespace LLInitParam { // LLSD specialization // block param interface - bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) + bool ParamValue<LLSD, TypeValues<LLSD>, NOT_BLOCK>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) { LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack); @@ -328,12 +328,12 @@ namespace LLInitParam } //static - void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) + void ParamValue<LLSD, TypeValues<LLSD>, NOT_BLOCK>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) { p.writeValue<LLSD::String>(sd.asString(), name_stack); } - void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const + void ParamValue<LLSD, TypeValues<LLSD>, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const { // read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) Parser::name_stack_t stack; diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h index f07e8fa746..b9b90fee71 100644 --- a/indra/llui/lluiimage.h +++ b/indra/llui/lluiimage.h @@ -92,7 +92,7 @@ protected: namespace LLInitParam { template<> - class ParamValue<LLUIImage*, TypeValues<LLUIImage*> > + class ParamValue<LLUIImage*, TypeValues<LLUIImage*>, NOT_BLOCK > : public CustomParamValue<LLUIImage*> { typedef boost::add_reference<boost::add_const<LLUIImage*>::type>::type T_const_ref; @@ -100,7 +100,7 @@ namespace LLInitParam public: Optional<std::string> name; - ParamValue(LLUIImage* const& image) + ParamValue(LLUIImage* const& image = NULL) : super_t(image) { updateBlockFromValue(false); diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp index db72aa19b9..3cf145cdde 100644 --- a/indra/llxuixml/llinitparam.cpp +++ b/indra/llxuixml/llinitparam.cpp @@ -112,6 +112,35 @@ namespace LLInitParam std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams)); } + void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name) + { + // create a copy of the param descriptor in mAllParams + // so other data structures can store a pointer to it + mAllParams.push_back(in_param); + ParamDescriptorPtr param(mAllParams.back()); + + std::string name(char_name); + if ((size_t)param->mParamHandle > mMaxParamOffset) + { + llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl; + } + + if (name.empty()) + { + mUnnamedParams.push_back(param); + } + else + { + // don't use insert, since we want to overwrite existing entries + mNamedParams[name] = param; + } + + if (param->mValidationFunc) + { + mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); + } + } + BlockDescriptor::BlockDescriptor() : mMaxParamOffset(0), mInitializationState(UNINITIALIZED), @@ -358,36 +387,6 @@ namespace LLInitParam return false; } - //static - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name) - { - // create a copy of the param descriptor in mAllParams - // so other data structures can store a pointer to it - block_data.mAllParams.push_back(in_param); - ParamDescriptorPtr param(block_data.mAllParams.back()); - - std::string name(char_name); - if ((size_t)param->mParamHandle > block_data.mMaxParamOffset) - { - llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl; - } - - if (name.empty()) - { - block_data.mUnnamedParams.push_back(param); - } - else - { - // don't use insert, since we want to overwrite existing entries - block_data.mNamedParams[name] = param; - } - - if (param->mValidationFunc) - { - block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); - } - } - void BaseBlock::addSynonym(Param& param, const std::string& synonym) { BlockDescriptor& block_data = mostDerivedBlockDescriptor(); diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 1f0dec5d94..dbf2fdaa73 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -354,6 +354,7 @@ namespace LLInitParam } EInitializationState; void aggregateBlockData(BlockDescriptor& src_block_data); + void addParam(ParamDescriptorPtr param, const char* name); typedef boost::unordered_map<const std::string, ParamDescriptorPtr> param_map_t; typedef std::vector<ParamDescriptorPtr> param_list_t; @@ -377,22 +378,23 @@ namespace LLInitParam template<typename T, typename BLOCK_IDENTIFIER = void> struct IsBlock { - static const bool value = false; typedef NOT_BLOCK value_t; }; template<typename T> struct IsBlock<T, typename T::baseblock_base_class_t> { - static const bool value = true; typedef IS_BLOCK value_t; }; class BaseBlock { public: + typedef IS_BLOCK IS_BLOCK; + typedef NOT_BLOCK NOT_BLOCK; + //TODO: implement in terms of owned_ptr - template<typename T, bool IS_BLOCK = true> + template<typename T, typename BLOCK_T = IS_BLOCK> class Lazy { public: @@ -487,7 +489,6 @@ namespace LLInitParam mutable T* mPtr; }; - // "Multiple" constraint types, put here in root class to avoid ambiguity during use struct AnyAmount { @@ -572,8 +573,6 @@ namespace LLInitParam return false; } - static void addParam(BlockDescriptor& block_data, ParamDescriptorPtr param, const char* name); - ParamDescriptorPtr findParamDescriptor(const Param& param); // take all provided params from other and apply to self @@ -638,7 +637,7 @@ namespace LLInitParam }; - template<typename T, typename NAME_VALUE_LOOKUP, bool VALUE_IS_BLOCK = IsBlock<T>::value> + template<typename T, typename NAME_VALUE_LOOKUP, typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t> class ParamValue : public NAME_VALUE_LOOKUP { public: @@ -694,14 +693,14 @@ namespace LLInitParam }; template<typename T, typename NAME_VALUE_LOOKUP> - class ParamValue<T, NAME_VALUE_LOOKUP, true> + class ParamValue<T, NAME_VALUE_LOOKUP, IS_BLOCK> : public T, public NAME_VALUE_LOOKUP { public: typedef const T& value_assignment_t; typedef T value_t; - typedef ParamValue<T, NAME_VALUE_LOOKUP, true> self_t; + typedef ParamValue<T, NAME_VALUE_LOOKUP, IS_BLOCK> self_t; ParamValue() : T(), @@ -758,13 +757,13 @@ namespace LLInitParam }; template<typename NAME_VALUE_LOOKUP> - class ParamValue<std::string, NAME_VALUE_LOOKUP, false> + class ParamValue<std::string, NAME_VALUE_LOOKUP, NOT_BLOCK> : public NAME_VALUE_LOOKUP { public: typedef const std::string& value_assignment_t; typedef std::string value_t; - typedef ParamValue<std::string, NAME_VALUE_LOOKUP, false> self_t; + typedef ParamValue<std::string, NAME_VALUE_LOOKUP, NOT_BLOCK> self_t; ParamValue(): mValue() {} ParamValue(value_assignment_t other) : mValue(other) {} @@ -818,7 +817,7 @@ namespace LLInitParam template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>, bool HAS_MULTIPLE_VALUES = false, - bool VALUE_IS_BLOCK = IsBlock<T>::value> + typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t> class TypedParam : public Param, public ParamValue<T, NAME_VALUE_LOOKUP> @@ -836,15 +835,7 @@ namespace LLInitParam { if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { - ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( - block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - &mergeWith, - &deserializeParam, - &serializeParam, - validate_func, - &inspectParam, - min_count, max_count)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); + init(block_descriptor, validate_func, min_count, max_count, name); } } @@ -964,18 +955,31 @@ namespace LLInitParam } return false; } + private: + void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + block_descriptor.addParam(param_descriptor, name); + } }; // parameter that is a block template <typename T, typename NAME_VALUE_LOOKUP> - class TypedParam<T, NAME_VALUE_LOOKUP, false, true> + class TypedParam<T, NAME_VALUE_LOOKUP, false, IS_BLOCK> : public Param, public ParamValue<T, NAME_VALUE_LOOKUP> { public: typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; typedef typename param_value_t::value_assignment_t value_assignment_t; - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true> self_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_BLOCK> self_t; using param_value_t::operator(); @@ -985,15 +989,7 @@ namespace LLInitParam { if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { - ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( - block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - &mergeWith, - &deserializeParam, - &serializeParam, - validate_func, - &inspectParam, - min_count, max_count)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); + init(block_descriptor, validate_func, min_count, max_count, name); } } @@ -1130,15 +1126,29 @@ namespace LLInitParam } return false; } + + private: + void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + block_descriptor.addParam(param_descriptor, name); + } }; // container of non-block parameters template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> - class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false> + class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> : public Param { public: - typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false> self_t; + typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t; typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP> param_value_t; typedef typename std::vector<param_value_t> container_t; typedef const container_t& value_assignment_t; @@ -1152,15 +1162,8 @@ namespace LLInitParam if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { - ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( - block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - &mergeWith, - &deserializeParam, - &serializeParam, - validate_func, - &inspectParam, - min_count, max_count)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); + init(block_descriptor, validate_func, min_count, max_count, name); + } } @@ -1322,15 +1325,29 @@ namespace LLInitParam } container_t mValues; + + private: + void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + block_descriptor.addParam(param_descriptor, name); + } }; // container of block parameters template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> - class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true> + class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_BLOCK> : public Param { public: - typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true> self_t; + typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_BLOCK> self_t; typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP> param_value_t; typedef typename std::vector<param_value_t> container_t; typedef const container_t& value_assignment_t; @@ -1343,15 +1360,7 @@ namespace LLInitParam if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { - ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( - block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - &mergeWith, - &deserializeParam, - &serializeParam, - validate_func, - &inspectParam, - min_count, max_count)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); + init(block_descriptor, validate_func, min_count, max_count, name); } } @@ -1516,6 +1525,20 @@ namespace LLInitParam } container_t mValues; + + private: + void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + block_descriptor.addParam(param_descriptor, name); + } }; template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock> @@ -1595,7 +1618,7 @@ namespace LLInitParam friend class ChoiceBlock<DERIVED_BLOCK>; typedef Alternative<T, NAME_VALUE_LOOKUP> self_t; - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<T>::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, typename IsBlock<T>::value_t> super_t; typedef typename super_t::value_assignment_t value_assignment_t; using super_t::operator =; @@ -1713,8 +1736,8 @@ namespace LLInitParam class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<T>::value> super_t; - typedef typename super_t::value_assignment_t value_assignment_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, typename IsBlock<T>::value_t> super_t; + typedef typename super_t::value_assignment_t value_assignment_t; using super_t::operator(); using super_t::operator =; @@ -1742,7 +1765,7 @@ namespace LLInitParam class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<T>::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, typename IsBlock<T>::value_t> super_t; typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t; typedef typename super_t::value_assignment_t value_assignment_t; @@ -1778,7 +1801,7 @@ namespace LLInitParam class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBlock<T>::value> super_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, true, typename IsBlock<T>::value_t> super_t; typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t; typedef typename super_t::container_t container_t; typedef typename super_t::value_assignment_t value_assignment_t; @@ -1825,7 +1848,7 @@ namespace LLInitParam NULL, NULL, 0, S32_MAX)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); + block_descriptor.addParam(param_descriptor, name); } } @@ -1853,7 +1876,7 @@ namespace LLInitParam } protected: - template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, bool is_block> + template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, typename is_block> void changeDefault(TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>& param, typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_assignment_t value) { @@ -1911,7 +1934,7 @@ namespace LLInitParam typename NAME_VALUE_LOOKUP> class ParamValue <BatchBlock<DERIVED_BLOCK, BASE_BLOCK>, NAME_VALUE_LOOKUP, - true> + IS_BLOCK> : public NAME_VALUE_LOOKUP, protected BatchBlock<DERIVED_BLOCK, BASE_BLOCK> { @@ -1961,25 +1984,31 @@ namespace LLInitParam }; template<typename T, typename BLOCK_IDENTIFIER> - struct IsBlock<BaseBlock::Lazy<T, true>, BLOCK_IDENTIFIER> + struct IsBlock<BaseBlock::Lazy<T, IS_BLOCK>, BLOCK_IDENTIFIER> { - static const bool value = true; + typedef IS_BLOCK value_t; }; template<typename T, typename BLOCK_IDENTIFIER> - struct IsBlock<BaseBlock::Lazy<T, false>, BLOCK_IDENTIFIER> + struct IsBlock<BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_IDENTIFIER> { - static const bool value = false; + typedef NOT_BLOCK value_t; }; + //template<typename T, typename BLOCK_IDENTIFIER> + //struct IsBlock<BaseBlock::Lazy<T, void>, BLOCK_IDENTIFIER> + //{ + // typedef typename IsBlock<T>::value_t value_t; + //}; + template<typename T> - class ParamValue <BaseBlock::Lazy<T, true>, - TypeValues<BaseBlock::Lazy<T, true> >, - true> + class ParamValue <BaseBlock::Lazy<T, IS_BLOCK>, + TypeValues<BaseBlock::Lazy<T, IS_BLOCK> >, + IS_BLOCK> : public TypeValues<T> { public: - typedef ParamValue <BaseBlock::Lazy<T, true>, TypeValues<BaseBlock::Lazy<T, true> >, true> self_t; + typedef ParamValue <BaseBlock::Lazy<T, IS_BLOCK>, TypeValues<BaseBlock::Lazy<T, IS_BLOCK> >, IS_BLOCK> self_t; typedef const T& value_assignment_t; typedef T value_t; @@ -1988,7 +2017,7 @@ namespace LLInitParam mValidated(false) {} - ParamValue(const BaseBlock::Lazy<T, true>& other) + ParamValue(const BaseBlock::Lazy<T, IS_BLOCK>& other) : mValue(other), mValidated(false) {} @@ -2062,18 +2091,18 @@ namespace LLInitParam mutable bool mValidated; // lazy validation flag private: - BaseBlock::Lazy<T, true> mValue; + BaseBlock::Lazy<T, IS_BLOCK> mValue; }; template <> class ParamValue <LLSD, TypeValues<LLSD>, - false> + NOT_BLOCK> : public TypeValues<LLSD>, public BaseBlock { public: - typedef ParamValue<LLSD, TypeValues<LLSD>, false> self_t; + typedef ParamValue<LLSD, TypeValues<LLSD>, NOT_BLOCK> self_t; typedef const LLSD& value_assignment_t; ParamValue() -- cgit v1.2.3 From 5ed0819309dcb9352de51795a0e9338fd7de844a Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Tue, 10 Apr 2012 18:03:55 +0300 Subject: CHUI-77 WIP Made per-tab filters work. --- indra/newview/llpanelpeople.cpp | 77 ++++++++++++++-------- indra/newview/llpanelpeople.h | 7 +- .../newview/skins/default/xui/en/panel_people.xml | 2 +- 3 files changed, 52 insertions(+), 34 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 2d665e9bf3..aceee7cf23 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -492,9 +492,6 @@ public: LLPanelPeople::LLPanelPeople() : LLPanel(), - mFilterSubString(LLStringUtil::null), - mFilterSubStringOrig(LLStringUtil::null), - mFilterEditor(NULL), mTabContainer(NULL), mOnlineFriendList(NULL), mAllFriendList(NULL), @@ -567,11 +564,15 @@ void LLPanelPeople::onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LL BOOL LLPanelPeople::postBuild() { - mFilterEditor = getChild<LLFilterEditor>("filter_input"); - mFilterEditor->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); + getChild<LLFilterEditor>("nearby_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); + getChild<LLFilterEditor>("friends_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); + getChild<LLFilterEditor>("groups_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); + getChild<LLFilterEditor>("recent_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); mTabContainer = getChild<LLTabContainer>("tabs"); mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2)); + mSavedFilters.resize(mTabContainer->getTabCount()); + mSavedOriginalFilters.resize(mTabContainer->getTabCount()); LLPanel* friends_tab = getChild<LLPanel>(FRIENDS_TAB_NAME); // updater is active only if panel is visible to user. @@ -680,9 +681,11 @@ void LLPanelPeople::updateFriendListHelpText() if (no_friends_text->getVisible()) { //update help text for empty lists - std::string message_name = mFilterSubString.empty() ? "no_friends_msg" : "no_filtered_friends_msg"; + const std::string& filter = mSavedOriginalFilters[mTabContainer->getCurrentPanelIndex()]; + + std::string message_name = filter.empty() ? "no_friends_msg" : "no_filtered_friends_msg"; LLStringUtil::format_map_t args; - args["[SEARCH_TERM]"] = LLURI::escape(mFilterSubStringOrig); + args["[SEARCH_TERM]"] = LLURI::escape(filter); no_friends_text->setText(getString(message_name, args)); } } @@ -973,40 +976,56 @@ void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save void LLPanelPeople::onFilterEdit(const std::string& search_string) { - mFilterSubStringOrig = search_string; - LLStringUtil::trimHead(mFilterSubStringOrig); + const S32 cur_tab_idx = mTabContainer->getCurrentPanelIndex(); + std::string& filter = mSavedOriginalFilters[cur_tab_idx]; + std::string& saved_filter = mSavedFilters[cur_tab_idx]; + + filter = search_string; + LLStringUtil::trimHead(filter); + // Searches are case-insensitive - std::string search_upper = mFilterSubStringOrig; + std::string search_upper = filter; LLStringUtil::toUpper(search_upper); - if (mFilterSubString == search_upper) + if (saved_filter == search_upper) return; - mFilterSubString = search_upper; + saved_filter = search_upper; - //store accordion tabs state before any manipulation with accordion tabs - if(!mFilterSubString.empty()) + // Apply new filter to the current tab. + const std::string cur_tab = getActiveTabName(); + if (cur_tab == NEARBY_TAB_NAME) { - notifyChildren(LLSD().with("action","store_state")); + mNearbyList->setNameFilter(filter); } + else if (cur_tab == FRIENDS_TAB_NAME) + { + // store accordion tabs opened/closed state before any manipulation with accordion tabs + if (!saved_filter.empty()) + { + notifyChildren(LLSD().with("action","store_state")); + } + mOnlineFriendList->setNameFilter(filter); + mAllFriendList->setNameFilter(filter); - // Apply new filter. - mNearbyList->setNameFilter(mFilterSubStringOrig); - mOnlineFriendList->setNameFilter(mFilterSubStringOrig); - mAllFriendList->setNameFilter(mFilterSubStringOrig); - mRecentList->setNameFilter(mFilterSubStringOrig); - mGroupList->setNameFilter(mFilterSubStringOrig); - - setAccordionCollapsedByUser("tab_online", false); - setAccordionCollapsedByUser("tab_all", false); + setAccordionCollapsedByUser("tab_online", false); + setAccordionCollapsedByUser("tab_all", false); + showFriendsAccordionsIfNeeded(); - showFriendsAccordionsIfNeeded(); - - //restore accordion tabs state _after_ all manipulations... - if(mFilterSubString.empty()) + // restore accordion tabs state _after_ all manipulations + if(saved_filter.empty()) + { + notifyChildren(LLSD().with("action","restore_state")); + } + } + else if (cur_tab == GROUP_TAB_NAME) + { + mGroupList->setNameFilter(filter); + } + else if (cur_tab == RECENT_TAB_NAME) { - notifyChildren(LLSD().with("action","restore_state")); + mRecentList->setNameFilter(filter); } } diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 684dcdeb6d..765e62ffa6 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -132,7 +132,6 @@ private: bool isAccordionCollapsedByUser(LLUICtrl* acc_tab); bool isAccordionCollapsedByUser(const std::string& name); - LLFilterEditor* mFilterEditor; LLTabContainer* mTabContainer; LLAvatarList* mOnlineFriendList; LLAvatarList* mAllFriendList; @@ -141,13 +140,13 @@ private: LLGroupList* mGroupList; LLNetMap* mMiniMap; + std::vector<std::string> mSavedOriginalFilters; + std::vector<std::string> mSavedFilters; + Updater* mFriendListUpdater; Updater* mNearbyListUpdater; Updater* mRecentListUpdater; Updater* mButtonsUpdater; - - std::string mFilterSubString; - std::string mFilterSubStringOrig; }; #endif //LL_LLPANELPEOPLE_H diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 5da87456f1..ad4a840106 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -365,7 +365,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M height="450" left="13" name="no_friends_help_text" - top="10" + top="37" width="293" wrap="true" /> </panel> -- cgit v1.2.3 From 60510292b08d69eb7053621ce6b3ac60d599a4fb Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 11 Apr 2012 13:04:02 -0700 Subject: CHUI-89 FIX Make nametags appear consistently next to avatar heads --- indra/newview/llhudnametag.cpp | 279 ++++++------------ indra/newview/llhudnametag.h | 2 - indra/newview/llspatialpartition.cpp | 4 +- indra/newview/llviewermenu.cpp | 9 - indra/newview/llvoavatar.cpp | 546 +++++++++++++++-------------------- indra/newview/llvoavatar.h | 15 +- indra/newview/pipeline.cpp | 5 - 7 files changed, 331 insertions(+), 529 deletions(-) (limited to 'indra') diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 482294c8a6..cf55954d7d 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -187,45 +187,42 @@ BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3& + (y_pixel_vec * screen_offset.mV[VY]); - //if (mUseBubble) - { - LLVector3 bg_pos = render_position - + (F32)mOffsetY * y_pixel_vec - - (width_vec / 2.f) - - (height_vec); - //LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); + LLVector3 bg_pos = render_position + + (F32)mOffsetY * y_pixel_vec + - (width_vec / 2.f) + - (height_vec); + //LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); - LLVector3 v[] = - { - bg_pos, - bg_pos + width_vec, - bg_pos + width_vec + height_vec, - bg_pos + height_vec, - }; + LLVector3 v[] = + { + bg_pos, + bg_pos + width_vec, + bg_pos + width_vec + height_vec, + bg_pos + height_vec, + }; - if (debug_render) - { - gGL.begin(LLRender::LINE_STRIP); - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[2].mV); - gGL.vertex3fv(v[3].mV); - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[2].mV); - gGL.end(); - } + if (debug_render) + { + gGL.begin(LLRender::LINE_STRIP); + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[2].mV); + gGL.vertex3fv(v[3].mV); + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[2].mV); + gGL.end(); + } - LLVector3 dir = end-start; - F32 a, b, t; + LLVector3 dir = end-start; + F32 a, b, t; - if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE) || - LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, a, b, t, FALSE) ) + if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE) || + LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, a, b, t, FALSE) ) + { + if (t <= 1.f) { - if (t <= 1.f) - { - intersection = start + dir*t; - return TRUE; - } + intersection = start + dir*t; + return TRUE; } } @@ -241,12 +238,6 @@ void LLHUDNameTag::render() } } -void LLHUDNameTag::renderForSelect() -{ - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - renderText(TRUE); -} - void LLHUDNameTag::renderText(BOOL for_select) { if (!mVisible || mHidden) @@ -336,142 +327,53 @@ void LLHUDNameTag::renderText(BOOL for_select) LLCoordGL screen_pos; LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE); - LLVector2 screen_offset; -// if (!mUseBubble) -// { -// screen_offset = mPositionOffset; -// } -// else -// { - screen_offset = updateScreenPos(mPositionOffset); -// } + LLVector2 screen_offset = updateScreenPos(mPositionOffset); LLVector3 render_position = mPositionAgent + (x_pixel_vec * screen_offset.mV[VX]) + (y_pixel_vec * screen_offset.mV[VY]); -// if (mUseBubble) + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + LLUI::pushMatrix(); { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - LLUI::pushMatrix(); - { - LLVector3 bg_pos = render_position - + (F32)mOffsetY * y_pixel_vec - - (width_vec / 2.f) - - (height_vec); - LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); + LLVector3 bg_pos = render_position + + (F32)mOffsetY * y_pixel_vec + - (width_vec / 2.f) + - (height_vec); + LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); - if (for_select) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - S32 name = mSourceObject->mGLName; - LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name); - gGL.color4ubv(coloru.mV); - gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); - LLUI::popMatrix(); - return; - } - else - { - gGL.getTexUnit(0)->bind(imagep->getImage()); + if (for_select) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + S32 name = mSourceObject->mGLName; + LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name); + gGL.color4ubv(coloru.mV); + gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); + LLUI::popMatrix(); + return; + } + else + { + gGL.getTexUnit(0)->bind(imagep->getImage()); - gGL.color4fv(bg_color.mV); - gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); + gGL.color4fv(bg_color.mV); + gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); - if ( mLabelSegments.size()) - { - LLUI::pushMatrix(); - { - gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); - LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; - LLVector3 label_offset = height_vec - label_height; - LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); - gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); - } - LLUI::popMatrix(); - } - } - - BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f; - BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f); - - // draw line segments pointing to parent object - if (!mOffscreen && (outside_width || outside_height)) + if ( mLabelSegments.size()) { LLUI::pushMatrix(); { - gGL.color4fv(bg_color.mV); - LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec); - target_pos += (width_vec / 2.f); - target_pos += mVertAlignment == ALIGN_VERT_CENTER ? (height_vec * 0.5f) : LLVector3::zero; - target_pos -= 3.f * x_pixel_vec; - target_pos -= 6.f * y_pixel_vec; - LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]); - gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec); + gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); + LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; + LLVector3 label_offset = height_vec - label_height; + LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); + gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); } LLUI::popMatrix(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE); - - LLVector3 box_center_offset; - box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f); - LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]); - gGL.color4fv(bg_color.mV); - LLUI::setLineWidth(2.0); - gGL.begin(LLRender::LINES); - { - if (outside_width) - { - LLVector3 vert; - // draw line in x then y - if (mPositionOffset.mV[VX] < 0.f) - { - // start at right edge - vert = width_vec * 0.5f; - gGL.vertex3fv(vert.mV); - } - else - { - // start at left edge - vert = width_vec * -0.5f; - gGL.vertex3fv(vert.mV); - } - vert = -mPositionOffset.mV[VX] * x_pixel_vec; - gGL.vertex3fv(vert.mV); - gGL.vertex3fv(vert.mV); - vert -= mPositionOffset.mV[VY] * y_pixel_vec; - vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); - gGL.vertex3fv(vert.mV); - } - else - { - LLVector3 vert; - // draw line in y then x - if (mPositionOffset.mV[VY] < 0.f) - { - // start at top edge - vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); - gGL.vertex3fv(vert.mV); - } - else - { - // start at bottom edge - vert = (height_vec * -0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); - gGL.vertex3fv(vert.mV); - } - vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec; - vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); - gGL.vertex3fv(vert.mV); - } - } - gGL.end(); - LLUI::setLineWidth(1.0); - } } - LLUI::popMatrix(); } + LLUI::popMatrix(); F32 y_offset = (F32)mOffsetY; @@ -874,29 +776,26 @@ void LLHUDNameTag::updateAll() for (r_it = sVisibleTextObjects.rbegin(); r_it != sVisibleTextObjects.rend(); ++r_it) { LLHUDNameTag* textp = (*r_it); -// if (textp->mUseBubble) -// { - if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE) - { - textp->setLOD(3); - } - else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE) - { - textp->setLOD(2); - } - else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE) - { - textp->setLOD(1); - } - else - { - textp->setLOD(0); - } - textp->updateSize(); - // find on-screen position and initialize collision rectangle - textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero); - current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight()); -// } + if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE) + { + textp->setLOD(3); + } + else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE) + { + textp->setLOD(2); + } + else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE) + { + textp->setLOD(1); + } + else + { + textp->setLOD(0); + } + textp->updateSize(); + // find on-screen position and initialize collision rectangle + textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero); + current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight()); } LLStat* camera_vel_stat = LLViewerCamera::getInstance()->getVelocityStat(); @@ -914,20 +813,12 @@ void LLHUDNameTag::updateAll() { LLHUDNameTag* src_textp = (*src_it); -// if (!src_textp->mUseBubble) -// { -// continue; -// } VisibleTextObjectIterator dst_it = src_it; ++dst_it; for (; dst_it != sVisibleTextObjects.end(); ++dst_it) { LLHUDNameTag* dst_textp = (*dst_it); -// if (!dst_textp->mUseBubble) -// { -// continue; -// } if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect)) { LLRectf intersect_rect = src_textp->mSoftScreenRect; @@ -976,10 +867,6 @@ void LLHUDNameTag::updateAll() VisibleTextObjectIterator this_object_it; for (this_object_it = sVisibleTextObjects.begin(); this_object_it != sVisibleTextObjects.end(); ++this_object_it) { -// if (!(*this_object_it)->mUseBubble) -// { -// continue; -// } (*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC)); } } @@ -1037,10 +924,6 @@ void LLHUDNameTag::addPickable(std::set<LLViewerObject*> &pick_list) VisibleTextObjectIterator text_it; for (text_it = sVisibleTextObjects.begin(); text_it != sVisibleTextObjects.end(); ++text_it) { -// if (!(*text_it)->mUseBubble) -// { -// continue; -// } pick_list.insert((*text_it)->mSourceObject); } } diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h index 3325c22def..72647d5b26 100644 --- a/indra/newview/llhudnametag.h +++ b/indra/newview/llhudnametag.h @@ -118,7 +118,6 @@ public: /*virtual*/ void markDead(); friend class LLHUDObject; /*virtual*/ F32 getDistance() const { return mLastDistance; } - //void setUseBubble(BOOL use_bubble) { mUseBubble = use_bubble; } S32 getLOD() { return mLOD; } BOOL getVisible() { return mVisible; } BOOL getHidden() const { return mHidden; } @@ -136,7 +135,6 @@ protected: LLHUDNameTag(const U8 type); /*virtual*/ void render(); - /*virtual*/ void renderForSelect(); void renderText(BOOL for_select); static void updateAll(); void setLOD(S32 lod); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 5d196a465f..1333862855 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2774,7 +2774,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color) { - gGL.diffuseColor4fv(color.mV); + gGL.color4fv(color.mV); gGL.begin(LLRender::LINES); { gGL.vertex3fv((position - LLVector3(size, 0.f, 0.f)).mV); @@ -3904,7 +3904,7 @@ void renderAgentTarget(LLVOAvatar* avatar) if (avatar->isSelf()) { renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); - renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); + renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(0, 1, 0, 0.8f)); renderCrossHairs(avatar->mRoot.getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f)); renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f)); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 99540ccce9..ae32683c99 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3190,15 +3190,6 @@ bool enable_freeze_eject(const LLSD& avatar_id) return new_value; } - -void login_done(S32 which, void *user) -{ - llinfos << "Login done " << which << llendl; - - LLPanelLogin::closePanel(); -} - - bool callback_leave_group(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index bc7f5a9744..ef59e366e8 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -62,6 +62,7 @@ #include "llhudmanager.h" #include "llhudnametag.h" #include "llhudtext.h" // for mText/mDebugText +#include "llinitparam.h" #include "llkeyframefallmotion.h" #include "llkeyframestandmotion.h" #include "llkeyframewalkmotion.h" @@ -193,6 +194,9 @@ const S32 MAX_BUBBLE_CHAT_LENGTH = DB_CHAT_MSG_STR_LEN; const S32 MAX_BUBBLE_CHAT_UTTERANCES = 12; const F32 CHAT_FADE_TIME = 8.0; const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f; +const F32 NAMETAG_UPDATE_THRESHOLD = 0.3f; +const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f; +const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.15f; const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); @@ -234,11 +238,11 @@ class LLVOAvatarBoneInfo public: LLVOAvatarBoneInfo() : mIsJoint(FALSE) {} ~LLVOAvatarBoneInfo() - { +{ std::for_each(mChildList.begin(), mChildList.end(), DeletePointer()); } BOOL parseXml(LLXmlTreeNode* node); - + private: std::string mName; BOOL mIsJoint; @@ -1656,7 +1660,7 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename) // parse the file //------------------------------------------------------------------------- BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE ); - + if (!parsesuccess) { llerrs << "Can't parse skeleton file: " << filename << llendl; @@ -1790,10 +1794,10 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) { LLVOAvatarBoneInfo *info = *iter; if (!setupBone(info, NULL, current_volume_num, current_joint_num)) - { - llerrs << "Error parsing bone in skeleton file" << llendl; - return FALSE; - } + { + llerrs << "Error parsing bone in skeleton file" << llendl; + return FALSE; + } } return TRUE; @@ -2922,43 +2926,43 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) return; } - BOOL new_name = FALSE; - if (visible_chat != mVisibleChat) - { - mVisibleChat = visible_chat; - new_name = TRUE; - } + BOOL new_name = FALSE; + if (visible_chat != mVisibleChat) + { + mVisibleChat = visible_chat; + new_name = TRUE; + } - if (sRenderGroupTitles != mRenderGroupTitles) - { - mRenderGroupTitles = sRenderGroupTitles; - new_name = TRUE; - } + if (sRenderGroupTitles != mRenderGroupTitles) + { + mRenderGroupTitles = sRenderGroupTitles; + new_name = TRUE; + } - // First Calculate Alpha - // If alpha > 0, create mNameText if necessary, otherwise delete it - F32 alpha = 0.f; - if (mAppAngle > 5.f) + // First Calculate Alpha + // If alpha > 0, create mNameText if necessary, otherwise delete it + F32 alpha = 0.f; + if (mAppAngle > 5.f) + { + const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; + if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) { - const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; - if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) - { - alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; - } - else - { - // ...not fading, full alpha - alpha = 1.f; - } + alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; } - else if (mAppAngle > 2.f) + else { - // far away is faded out also - alpha = (mAppAngle-2.f)/3.f; + // ...not fading, full alpha + alpha = 1.f; } + } + else if (mAppAngle > 2.f) + { + // far away is faded out also + alpha = (mAppAngle-2.f)/3.f; + } if (alpha <= 0.f) - { + { if (mNameText) { mNameText->markDead(); @@ -2968,31 +2972,30 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) return; } - if (!mNameText) - { + if (!mNameText) + { mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject( LLHUDObject::LL_HUD_NAME_TAG) ); //mNameText->setMass(10.f); - mNameText->setSourceObject(this); + mNameText->setSourceObject(this); mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); - mNameText->setVisibleOffScreen(TRUE); - mNameText->setMaxLines(11); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - sNumVisibleChatBubbles++; - new_name = TRUE; - } + mNameText->setVisibleOffScreen(TRUE); + mNameText->setMaxLines(11); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + sNumVisibleChatBubbles++; + new_name = TRUE; + } - LLVector3 name_position = idleUpdateNameTagPosition(root_pos_last); - mNameText->setPositionAgent(name_position); + idleUpdateNameTagPosition(root_pos_last); idleUpdateNameTagText(new_name); idleUpdateNameTagAlpha(new_name, alpha); } void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) - { - LLNameValue *title = getNVPair("Title"); - LLNameValue* firstname = getNVPair("FirstName"); - LLNameValue* lastname = getNVPair("LastName"); +{ + LLNameValue *title = getNVPair("Title"); + LLNameValue* firstname = getNVPair("FirstName"); + LLNameValue* lastname = getNVPair("LastName"); // Avatars must have a first and last name if (!firstname || !lastname) return; @@ -3006,34 +3009,29 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) is_muted = false; } else - { + { is_muted = LLMuteList::getInstance()->isMuted(getID()); } bool is_friend = LLAvatarTracker::instance().isBuddy(getID()); bool is_cloud = getIsCloud(); - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { - if (is_appearance != mNameAppearance) - { - if (is_appearance) - { - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezEnteredAppearanceNotification",args); - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' entered appearance mode." << llendl; - } - else - { - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezLeftAppearanceNotification",args); - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left appearance mode." << llendl; - } - } - } + if (gSavedSettings.getBOOL("DebugAvatarRezTime") + && is_appearance != mNameAppearance) + { + LLSD args; + args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); + args["NAME"] = getFullname(); + if (is_appearance) + { + LLNotificationsUtil::add("AvatarRezEnteredAppearanceNotification",args); + llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' entered appearance mode." << llendl; + } + else + { + LLNotificationsUtil::add("AvatarRezLeftAppearanceNotification",args); + llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left appearance mode." << llendl; + } + } // Rebuild name tag if state change detected if (mNameString.empty() @@ -3043,39 +3041,39 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) || is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute - || is_appearance != mNameAppearance + || is_appearance != mNameAppearance || is_friend != mNameFriend || is_cloud != mNameCloud) - { + { LLColor4 name_tag_color = getNameTagColor(is_friend); clearNameTag(); if (is_away || is_muted || is_busy || is_appearance) - { + { std::string line; - if (is_away) - { - line += LLTrans::getString("AvatarAway"); + if (is_away) + { + line += LLTrans::getString("AvatarAway"); line += ", "; - } - if (is_busy) - { + } + if (is_busy) + { line += LLTrans::getString("AvatarBusy"); line += ", "; } if (is_muted) - { + { line += LLTrans::getString("AvatarMuted"); - line += ", "; - } + line += ", "; + } if (is_appearance) { line += LLTrans::getString("AvatarEditingAppearance"); line += ", "; - } + } if (is_cloud) - { + { line += LLTrans::getString("LoadingData"); line += ", "; } @@ -3087,12 +3085,12 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) if (sRenderGroupTitles && title && title->getString() && title->getString()[0] != '\0') - { + { std::string title_str = title->getString(); LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerifSmall()); - } + } static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames"); static LLUICachedControl<bool> show_usernames("NameTagShowUsernames"); @@ -3106,119 +3104,118 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) // and force a rebuild LLAvatarNameCache::get(getID(), boost::bind(&LLVOAvatar::clearNameTag, this)); - } + } // Might be blank if name not available yet, that's OK if (show_display_names) { addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerif()); - } + } // Suppress SLID display if display name matches exactly (ugh) if (show_usernames && !av_name.mIsDisplayNameDefault) - { + { // *HACK: Desaturate the color LLColor4 username_color = name_tag_color * 0.83f; addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerifSmall()); } - } + } else - { + { const LLFontGL* font = LLFontGL::getFontSansSerif(); - std::string full_name = - LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); + std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font); - } + } - mNameAway = is_away; - mNameBusy = is_busy; - mNameMute = is_muted; - mNameAppearance = is_appearance; - mNameFriend = is_friend; - mNameCloud = is_cloud; - mTitle = title ? title->getString() : ""; - LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); - new_name = TRUE; - } + mNameAway = is_away; + mNameBusy = is_busy; + mNameMute = is_muted; + mNameAppearance = is_appearance; + mNameFriend = is_friend; + mNameCloud = is_cloud; + mTitle = title ? title->getString() : ""; + LLStringFn::replace_ascii_controlchars(mTitle, LL_UNKNOWN_CHAR); + new_name = TRUE; + } if (mVisibleChat) - { - mNameText->setFont(LLFontGL::getFontSansSerif()); + { + mNameText->setFont(LLFontGL::getFontSansSerif()); mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - - char line[MAX_STRING]; /* Flawfinder: ignore */ - line[0] = '\0'; - std::deque<LLChat>::iterator chat_iter = mChats.begin(); - mNameText->clearString(); - - LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); - LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); - LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); - if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) - { - ++chat_iter; - } + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - for(; chat_iter != mChats.end(); ++chat_iter) - { - F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); - LLFontGL::StyleFlags style; - switch(chat_iter->mChatType) - { - case CHAT_TYPE_WHISPER: - style = LLFontGL::ITALIC; - break; - case CHAT_TYPE_SHOUT: - style = LLFontGL::BOLD; - break; - default: - style = LLFontGL::NORMAL; - break; - } - if (chat_fade_amt < 1.f) - { - F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); - } - else if (chat_fade_amt < 2.f) - { - F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); - } - else if (chat_fade_amt < 3.f) - { - // *NOTE: only remove lines down to minimum number - mNameText->addLine(chat_iter->mText, old_chat, style); - } - } - mNameText->setVisibleOffScreen(TRUE); + char line[MAX_STRING]; /* Flawfinder: ignore */ + line[0] = '\0'; + std::deque<LLChat>::iterator chat_iter = mChats.begin(); + mNameText->clearString(); - if (mTyping) - { - S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; - switch(dot_count) - { - case 1: - mNameText->addLine(".", new_chat); - break; - case 2: - mNameText->addLine("..", new_chat); - break; - case 3: - mNameText->addLine("...", new_chat); - break; - } + LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); + LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); + LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); + if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) + { + ++chat_iter; + } - } + for(; chat_iter != mChats.end(); ++chat_iter) + { + F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); + LLFontGL::StyleFlags style; + switch(chat_iter->mChatType) + { + case CHAT_TYPE_WHISPER: + style = LLFontGL::ITALIC; + break; + case CHAT_TYPE_SHOUT: + style = LLFontGL::BOLD; + break; + default: + style = LLFontGL::NORMAL; + break; } - else + if (chat_fade_amt < 1.f) + { + F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); + } + else if (chat_fade_amt < 2.f) { + F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); + } + else if (chat_fade_amt < 3.f) + { + // *NOTE: only remove lines down to minimum number + mNameText->addLine(chat_iter->mText, old_chat, style); + } + } + mNameText->setVisibleOffScreen(TRUE); + + if (mTyping) + { + S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; + switch(dot_count) + { + case 1: + mNameText->addLine(".", new_chat); + break; + case 2: + mNameText->addLine("..", new_chat); + break; + case 3: + mNameText->addLine("...", new_chat); + break; + } + + } + } + else + { // ...not using chat bubbles, just names mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - mNameText->setVisibleOffScreen(FALSE); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + mNameText->setVisibleOffScreen(FALSE); } } @@ -3241,8 +3238,8 @@ void LLVOAvatar::clearNameTag() { mNameString.clear(); if (mNameText) - { - mNameText->setLabel(""); + { + mNameText->setLabel(""); mNameText->setString( "" ); } } @@ -3270,34 +3267,45 @@ void LLVOAvatar::invalidateNameTags() if (avatar->isDead()) continue; avatar->clearNameTag(); - } } // Compute name tag position during idle update -LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) +void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) { LLQuaternion root_rot = mRoot.getWorldRotation(); + LLQuaternion inv_root_rot = ~root_rot; LLVector3 pixel_right_vec; LLVector3 pixel_up_vec; LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec); LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin(); camera_to_av.normalize(); - LLVector3 local_camera_at = camera_to_av * ~root_rot; + LLVector3 local_camera_at = camera_to_av * inv_root_rot; LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis(); local_camera_up.normalize(); - local_camera_up = local_camera_up * ~root_rot; + local_camera_up = local_camera_up * inv_root_rot; + + LLVector3 avatar_ellipsoid(mBodySize.mV[VX] * 0.4f, + mBodySize.mV[VY] * 0.4f, + mBodySize.mV[VZ] * NAMETAG_VERT_OFFSET_WEIGHT); + + local_camera_up.scaleVec(avatar_ellipsoid); + local_camera_at.scaleVec(avatar_ellipsoid); - local_camera_up.scaleVec(mBodySize * 0.5f); - local_camera_at.scaleVec(mBodySize * 0.5f); + LLVector3 head_offset = (mHeadp->getLastWorldPosition() - mRoot.getLastWorldPosition()) * inv_root_rot; - LLVector3 name_position = mRoot.getWorldPosition(); - name_position[VZ] -= mPelvisToFoot; - name_position[VZ] += (mBodySize[VZ]* 0.55f); + if (dist_vec(head_offset, mTargetRootToHeadOffset) > NAMETAG_UPDATE_THRESHOLD) + { + mTargetRootToHeadOffset = head_offset; + } + + mCurRootToHeadOffset = lerp(mCurRootToHeadOffset, mTargetRootToHeadOffset, LLCriticalDamp::getInterpolant(0.2f)); + + LLVector3 name_position = mRoot.getLastWorldPosition() + (mCurRootToHeadOffset * root_rot); name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av)); - name_position += pixel_up_vec * 15.f; + name_position += pixel_up_vec * NAMETAG_VERTICAL_SCREEN_OFFSET; - return name_position; + mNameText->setPositionAgent(name_position); } void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha) @@ -3333,7 +3341,7 @@ LLColor4 LLVOAvatar::getNameTagColor(bool is_friend) else { color_name = "NameTagMismatch"; - } + } } else { @@ -3370,9 +3378,9 @@ bool LLVOAvatar::isVisuallyMuted() static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit"); static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); - return LLMuteList::getInstance()->isMuted(getID()) || - (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || - (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); + return LLMuteList::getInstance()->isMuted(getID()) + || (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) + || (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); } //------------------------------------------------------------------------ @@ -3413,8 +3421,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } } - LLVector3d root_pos_global; - if (!mIsBuilt) { return FALSE; @@ -3428,7 +3434,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) { mTimeVisible.reset(); } - //-------------------------------------------------------------------- // the rest should only be done occasionally for far away avatars @@ -3823,10 +3828,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) if ( playSound ) { -// F32 gain = clamp_rescale( mSpeedAccum, -// AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED, -// AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); - const F32 STEP_VOLUME = 0.1f; const LLUUID& step_sound_id = getStepSound(); @@ -4043,13 +4044,6 @@ void LLVOAvatar::updateVisibility() { releaseMeshData(); } - // this breaks off-screen chat bubbles - //if (mNameText) - //{ - // mNameText->markDead(); - // mNameText = NULL; - // sNumVisibleChatBubbles--; - //} } mVisible = visible; @@ -4065,46 +4059,6 @@ bool LLVOAvatar::shouldAlphaMask() } -U32 LLVOAvatar::renderSkinnedAttachments() -{ - /*U32 num_indices = 0; - - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; - - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - const LLViewerObject* attached_object = (*attachment_iter); - if (attached_object && !attached_object->isHUDAttachment()) - { - const LLDrawable* drawable = attached_object->mDrawable; - if (drawable) - { - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - LLFace* face = drawable->getFace(i); - if (face->isState(LLFace::RIGGED)) - { - - } - } - } - } - - return num_indices;*/ - return 0; -} - //----------------------------------------------------------------------------- // renderSkinned() //----------------------------------------------------------------------------- @@ -4125,11 +4079,11 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) { //LOD changed or new mesh created, allocate new vertex buffer if needed if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4) { - updateMeshData(); + updateMeshData(); mDirtyMesh = 0; - mNeedsSkin = TRUE; - mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); - } + mNeedsSkin = TRUE; + mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); + } } if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) @@ -5790,36 +5744,34 @@ BOOL LLVOAvatar::updateJointLODs() F32 avatar_num_factor = clamp_rescale((F32)sNumVisibleAvatars, 8, 25, 1.f, avatar_num_min_factor); F32 area_scale = 0.16f; + if (isSelf()) { - if (isSelf()) - { - if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook()) - { - mAdjustedPixelArea = MAX_PIXEL_AREA; - } - else - { - mAdjustedPixelArea = mPixelArea*area_scale; - } - } - else if (mIsDummy) + if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook()) { mAdjustedPixelArea = MAX_PIXEL_AREA; } else { - // reported avatar pixel area is dependent on avatar render load, based on number of visible avatars - mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; + mAdjustedPixelArea = mPixelArea*area_scale; } + } + else if (mIsDummy) + { + mAdjustedPixelArea = MAX_PIXEL_AREA; + } + else + { + // reported avatar pixel area is dependent on avatar render load, based on number of visible avatars + mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; + } - // now select meshes to render based on adjusted pixel area - BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); - if (res) - { - sNumLODChangesThisFrame++; - dirtyMesh(2); - return TRUE; - } + // now select meshes to render based on adjusted pixel area + BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); + if (res) + { + sNumLODChangesThisFrame++; + dirtyMesh(2); + return TRUE; } return FALSE; @@ -6109,25 +6061,18 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO ) if ( pVObj ) { const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); - if ( pSkinData ) - { - const int jointCnt = pSkinData->mJointNames.size(); - bool fullRig = ( jointCnt>=20 ) ? true : false; - if ( fullRig ) + if (pSkinData + && pSkinData->mJointNames.size() > 20 // full rig + && pSkinData->mAlternateBindMatrix.size() > 0) + { + LLVOAvatar::resetJointPositionsToDefault(); + //Need to handle the repositioning of the cam, updating rig data etc during outfit editing + //This handles the case where we detach a replacement rig. + if ( gAgentCamera.cameraCustomizeAvatar() ) { - const int bindCnt = pSkinData->mAlternateBindMatrix.size(); - if ( bindCnt > 0 ) - { - LLVOAvatar::resetJointPositionsToDefault(); - //Need to handle the repositioning of the cam, updating rig data etc during outfit editing - //This handles the case where we detach a replacement rig. - if ( gAgentCamera.cameraCustomizeAvatar() ) - { - gAgent.unpauseAnimation(); - //Still want to refocus on head bone - gAgentCamera.changeCameraToCustomizeAvatar(); - } - } + gAgent.unpauseAnimation(); + //Still want to refocus on head bone + gAgentCamera.changeCameraToCustomizeAvatar(); } } } @@ -6281,11 +6226,7 @@ void LLVOAvatar::getOffObject() at_axis.mV[VZ] = 0.f; at_axis.normalize(); gAgent.resetAxes(at_axis); - - //reset orientation -// mRoot.setRotation(avWorldRot); gAgentCamera.setThirdPersonHeadOffset(LLVector3(0.f, 0.f, 1.f)); - gAgentCamera.setSitCamera(LLUUID::null); } } @@ -6335,7 +6276,6 @@ LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) const } else { -// return LLColor4( .5f, .5f, .5f, .5f ); return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color } } @@ -7067,10 +7007,6 @@ LLBBox LLVOAvatar::getHUDBBox() const return bbox; } -void LLVOAvatar::rebuildHUD() -{ -} - //----------------------------------------------------------------------------- // onFirstTEMessageReceived() //----------------------------------------------------------------------------- @@ -7192,7 +7128,10 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) && baked_index != BAKED_SKIRT) { setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, - LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, + TRUE, + LLViewerTexture::BOOST_NONE, + LLViewerTexture::LOD_TEXTURE)); } } @@ -7483,11 +7422,6 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_ // Called when baked texture is loaded and also when we start up with a baked texture void LLVOAvatar::useBakedTexture( const LLUUID& id ) { - /* if(id == head_baked->getID()) - mHeadBakedLoaded = TRUE; - mLastHeadBakedID = id; - mHeadMesh0.setTexture( head_baked ); - mHeadMesh1.setTexture( head_baked ); */ for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index dd0317f555..e84acd51ff 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -66,8 +66,9 @@ class LLVoiceVisualizer; class LLHUDNameTag; class LLHUDEffectSpiral; class LLTexGlobalColor; -class LLVOAvatarBoneInfo; -class LLVOAvatarSkeletonInfo; +struct LLVOAvatarBoneInfo; +struct LLVOAvatarChildJoint; +struct LLVOAvatarSkeletonInfo; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLVOAvatar @@ -232,7 +233,7 @@ public: void idleUpdateWindEffect(); void idleUpdateNameTag(const LLVector3& root_pos_last); void idleUpdateNameTagText(BOOL new_name); - LLVector3 idleUpdateNameTagPosition(const LLVector3& root_pos_last); + void idleUpdateNameTagPosition(const LLVector3& root_pos_last); void idleUpdateNameTagAlpha(BOOL new_name, F32 alpha); LLColor4 getNameTagColor(bool is_friend); void clearNameTag(); @@ -317,6 +318,8 @@ public: F32 mLastPelvisToFoot; F32 mPelvisFixup; F32 mLastPelvisFixup; + LLVector3 mCurRootToHeadOffset; + LLVector3 mTargetRootToHeadOffset; LLVector3 mHeadOffset; // current head position LLViewerJoint mRoot; @@ -325,7 +328,7 @@ protected: void buildCharacter(); virtual BOOL loadAvatar(); - BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); + BOOL setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info); private: BOOL mIsBuilt; // state of deferred character building @@ -369,7 +372,7 @@ public: //-------------------------------------------------------------------- private: static LLXmlTree sXMLTree; // avatar config file - static LLXmlTree sSkeletonXMLTree; // avatar skeleton file + static LLXMLNodePtr sSkeletonXMLTree; // avatar skeleton file /** Skeleton ** ** @@ -387,7 +390,6 @@ public: U32 renderRigid(); U32 renderSkinned(EAvatarRenderPass pass); F32 getLastSkinTime() { return mLastSkinTime; } - U32 renderSkinnedAttachments(); U32 renderTransparent(BOOL first_pass); void renderCollisionVolumes(); static void deleteCachedImages(bool clearAll=true); @@ -735,7 +737,6 @@ public: public: BOOL hasHUDAttachment() const; LLBBox getHUDBBox() const; - void rebuildHUD(); void resetHUDAttachments(); BOOL canAttachMoreObjects() const; BOOL canAttachMoreObjects(U32 n) const; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index c523a78b22..fc499bfe9c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -4678,11 +4678,6 @@ void LLPipeline::rebuildPools() } max_count--; } - - if (isAgentAvatarValid()) - { - gAgentAvatarp->rebuildHUD(); - } } void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) -- cgit v1.2.3 From d88491d55843b62e4206e7a28614d5dcc4ed6b9e Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 11 Apr 2012 14:00:26 -0700 Subject: rolled back accidental merge of wip code --- indra/newview/llvoavatar.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index e84acd51ff..599d7e66b4 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -66,9 +66,8 @@ class LLVoiceVisualizer; class LLHUDNameTag; class LLHUDEffectSpiral; class LLTexGlobalColor; -struct LLVOAvatarBoneInfo; -struct LLVOAvatarChildJoint; -struct LLVOAvatarSkeletonInfo; +class LLVOAvatarBoneInfo; +class LLVOAvatarSkeletonInfo; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLVOAvatar @@ -328,7 +327,7 @@ protected: void buildCharacter(); virtual BOOL loadAvatar(); - BOOL setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); + BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info); private: BOOL mIsBuilt; // state of deferred character building @@ -372,7 +371,7 @@ public: //-------------------------------------------------------------------- private: static LLXmlTree sXMLTree; // avatar config file - static LLXMLNodePtr sSkeletonXMLTree; // avatar skeleton file + static LLXmlTree sSkeletonXMLTree; // avatar skeleton file /** Skeleton ** ** -- cgit v1.2.3 From 571a929040d2303f4b0917337d4900229a08f99e Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 11 Apr 2012 19:07:14 -0700 Subject: CHUI-89 FIX Make nametags appear consistently next to avatar heads tweaked nametag positioning --- indra/newview/llvoavatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index ef59e366e8..0ae95c6eff 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -196,7 +196,7 @@ const F32 CHAT_FADE_TIME = 8.0; const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f; const F32 NAMETAG_UPDATE_THRESHOLD = 0.3f; const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f; -const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.15f; +const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.17f; const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); -- cgit v1.2.3 From a3d08c2355e35758b27b0fb7dca926959c440e63 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 12 Apr 2012 11:26:38 -0700 Subject: fixed broken unit tests --- indra/llui/tests/llurlentry_stub.cpp | 2 +- indra/llui/tests/llurlmatch_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index c75df86891..20bac5ff55 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -113,7 +113,7 @@ namespace LLInitParam mEnclosingBlockOffset = (U16)(my_addr - block_addr); } - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){} + void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name){} void BaseBlock::addSynonym(Param& param, const std::string& synonym) {} param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;} diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index 7183413463..9119e7d1fe 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -74,7 +74,7 @@ namespace LLInitParam S32 max_count){} ParamDescriptor::~ParamDescriptor() {} - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){} + void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name){} param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;} void BaseBlock::addSynonym(Param& param, const std::string& synonym) {} -- cgit v1.2.3 From bc4702a7c74977d4f685902b1d6f5d3cb07318d4 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Thu, 12 Apr 2012 23:25:12 +0300 Subject: CHUI-90 WIP Removed all buttons and menus from avatar inspectors. --- indra/newview/llinspectavatar.cpp | 572 +-------------------- .../skins/default/xui/en/inspect_avatar.xml | 105 ---- .../default/xui/en/menu_inspect_avatar_gear.xml | 143 ------ .../default/xui/en/menu_inspect_self_gear.xml | 252 --------- 4 files changed, 2 insertions(+), 1070 deletions(-) delete mode 100644 indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml (limited to 'indra') diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index b2a8c6e3e6..bf71a5c5c5 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -28,38 +28,20 @@ #include "llinspectavatar.h" // viewer files -#include "llagent.h" -#include "llagentdata.h" -#include "llavataractions.h" +#include "llavatariconctrl.h" #include "llavatarnamecache.h" #include "llavatarpropertiesprocessor.h" -#include "llcallingcard.h" #include "lldateutil.h" -#include "llfloaterreporter.h" -#include "llfloaterworldmap.h" -#include "llimview.h" #include "llinspect.h" -#include "llmutelist.h" -#include "llpanelblockedlist.h" #include "llstartup.h" -#include "llspeakers.h" -#include "llviewermenu.h" -#include "llvoiceclient.h" -#include "llviewerobjectlist.h" #include "lltransientfloatermgr.h" -#include "llnotificationsutil.h" // Linden libraries #include "llfloater.h" #include "llfloaterreg.h" -#include "llmenubutton.h" #include "lltextbox.h" -#include "lltoggleablemenu.h" #include "lltooltip.h" // positionViewNearMouse() #include "lltrans.h" -#include "lluictrl.h" - -#include "llavatariconctrl.h" class LLFetchAvatarData; @@ -81,22 +63,13 @@ public: LLInspectAvatar(const LLSD& avatar_id); virtual ~LLInspectAvatar(); - /*virtual*/ BOOL postBuild(void); - // Because floater is single instance, need to re-parse data on each spawn // (for example, inspector about same avatar but in different position) /*virtual*/ void onOpen(const LLSD& avatar_id); - // When closing they should close their gear menu - /*virtual*/ void onClose(bool app_quitting); - // Update view based on information from avatar properties processor void processAvatarData(LLAvatarData* data); - // override the inspector mouse leave so timer is only paused if - // gear menu is not open - /* virtual */ void onMouseLeave(S32 x, S32 y, MASK mask); - virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; } private: @@ -104,47 +77,6 @@ private: // Used on construction and if avatar id changes. void requestUpdate(); - // Set the volume slider to this user's current client-side volume setting, - // hiding/disabling if the user is not nearby. - void updateVolumeSlider(); - - // Shows/hides moderator panel depending on voice state - void updateModeratorPanel(); - - // Moderator ability to enable/disable voice chat for avatar - void toggleSelectedVoice(bool enabled); - - // Button callbacks - void onClickAddFriend(); - void onClickViewProfile(); - void onClickIM(); - void onClickCall(); - void onClickTeleport(); - void onClickInviteToGroup(); - void onClickPay(); - void onClickShare(); - void onToggleMute(); - void onClickReport(); - void onClickFreeze(); - void onClickEject(); - void onClickKick(); - void onClickCSR(); - void onClickZoomIn(); - void onClickFindOnMap(); - bool onVisibleFindOnMap(); - bool onVisibleEject(); - bool onVisibleFreeze(); - bool onVisibleZoomIn(); - void onClickMuteVolume(); - void onVolumeChange(const LLSD& data); - bool enableMute(); - bool enableUnmute(); - bool enableTeleportOffer(); - bool godModeEnabled(); - - // Is used to determine if "Add friend" option should be enabled in gear menu - bool isNotFriend(); - void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); @@ -209,39 +141,8 @@ LLInspectAvatar::LLInspectAvatar(const LLSD& sd) mAvatarName(), mPropertiesRequest(NULL) { - mCommitCallbackRegistrar.add("InspectAvatar.ViewProfile", boost::bind(&LLInspectAvatar::onClickViewProfile, this)); - mCommitCallbackRegistrar.add("InspectAvatar.AddFriend", boost::bind(&LLInspectAvatar::onClickAddFriend, this)); - mCommitCallbackRegistrar.add("InspectAvatar.IM", - boost::bind(&LLInspectAvatar::onClickIM, this)); - mCommitCallbackRegistrar.add("InspectAvatar.Call", boost::bind(&LLInspectAvatar::onClickCall, this)); - mCommitCallbackRegistrar.add("InspectAvatar.Teleport", boost::bind(&LLInspectAvatar::onClickTeleport, this)); - mCommitCallbackRegistrar.add("InspectAvatar.InviteToGroup", boost::bind(&LLInspectAvatar::onClickInviteToGroup, this)); - mCommitCallbackRegistrar.add("InspectAvatar.Pay", boost::bind(&LLInspectAvatar::onClickPay, this)); - mCommitCallbackRegistrar.add("InspectAvatar.Share", boost::bind(&LLInspectAvatar::onClickShare, this)); - mCommitCallbackRegistrar.add("InspectAvatar.ToggleMute", boost::bind(&LLInspectAvatar::onToggleMute, this)); - mCommitCallbackRegistrar.add("InspectAvatar.Freeze", boost::bind(&LLInspectAvatar::onClickFreeze, this)); - mCommitCallbackRegistrar.add("InspectAvatar.Eject", boost::bind(&LLInspectAvatar::onClickEject, this)); - mCommitCallbackRegistrar.add("InspectAvatar.Kick", boost::bind(&LLInspectAvatar::onClickKick, this)); - mCommitCallbackRegistrar.add("InspectAvatar.CSR", boost::bind(&LLInspectAvatar::onClickCSR, this)); - mCommitCallbackRegistrar.add("InspectAvatar.Report", boost::bind(&LLInspectAvatar::onClickReport, this)); - mCommitCallbackRegistrar.add("InspectAvatar.FindOnMap", boost::bind(&LLInspectAvatar::onClickFindOnMap, this)); - mCommitCallbackRegistrar.add("InspectAvatar.ZoomIn", boost::bind(&LLInspectAvatar::onClickZoomIn, this)); - mCommitCallbackRegistrar.add("InspectAvatar.DisableVoice", boost::bind(&LLInspectAvatar::toggleSelectedVoice, this, false)); - mCommitCallbackRegistrar.add("InspectAvatar.EnableVoice", boost::bind(&LLInspectAvatar::toggleSelectedVoice, this, true)); - - mEnableCallbackRegistrar.add("InspectAvatar.EnableGod", boost::bind(&LLInspectAvatar::godModeEnabled, this)); - mEnableCallbackRegistrar.add("InspectAvatar.VisibleFindOnMap", boost::bind(&LLInspectAvatar::onVisibleFindOnMap, this)); - mEnableCallbackRegistrar.add("InspectAvatar.VisibleEject", boost::bind(&LLInspectAvatar::onVisibleEject, this)); - mEnableCallbackRegistrar.add("InspectAvatar.VisibleFreeze", boost::bind(&LLInspectAvatar::onVisibleFreeze, this)); - mEnableCallbackRegistrar.add("InspectAvatar.VisibleZoomIn", boost::bind(&LLInspectAvatar::onVisibleZoomIn, this)); - mEnableCallbackRegistrar.add("InspectAvatar.Gear.Enable", boost::bind(&LLInspectAvatar::isNotFriend, this)); - mEnableCallbackRegistrar.add("InspectAvatar.Gear.EnableCall", boost::bind(&LLAvatarActions::canCall)); - mEnableCallbackRegistrar.add("InspectAvatar.Gear.EnableTeleportOffer", boost::bind(&LLInspectAvatar::enableTeleportOffer, this)); - mEnableCallbackRegistrar.add("InspectAvatar.EnableMute", boost::bind(&LLInspectAvatar::enableMute, this)); - mEnableCallbackRegistrar.add("InspectAvatar.EnableUnmute", boost::bind(&LLInspectAvatar::enableUnmute, this)); - // can't make the properties request until the widgets are constructed - // as it might return immediately, so do it in postBuild. + // as it might return immediately, so do it in onOpen. LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::GLOBAL, this); LLTransientFloater::init(this); @@ -257,25 +158,6 @@ LLInspectAvatar::~LLInspectAvatar() LLTransientFloaterMgr::getInstance()->removeControlView(this); } -/*virtual*/ -BOOL LLInspectAvatar::postBuild(void) -{ - getChild<LLUICtrl>("add_friend_btn")->setCommitCallback( - boost::bind(&LLInspectAvatar::onClickAddFriend, this) ); - - getChild<LLUICtrl>("view_profile_btn")->setCommitCallback( - boost::bind(&LLInspectAvatar::onClickViewProfile, this) ); - - getChild<LLUICtrl>("mute_btn")->setCommitCallback( - boost::bind(&LLInspectAvatar::onClickMuteVolume, this) ); - - getChild<LLUICtrl>("volume_slider")->setCommitCallback( - boost::bind(&LLInspectAvatar::onVolumeChange, this, _2)); - - return TRUE; -} - - // Multiple calls to showInstance("inspect_avatar", foo) will provide different // LLSD for foo, which we will catch here. //virtual @@ -287,11 +169,6 @@ void LLInspectAvatar::onOpen(const LLSD& data) // Extract appropriate avatar id mAvatarID = data["avatar_id"]; - BOOL self = mAvatarID == gAgent.getID(); - - getChild<LLUICtrl>("gear_self_btn")->setVisible(self); - getChild<LLUICtrl>("gear_btn")->setVisible(!self); - // Position the inspector relative to the mouse cursor // Similar to how tooltips are positioned // See LLToolTipMgr::createToolTip @@ -306,18 +183,8 @@ void LLInspectAvatar::onOpen(const LLSD& data) // can't call from constructor as widgets are not built yet requestUpdate(); - - updateVolumeSlider(); - - updateModeratorPanel(); } -// virtual -void LLInspectAvatar::onClose(bool app_quitting) -{ - getChild<LLMenuButton>("gear_btn")->hideMenu(); -} - void LLInspectAvatar::requestUpdate() { // Don't make network requests when spawning from the debug menu at the @@ -344,25 +211,6 @@ void LLInspectAvatar::requestUpdate() delete mPropertiesRequest; mPropertiesRequest = new LLFetchAvatarData(mAvatarID, this); - // You can't re-add someone as a friend if they are already your friend - bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL; - bool is_self = (mAvatarID == gAgentID); - if (is_self) - { - getChild<LLUICtrl>("add_friend_btn")->setVisible(false); - getChild<LLUICtrl>("im_btn")->setVisible(false); - } - else if (is_friend) - { - getChild<LLUICtrl>("add_friend_btn")->setVisible(false); - getChild<LLUICtrl>("im_btn")->setVisible(true); - } - else - { - getChild<LLUICtrl>("add_friend_btn")->setVisible(true); - getChild<LLUICtrl>("im_btn")->setVisible(false); - } - // Use an avatar_icon even though the image id will come down with the // avatar properties because the avatar_icon code maintains a cache of icons // and this may result in the image being visible sooner. @@ -405,213 +253,6 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data) mPropertiesRequest = NULL; } -// For the avatar inspector, we only want to unpause the fade timer -// if neither the gear menu or self gear menu are open -void LLInspectAvatar::onMouseLeave(S32 x, S32 y, MASK mask) -{ - LLToggleableMenu* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu(); - LLToggleableMenu* gear_menu_self = getChild<LLMenuButton>("gear_self_btn")->getMenu(); - if ( gear_menu && gear_menu->getVisible() && - gear_menu_self && gear_menu_self->getVisible() ) - { - return; - } - - if(childHasVisiblePopupMenu()) - { - return; - } - - mOpenTimer.unpause(); -} - -void LLInspectAvatar::updateModeratorPanel() -{ - bool enable_moderator_panel = false; - - if (LLVoiceChannel::getCurrentVoiceChannel() && - mAvatarID != gAgent.getID()) - { - LLUUID session_id = LLVoiceChannel::getCurrentVoiceChannel()->getSessionID(); - - if (session_id != LLUUID::null) - { - LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); - - if (speaker_mgr) - { - LLPointer<LLSpeaker> self_speakerp = speaker_mgr->findSpeaker(gAgent.getID()); - LLPointer<LLSpeaker> selected_speakerp = speaker_mgr->findSpeaker(mAvatarID); - - if(speaker_mgr->isVoiceActive() && selected_speakerp && - selected_speakerp->isInVoiceChannel() && - ((self_speakerp && self_speakerp->mIsModerator) || gAgent.isGodlike())) - { - getChild<LLUICtrl>("enable_voice")->setVisible(selected_speakerp->mModeratorMutedVoice); - getChild<LLUICtrl>("disable_voice")->setVisible(!selected_speakerp->mModeratorMutedVoice); - - enable_moderator_panel = true; - } - } - } - } - - if (enable_moderator_panel) - { - if (!getChild<LLUICtrl>("moderator_panel")->getVisible()) - { - getChild<LLUICtrl>("moderator_panel")->setVisible(true); - // stretch the floater so it can accommodate the moderator panel - reshape(getRect().getWidth(), getRect().getHeight() + getChild<LLUICtrl>("moderator_panel")->getRect().getHeight()); - } - } - else if (getChild<LLUICtrl>("moderator_panel")->getVisible()) - { - getChild<LLUICtrl>("moderator_panel")->setVisible(false); - // shrink the inspector floater back to original size - reshape(getRect().getWidth(), getRect().getHeight() - getChild<LLUICtrl>("moderator_panel")->getRect().getHeight()); - } -} - -void LLInspectAvatar::toggleSelectedVoice(bool enabled) -{ - LLUUID session_id = LLVoiceChannel::getCurrentVoiceChannel()->getSessionID(); - LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); - - if (speaker_mgr) - { - if (!gAgent.getRegion()) - return; - - std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); - LLSD data; - data["method"] = "mute update"; - data["session-id"] = session_id; - data["params"] = LLSD::emptyMap(); - data["params"]["agent_id"] = mAvatarID; - data["params"]["mute_info"] = LLSD::emptyMap(); - // ctrl value represents ability to type, so invert - data["params"]["mute_info"]["voice"] = !enabled; - - class MuteVoiceResponder : public LLHTTPClient::Responder - { - public: - MuteVoiceResponder(const LLUUID& session_id) - { - mSessionID = session_id; - } - - virtual void error(U32 status, const std::string& reason) - { - llwarns << status << ": " << reason << llendl; - - if ( gIMMgr ) - { - //403 == you're not a mod - //should be disabled if you're not a moderator - if ( 403 == status ) - { - gIMMgr->showSessionEventError( - "mute", - "not_a_moderator", - mSessionID); - } - else - { - gIMMgr->showSessionEventError( - "mute", - "generic", - mSessionID); - } - } - } - - private: - LLUUID mSessionID; - }; - - LLHTTPClient::post( - url, - data, - new MuteVoiceResponder(speaker_mgr->getSessionID())); - } - - closeFloater(); - -} - -void LLInspectAvatar::updateVolumeSlider() -{ - bool voice_enabled = LLVoiceClient::getInstance()->getVoiceEnabled(mAvatarID); - - // Do not display volume slider and mute button if it - // is ourself or we are not in a voice channel together - if (!voice_enabled || (mAvatarID == gAgent.getID())) - { - getChild<LLUICtrl>("mute_btn")->setVisible(false); - getChild<LLUICtrl>("volume_slider")->setVisible(false); - } - - else - { - getChild<LLUICtrl>("mute_btn")->setVisible(true); - getChild<LLUICtrl>("volume_slider")->setVisible(true); - - // By convention, we only display and toggle voice mutes, not all mutes - bool is_muted = LLAvatarActions::isVoiceMuted(mAvatarID); - - LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); - - bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); - - mute_btn->setEnabled( !is_linden); - mute_btn->setValue( is_muted ); - - LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); - volume_slider->setEnabled( !is_muted ); - - F32 volume; - - if (is_muted) - { - // it's clearer to display their volume as zero - volume = 0.f; - } - else - { - // actual volume - volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); - } - volume_slider->setValue( (F64)volume ); - } - -} - -void LLInspectAvatar::onClickMuteVolume() -{ - // By convention, we only display and toggle voice mutes, not all mutes - LLMuteList* mute_list = LLMuteList::getInstance(); - bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat); - - LLMute mute(mAvatarID, mAvatarName.getLegacyName(), LLMute::AGENT); - if (!is_muted) - { - mute_list->add(mute, LLMute::flagVoiceChat); - } - else - { - mute_list->remove(mute, LLMute::flagVoiceChat); - } - - updateVolumeSlider(); -} - -void LLInspectAvatar::onVolumeChange(const LLSD& data) -{ - F32 volume = (F32)data.asReal(); - LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); -} - void LLInspectAvatar::onAvatarNameCache( const LLUUID& agent_id, const LLAvatarName& av_name) @@ -639,215 +280,6 @@ void LLInspectAvatar::onAvatarNameCache( } } -void LLInspectAvatar::onClickAddFriend() -{ - LLAvatarActions::requestFriendshipDialog(mAvatarID, mAvatarName.getLegacyName()); - closeFloater(); -} - -void LLInspectAvatar::onClickViewProfile() -{ - LLAvatarActions::showProfile(mAvatarID); - closeFloater(); -} - -bool LLInspectAvatar::isNotFriend() -{ - return !LLAvatarActions::isFriend(mAvatarID); -} - -bool LLInspectAvatar::onVisibleFindOnMap() -{ - return gAgent.isGodlike() || is_agent_mappable(mAvatarID); -} - -bool LLInspectAvatar::onVisibleEject() -{ - return enable_freeze_eject( LLSD(mAvatarID) ); -} - -bool LLInspectAvatar::onVisibleFreeze() -{ - // either user is a god and can do long distance freeze - // or check for target proximity and permissions - return gAgent.isGodlike() || enable_freeze_eject(LLSD(mAvatarID)); -} - -bool LLInspectAvatar::onVisibleZoomIn() -{ - return gObjectList.findObject(mAvatarID); -} - -void LLInspectAvatar::onClickIM() -{ - LLAvatarActions::startIM(mAvatarID); - closeFloater(); -} - -void LLInspectAvatar::onClickCall() -{ - LLAvatarActions::startCall(mAvatarID); - closeFloater(); -} - -void LLInspectAvatar::onClickTeleport() -{ - LLAvatarActions::offerTeleport(mAvatarID); - closeFloater(); -} - -void LLInspectAvatar::onClickInviteToGroup() -{ - LLAvatarActions::inviteToGroup(mAvatarID); - closeFloater(); -} - -void LLInspectAvatar::onClickPay() -{ - LLAvatarActions::pay(mAvatarID); - closeFloater(); -} - -void LLInspectAvatar::onClickShare() -{ - LLAvatarActions::share(mAvatarID); - closeFloater(); -} - -void LLInspectAvatar::onToggleMute() -{ - LLMute mute(mAvatarID, mAvatarName.mDisplayName, LLMute::AGENT); - - if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName)) - { - LLMuteList::getInstance()->remove(mute); - } - else - { - LLMuteList::getInstance()->add(mute); - } - - LLPanelBlockedList::showPanelAndSelect(mute.mID); - closeFloater(); -} - -void LLInspectAvatar::onClickReport() -{ - LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName.getCompleteName()); - closeFloater(); -} - -bool godlike_freeze(const LLSD& notification, const LLSD& response) -{ - LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - - switch (option) - { - case 0: - LLAvatarActions::freeze(avatar_id); - break; - case 1: - LLAvatarActions::unfreeze(avatar_id); - break; - default: - break; - } - - return false; -} - -void LLInspectAvatar::onClickFreeze() -{ - if (gAgent.isGodlike()) - { - // use godlike freeze-at-a-distance, with confirmation - LLNotificationsUtil::add("FreezeAvatar", - LLSD(), - LLSD().with("avatar_id", mAvatarID), - godlike_freeze); - } - else - { - // use default "local" version of freezing that requires avatar to be in range - handle_avatar_freeze( LLSD(mAvatarID) ); - } - closeFloater(); -} - -void LLInspectAvatar::onClickEject() -{ - handle_avatar_eject( LLSD(mAvatarID) ); - closeFloater(); -} - -void LLInspectAvatar::onClickKick() -{ - LLAvatarActions::kick(mAvatarID); - closeFloater(); -} - -void LLInspectAvatar::onClickCSR() -{ - std::string name; - gCacheName->getFullName(mAvatarID, name); - LLAvatarActions::csr(mAvatarID, name); - closeFloater(); -} - -void LLInspectAvatar::onClickZoomIn() -{ - handle_zoom_to_object(mAvatarID); - closeFloater(); -} - -void LLInspectAvatar::onClickFindOnMap() -{ - gFloaterWorldMap->trackAvatar(mAvatarID, mAvatarName.mDisplayName); - LLFloaterReg::showInstance("world_map"); -} - - -bool LLInspectAvatar::enableMute() -{ - bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); - bool is_self = mAvatarID == gAgent.getID(); - - if (!is_linden && !is_self && !LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName.getLegacyName())) - { - return true; - } - else - { - return false; - } -} - -bool LLInspectAvatar::enableUnmute() -{ - bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); - bool is_self = mAvatarID == gAgent.getID(); - - if (!is_linden && !is_self && LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName.getLegacyName())) - { - return true; - } - else - { - return false; - } -} - -bool LLInspectAvatar::enableTeleportOffer() -{ - return LLAvatarActions::canOfferTeleport(mAvatarID); -} - -bool LLInspectAvatar::godModeEnabled() -{ - return gAgent.isGodlike(); -} - ////////////////////////////////////////////////////////////////////////////// // LLInspectAvatarUtil ////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml index bc3bcd331b..866d54e4f8 100644 --- a/indra/newview/skins/default/xui/en/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml @@ -94,32 +94,6 @@ use_ellipses="true" width="220">This is my second life description and I really think it is great. But for some reason my description is super extra long because I like to talk a whole lot </text> - <slider - follows="top|left" - height="23" - increment="0.01" - left="1" - max_val="0.95" - min_val="0.05" - name="volume_slider" - show_text="false" - tool_tip="Voice volume" - top_pad="0" - value="0.5" - width="200" /> - <button - follows="top|left" - height="16" - image_disabled="Audio_Off" - image_disabled_selected="AudioMute_Off" - image_hover_selected="AudioMute_Over" - image_selected="AudioMute_Off" - image_unselected="Audio_Off" - is_toggle="true" - left_pad="0" - top_delta="4" - name="mute_btn" - width="16" /> <avatar_icon follows="top|left" height="38" @@ -130,83 +104,4 @@ name="avatar_icon" top="10" width="38" /> -<!-- Overlapping buttons for default actions - llinspectavatar.cpp makes visible the most likely default action ---> - <button - follows="top|left" - height="20" - label="Add Friend" - left="8" - top="135" - name="add_friend_btn" - width="90" /> - <button - follows="top|left" - height="20" - label="IM" - left_delta="0" - top_delta="0" - name="im_btn" - width="80" - commit_callback.function="InspectAvatar.IM"/> - <button - follows="top|left" - height="20" - label="Profile" - layout="topleft" - name="view_profile_btn" - left_delta="96" - top_delta="0" - tab_stop="false" - width="80" /> - <!-- gear buttons here --> - <menu_button - follows="top|left" - height="20" - layout="topleft" - image_overlay="OptionsMenu_Off" - menu_filename="menu_inspect_avatar_gear.xml" - name="gear_btn" - right="-5" - top_delta="0" - width="35" /> - <menu_button - follows="top|left" - height="20" - image_overlay="OptionsMenu_Off" - menu_filename="menu_inspect_self_gear.xml" - name="gear_self_btn" - right="-5" - top_delta="0" - width="35" /> - <panel - follows="top|left" - top="164" - left="0" - height="60" - width="228" - visible="false" - background_visible="true" - name="moderator_panel" - background_opaque="true" - bg_opaque_color="MouseGray"> - <button - name="disable_voice" - label="Disable Voice" - top="20" - width="95" - height="20" - left="10" - commit_callback.function="InspectAvatar.DisableVoice"/> - <button - name="enable_voice" - label="Enable Voice" - top="20" - width="95" - height="20" - left="10" - visible="false" - commit_callback.function="InspectAvatar.EnableVoice"/> - </panel> </floater> diff --git a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml deleted file mode 100644 index 76b188220d..0000000000 --- a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml +++ /dev/null @@ -1,143 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<toggleable_menu - create_jump_keys="true" - layout="topleft" - mouse_opaque="false" - visible="false" - name="Gear Menu"> - <menu_item_call - label="View Profile" - enabled="true" - name="view_profile"> - <menu_item_call.on_click - function="InspectAvatar.ViewProfile"/> - </menu_item_call> - <menu_item_call - label="Add Friend" - name="add_friend"> - <menu_item_call.on_click - function="InspectAvatar.AddFriend"/> - <menu_item_call.on_enable - function="InspectAvatar.Gear.Enable"/> - </menu_item_call> - <menu_item_call - label="IM" - name="im"> - <menu_item_call.on_click - function="InspectAvatar.IM"/> - </menu_item_call> - <menu_item_call - label="Call" - enabled="true" - name="call"> - <menu_item_call.on_click - function="InspectAvatar.Call"/> - <menu_item_call.on_enable - function="InspectAvatar.Gear.EnableCall"/> - </menu_item_call> - <menu_item_call - label="Teleport" - name="teleport"> - <menu_item_call.on_click - function="InspectAvatar.Teleport"/> - <menu_item_call.on_enable - function="InspectAvatar.Gear.EnableTeleportOffer"/> - </menu_item_call> - <menu_item_call - label="Invite to Group" - name="invite_to_group"> - <menu_item_call.on_click - function="InspectAvatar.InviteToGroup"/> - </menu_item_call> - <menu_item_separator /> - <menu_item_call - label="Block" - name="block"> - <menu_item_call.on_click - function="InspectAvatar.ToggleMute"/> - <menu_item_call.on_visible - function="InspectAvatar.EnableMute" /> - </menu_item_call> - <menu_item_call - label="Unblock" - name="unblock"> - <menu_item_call.on_click - function="InspectAvatar.ToggleMute"/> - <menu_item_call.on_visible - function="InspectAvatar.EnableUnmute" /> - </menu_item_call> - <menu_item_call - label="Report" - name="report"> - <menu_item_call.on_click - function="InspectAvatar.Report"/> - </menu_item_call> - <menu_item_call - label="Freeze" - name="freeze"> - <menu_item_call.on_click - function="InspectAvatar.Freeze"/> - <menu_item_call.on_visible - function="InspectAvatar.VisibleFreeze"/> - </menu_item_call> - <menu_item_call - label="Eject" - name="eject"> - <menu_item_call.on_click - function="InspectAvatar.Eject"/> - <menu_item_call.on_visible - function="InspectAvatar.VisibleEject"/> - </menu_item_call> - <menu_item_call - label="Kick" - name="kick"> - <menu_item_call.on_click - function="InspectAvatar.Kick"/> - <menu_item_call.on_visible - function="InspectAvatar.EnableGod"/> - </menu_item_call> - <menu_item_call - label="CSR" - name="csr"> - <menu_item_call.on_click - function="InspectAvatar.CSR" /> - <menu_item_call.on_visible - function="InspectAvatar.EnableGod" /> - </menu_item_call> - <menu_item_call - label="Debug Textures" - name="debug"> - <menu_item_call.on_click - function="Avatar.Debug"/> - <menu_item_call.on_visible - function="IsGodCustomerService"/> - </menu_item_call> - <menu_item_call - label="Find On Map" - name="find_on_map"> - <menu_item_call.on_click - function="InspectAvatar.FindOnMap"/> - <menu_item_call.on_visible - function="InspectAvatar.VisibleFindOnMap"/> - </menu_item_call> - <menu_item_call - label="Zoom In" - name="zoom_in"> - <menu_item_call.on_click - function="InspectAvatar.ZoomIn"/> - <menu_item_call.on_visible - function="InspectAvatar.VisibleZoomIn"/> - </menu_item_call> - <menu_item_call - label="Pay" - name="pay"> - <menu_item_call.on_click - function="InspectAvatar.Pay"/> - </menu_item_call> - <menu_item_call - label="Share" - name="share"> - <menu_item_call.on_click - function="InspectAvatar.Share"/> - </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml deleted file mode 100644 index 5e7b16ed4a..0000000000 --- a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml +++ /dev/null @@ -1,252 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu - layout="topleft" - name="Self Pie"> - <menu_item_call - label="Sit Down" - layout="topleft" - name="Sit Down Here"> - <menu_item_call.on_click - function="Self.SitDown" - parameter="" /> - <menu_item_call.on_enable - function="Self.EnableSitDown" /> - </menu_item_call> - <menu_item_call - label="Stand Up" - layout="topleft" - name="Stand Up"> - <menu_item_call.on_click - function="Self.StandUp" - parameter="" /> - <menu_item_call.on_enable - function="Self.EnableStandUp" /> - </menu_item_call> - <context_menu - label="Take Off" - layout="topleft" - name="Take Off >"> - <context_menu - label="Clothes" - layout="topleft" - name="Clothes >"> - <menu_item_call - enabled="false" - label="Shirt" - layout="topleft" - name="Shirt"> - <menu_item_call.on_click - function="Edit.TakeOff" - parameter="shirt" /> - <menu_item_call.on_enable - function="Edit.EnableTakeOff" - parameter="shirt" /> - </menu_item_call> - <menu_item_call - enabled="false" - label="Pants" - layout="topleft" - name="Pants"> - <menu_item_call.on_click - function="Edit.TakeOff" - parameter="pants" /> - <menu_item_call.on_enable - function="Edit.EnableTakeOff" - parameter="pants" /> - </menu_item_call> - <menu_item_call - enabled="false" - label="Skirt" - layout="topleft" - name="Skirt"> - <menu_item_call.on_click - function="Edit.TakeOff" - parameter="skirt" /> - <menu_item_call.on_enable - function="Edit.EnableTakeOff" - parameter="skirt" /> - </menu_item_call> - <menu_item_call - enabled="false" - label="Shoes" - layout="topleft" - name="Shoes"> - <menu_item_call.on_click - function="Edit.TakeOff" - parameter="shoes" /> - <menu_item_call.on_enable - function="Edit.EnableTakeOff" - parameter="shoes" /> - </menu_item_call> - <menu_item_call - enabled="false" - label="Socks" - layout="topleft" - name="Socks"> - <menu_item_call.on_click - function="Edit.TakeOff" - parameter="socks" /> - <menu_item_call.on_enable - function="Edit.EnableTakeOff" - parameter="socks" /> - </menu_item_call> - <menu_item_call - enabled="false" - label="Jacket" - layout="topleft" - name="Jacket"> - <menu_item_call.on_click - function="Edit.TakeOff" - parameter="jacket" /> - <menu_item_call.on_enable - function="Edit.EnableTakeOff" - parameter="jacket" /> - </menu_item_call> - <menu_item_call - enabled="false" - label="Gloves" - layout="topleft" - name="Gloves"> - <menu_item_call.on_click - function="Edit.TakeOff" - parameter="gloves" /> - <menu_item_call.on_enable - function="Edit.EnableTakeOff" - parameter="gloves" /> - </menu_item_call> - <menu_item_call - enabled="false" - label="Undershirt" - layout="topleft" - name="Self Undershirt"> - <menu_item_call.on_click - function="Edit.TakeOff" - parameter="undershirt" /> - <menu_item_call.on_enable - function="Edit.EnableTakeOff" - parameter="undershirt" /> - </menu_item_call> - <menu_item_call - enabled="false" - label="Underpants" - layout="topleft" - name="Self Underpants"> - <menu_item_call.on_click - function="Edit.TakeOff" - parameter="underpants" /> - <menu_item_call.on_enable - function="Edit.EnableTakeOff" - parameter="underpants" /> - </menu_item_call> - <menu_item_call - enabled="false" - label="Tattoo" - layout="topleft" - name="Self Tattoo"> - <menu_item_call.on_click - function="Edit.TakeOff" - parameter="tattoo" /> - <menu_item_call.on_enable - function="Edit.EnableTakeOff" - parameter="tattoo" /> - </menu_item_call> - <menu_item_call - enabled="false" - label="Alpha" - layout="topleft" - name="Self Alpha"> - <menu_item_call.on_click - function="Edit.TakeOff" - parameter="alpha" /> - <menu_item_call.on_enable - function="Edit.EnableTakeOff" - parameter="alpha" /> - </menu_item_call> - <menu_item_separator - layout="topleft" /> - <menu_item_call - label="All Clothes" - layout="topleft" - name="All Clothes"> - <menu_item_call.on_click - function="Edit.TakeOff" - parameter="all" /> - </menu_item_call> - </context_menu> - <context_menu - label="HUD" - layout="topleft" - name="Object Detach HUD" /> - <context_menu - label="Detach" - layout="topleft" - name="Object Detach" /> - <menu_item_call - label="Detach All" - layout="topleft" - name="Detach All"> - <menu_item_call.on_click - function="Self.RemoveAllAttachments" - parameter="" /> - <menu_item_call.on_enable - function="Self.EnableRemoveAllAttachments" /> - </menu_item_call> - </context_menu> - <menu_item_call - label="Change Outfit" - layout="topleft" - name="Chenge Outfit"> - <menu_item_call.on_click - function="CustomizeAvatar" /> - <menu_item_call.on_enable - function="Edit.EnableCustomizeAvatar" /> - </menu_item_call> - <menu_item_call label="Edit My Outfit" - layout="topleft" - name="Edit Outfit"> - <menu_item_call.on_click - function="EditOutfit" /> - <menu_item_call.on_enable - function="Edit.EnableCustomizeAvatar" /> - </menu_item_call> - <menu_item_call label="Edit My Shape" - layout="topleft" - name="Edit My Shape"> - <menu_item_call.on_click - function="EditShape" /> - <menu_item_call.on_enable - function="Edit.EnableEditShape" /> - </menu_item_call> - <menu_item_call - label="My Friends" - layout="topleft" - name="Friends..."> - <menu_item_call.on_click - function="SideTray.PanelPeopleTab" - parameter="friends_panel" /> - </menu_item_call> - <menu_item_call - label="My Groups" - layout="topleft" - name="Groups..."> - <menu_item_call.on_click - function="SideTray.PanelPeopleTab" - parameter="groups_panel" /> - </menu_item_call> - <menu_item_call - label="My Profile" - layout="topleft" - name="Profile..."> - <menu_item_call.on_click - function="ShowAgentProfile" - parameter="agent" /> - </menu_item_call> - <menu_item_call - label="Debug Textures" - name="Debug..."> - <menu_item_call.on_click - function="Avatar.Debug" /> - <menu_item_call.on_visible - function="IsGodCustomerService"/> - </menu_item_call> -</toggleable_menu> -- cgit v1.2.3 From 1e74372f50a2cb2ed3364e79344b0408e7e8d89b Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Fri, 13 Apr 2012 00:26:33 +0300 Subject: CHUI-90 WIP Added "View full profile" link to avatar inspectors. --- indra/newview/llinspectavatar.cpp | 4 ++++ indra/newview/skins/default/xui/en/inspect_avatar.xml | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index bf71a5c5c5..8a15cd279f 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -33,6 +33,7 @@ #include "llavatarpropertiesprocessor.h" #include "lldateutil.h" #include "llinspect.h" +#include "llslurl.h" #include "llstartup.h" #include "lltransientfloatermgr.h" @@ -181,6 +182,9 @@ void LLInspectAvatar::onOpen(const LLSD& data) LLUI::positionViewNearMouse(this); } + // Generate link to avatar profile. + getChild<LLUICtrl>("avatar_profile_link")->setTextArg("[LINK]", LLSLURL("agent", mAvatarID, "about").getSLURLString()); + // can't call from constructor as widgets are not built yet requestUpdate(); } diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml index 866d54e4f8..c3481e6d4c 100644 --- a/indra/newview/skins/default/xui/en/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml @@ -9,7 +9,7 @@ bg_opaque_image="Inspector_Background" can_close="false" can_minimize="false" - height="164" + height="130" layout="topleft" name="inspect_avatar" single_instance="true" @@ -94,6 +94,17 @@ use_ellipses="true" width="220">This is my second life description and I really think it is great. But for some reason my description is super extra long because I like to talk a whole lot </text> + <text + follows="top|left" + height="16" + left="8" + name="avatar_profile_link" + font="SansSerifSmall" + text_color="White" + top_pad="5" + translate="false" + value="[[LINK] View full profile]" + width="175" /> <avatar_icon follows="top|left" height="38" -- cgit v1.2.3 From 855fbc0bf331c116d20d402f427535f060f70345 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 12 Apr 2012 17:18:34 -0700 Subject: fixed UI not working at all due to bad param blocks --- indra/llui/llloadingindicator.cpp | 2 +- indra/llui/llloadingindicator.h | 6 +- indra/llxuixml/llinitparam.h | 391 ++++++++++++++++++++++++++------------ indra/llxuixml/llxuiparser.cpp | 26 +-- indra/newview/llvoavatar.cpp | 2 +- 5 files changed, 284 insertions(+), 143 deletions(-) (limited to 'indra') diff --git a/indra/llui/llloadingindicator.cpp b/indra/llui/llloadingindicator.cpp index 6ac38f5ad4..1ede5b706f 100644 --- a/indra/llui/llloadingindicator.cpp +++ b/indra/llui/llloadingindicator.cpp @@ -52,7 +52,7 @@ LLLoadingIndicator::LLLoadingIndicator(const Params& p) void LLLoadingIndicator::initFromParams(const Params& p) { - BOOST_FOREACH(LLUIImage* image, p.images.image) + BOOST_FOREACH(LLUIImage* image, p.images().image) { mImages.push_back(image); } diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h index c1f979c111..4998a57263 100644 --- a/indra/llui/llloadingindicator.h +++ b/indra/llui/llloadingindicator.h @@ -51,7 +51,7 @@ class LLLoadingIndicator LOG_CLASS(LLLoadingIndicator); public: - struct Images : public LLInitParam::BatchBlock<Images> + struct Images : public LLInitParam::Block<Images> { Multiple<LLUIImage*> image; @@ -62,8 +62,8 @@ public: struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> { - Optional<F32> images_per_sec; - Optional<Images> images; + Optional<F32> images_per_sec; + Optional<Batch<Images> > images; Params() : images_per_sec("images_per_sec", 1.0f), diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index dbf2fdaa73..0c53b36bad 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -390,15 +390,19 @@ namespace LLInitParam class BaseBlock { public: - typedef IS_BLOCK IS_BLOCK; - typedef NOT_BLOCK NOT_BLOCK; + // lift block tags into baseblock namespace so derived classes do not need to qualify them + typedef LLInitParam::IS_BLOCK IS_BLOCK; + typedef LLInitParam::NOT_BLOCK NOT_BLOCK; + + template<typename T> + class Batch + {}; //TODO: implement in terms of owned_ptr - template<typename T, typename BLOCK_T = IS_BLOCK> + template<typename T, typename BLOCK_T = IsBlock<T>::value_t > class Lazy { public: - Lazy() : mPtr(NULL) {} @@ -470,7 +474,7 @@ namespace LLInitParam return get(); } - private: + private: // lazily allocate an instance of T T* ensureInstance() const { @@ -642,11 +646,12 @@ namespace LLInitParam { public: typedef const T& value_assignment_t; + typedef T default_value_t; typedef T value_t; typedef ParamValue<T, NAME_VALUE_LOOKUP, VALUE_IS_BLOCK> self_t; ParamValue(): mValue() {} - ParamValue(value_assignment_t other) : mValue(other) {} + ParamValue(const default_value_t& other) : mValue(other) {} void setValue(value_assignment_t val) { @@ -699,6 +704,7 @@ namespace LLInitParam { public: typedef const T& value_assignment_t; + typedef T default_value_t; typedef T value_t; typedef ParamValue<T, NAME_VALUE_LOOKUP, IS_BLOCK> self_t; @@ -707,7 +713,7 @@ namespace LLInitParam mValidated(false) {} - ParamValue(value_assignment_t other) + ParamValue(const default_value_t& other) : T(other), mValidated(false) {} @@ -762,11 +768,12 @@ namespace LLInitParam { public: typedef const std::string& value_assignment_t; + typedef std::string default_value_t; typedef std::string value_t; typedef ParamValue<std::string, NAME_VALUE_LOOKUP, NOT_BLOCK> self_t; ParamValue(): mValue() {} - ParamValue(value_assignment_t other) : mValue(other) {} + ParamValue(const default_value_t& other) : mValue(other) {} void setValue(value_assignment_t val) { @@ -808,8 +815,8 @@ namespace LLInitParam template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > struct ParamIterator { - typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::const_iterator const_iterator; - typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::iterator iterator; + typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> >::const_iterator const_iterator; + typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> >::iterator iterator; }; // specialize for custom parsing/decomposition of specific classes @@ -817,19 +824,20 @@ namespace LLInitParam template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>, bool HAS_MULTIPLE_VALUES = false, - typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t> + typename VALUE_IS_BLOCK = typename IsBlock<ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> >::value_t> class TypedParam : public Param, - public ParamValue<T, NAME_VALUE_LOOKUP> + public ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t; - typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; - typedef typename param_value_t::value_assignment_t value_assignment_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t; + typedef ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> param_value_t; + typedef typename param_value_t::value_assignment_t value_assignment_t; + typedef typename param_value_t::default_value_t default_value_t; using param_value_t::operator(); - TypedParam(BlockDescriptor& block_descriptor, const char* name, const T& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr), param_value_t(value) { @@ -862,6 +870,7 @@ namespace LLInitParam if (parser.readValue(name)) { // try to parse a per type named value + if (param_value_t::getValueFromName(name, typed_param.getValue())) { typed_param.setValueName(name); @@ -974,16 +983,17 @@ namespace LLInitParam template <typename T, typename NAME_VALUE_LOOKUP> class TypedParam<T, NAME_VALUE_LOOKUP, false, IS_BLOCK> : public Param, - public ParamValue<T, NAME_VALUE_LOOKUP> + public ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> { public: - typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; + typedef ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> param_value_t; typedef typename param_value_t::value_assignment_t value_assignment_t; + typedef typename param_value_t::default_value_t default_value_t; typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_BLOCK> self_t; using param_value_t::operator(); - TypedParam(BlockDescriptor& block_descriptor, const char* name, const T& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr), param_value_t(value) { @@ -1149,13 +1159,14 @@ namespace LLInitParam { public: typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t; - typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP> param_value_t; + typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP, typename IsBlock<VALUE_TYPE>::value_t> param_value_t; typedef typename std::vector<param_value_t> container_t; typedef const container_t& value_assignment_t; + typedef container_t default_value_t; typedef typename param_value_t::value_t value_t; - TypedParam(BlockDescriptor& block_descriptor, const char* name, const container_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) { std::copy(value.begin(), value.end(), std::back_inserter(mValues)); @@ -1348,12 +1359,13 @@ namespace LLInitParam { public: typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_BLOCK> self_t; - typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP> param_value_t; + typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP, typename IsBlock<VALUE_TYPE>::value_t> param_value_t; typedef typename std::vector<param_value_t> container_t; typedef const container_t& value_assignment_t; typedef typename param_value_t::value_t value_t; + typedef container_t default_value_t; - TypedParam(BlockDescriptor& block_descriptor, const char* name, const container_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) { std::copy(value.begin(), value.end(), back_inserter(mValues)); @@ -1617,13 +1629,14 @@ namespace LLInitParam public: friend class ChoiceBlock<DERIVED_BLOCK>; - typedef Alternative<T, NAME_VALUE_LOOKUP> self_t; - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, typename IsBlock<T>::value_t> super_t; - typedef typename super_t::value_assignment_t value_assignment_t; + typedef Alternative<T, NAME_VALUE_LOOKUP> self_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; + typedef typename super_t::value_assignment_t value_assignment_t; + typedef typename super_t::default_value_t default_value_t; using super_t::operator =; - explicit Alternative(const char* name = "", const T& val = defaultValue<T>()) + explicit Alternative(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1), mOriginalValue(val) { @@ -1736,13 +1749,14 @@ namespace LLInitParam class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, typename IsBlock<T>::value_t> super_t; - typedef typename super_t::value_assignment_t value_assignment_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; + typedef typename super_t::value_assignment_t value_assignment_t; + typedef typename super_t::default_value_t default_value_t; using super_t::operator(); using super_t::operator =; - explicit Optional(const char* name = "", const T& val = defaultValue<T>()) + explicit Optional(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1) { //#pragma message("Parsing LLInitParam::Block::Optional") @@ -1765,15 +1779,16 @@ namespace LLInitParam class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, typename IsBlock<T>::value_t> super_t; - typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t; - typedef typename super_t::value_assignment_t value_assignment_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; + typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t; + typedef typename super_t::value_assignment_t value_assignment_t; + typedef typename super_t::default_value_t default_value_t; using super_t::operator(); using super_t::operator =; // mandatory parameters require a name to be parseable - explicit Mandatory(const char* name = "", const T& val = defaultValue<T>()) + explicit Mandatory(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, &validate, 1, 1) {} @@ -1801,12 +1816,12 @@ namespace LLInitParam class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true> { public: - typedef TypedParam<T, NAME_VALUE_LOOKUP, true, typename IsBlock<T>::value_t> super_t; - typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t; - typedef typename super_t::container_t container_t; - typedef typename super_t::value_assignment_t value_assignment_t; - typedef typename super_t::iterator iterator; - typedef typename super_t::const_iterator const_iterator; + typedef TypedParam<T, NAME_VALUE_LOOKUP, true> super_t; + typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t; + typedef typename super_t::container_t container_t; + typedef typename super_t::value_assignment_t value_assignment_t; + typedef typename super_t::iterator iterator; + typedef typename super_t::const_iterator const_iterator; explicit Multiple(const char* name = "") : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) @@ -1888,136 +1903,158 @@ namespace LLInitParam }; - template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock> - class BatchBlock - : public Block<DERIVED_BLOCK, BASE_BLOCK> + template<typename T, typename BLOCK_T> + struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::IS_BLOCK>, TypeValues<BaseBlock::Lazy<T, BaseBlock::IS_BLOCK> >, BLOCK_T >, void> { - public: - typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> self_t; - typedef Block<DERIVED_BLOCK, BASE_BLOCK> super_t; - - BatchBlock() - {} + typedef IS_BLOCK value_t; + }; - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) - { - if (new_name) - { - // reset block - *static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue(); - } - return super_t::deserializeBlock(p, name_stack_range, new_name); - } + template<typename T, typename BLOCK_T> + struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::NOT_BLOCK>, TypeValues<BaseBlock::Lazy<T, BaseBlock::NOT_BLOCK> >, BLOCK_T >, void> + { + typedef NOT_BLOCK value_t; + }; - bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) - { - if (overwrite) - { - *static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue(); - // merge individual parameters into destination - return super_t::mergeBlock(super_t::getBlockDescriptor(), other, overwrite); - } - return false; - } - protected: - static const DERIVED_BLOCK& defaultBatchValue() - { - static DERIVED_BLOCK default_value; - return default_value; - } + template<typename T, typename BLOCK_IDENTIFIER> + struct IsBlock<ParamValue<BaseBlock::Batch<T>, TypeValues<BaseBlock::Batch<T> >, typename IsBlock<BaseBlock::Batch<T> >::value_t >, BLOCK_IDENTIFIER> + { + typedef typename IsBlock<ParamValue<T, TypeValues<T>, typename IsBlock<T>::value_t > >::value_t value_t; }; - // FIXME: this specialization is not currently used, as it only matches against the BatchBlock base class - // and not the derived class with the actual params - template<typename DERIVED_BLOCK, - typename BASE_BLOCK, - typename NAME_VALUE_LOOKUP> - class ParamValue <BatchBlock<DERIVED_BLOCK, BASE_BLOCK>, - NAME_VALUE_LOOKUP, - IS_BLOCK> - : public NAME_VALUE_LOOKUP, - protected BatchBlock<DERIVED_BLOCK, BASE_BLOCK> + template<typename T, typename BLOCK_T> + class ParamValue <BaseBlock::Batch<T>, + TypeValues<BaseBlock::Batch<T> >, + BLOCK_T> + : public TypeValues<T> { public: - typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> block_t; - typedef const BatchBlock<DERIVED_BLOCK, BASE_BLOCK>& value_assignment_t; - typedef block_t value_t; + typedef ParamValue <BaseBlock::Batch<T>, TypeValues<BaseBlock::Batch<T> >, BLOCK_T> self_t; + typedef ParamValue<T, TypeValues<T>, typename IsBlock<T>::value_t > param_value_t; + typedef const T& value_assignment_t; + typedef T value_t; + typedef T default_value_t; ParamValue() - : block_t(), + : mValue(), mValidated(false) {} - ParamValue(value_assignment_t other) - : block_t(other), + ParamValue(const default_value_t& value) + : mValue(value), mValidated(false) - { - } + {} void setValue(value_assignment_t val) { - *this = val; + mValue.setValue(val); } - value_assignment_t getValue() const + const T& getValue() const { - return *this; + return mValue.getValue(); } - BatchBlock<DERIVED_BLOCK, BASE_BLOCK>& getValue() + T& getValue() { - return *this; + return mValue; } operator value_assignment_t() const { - return *this; + return mValue; } value_assignment_t operator()() const { + return mValue; + } + + void operator ()(const typename TypeValues<T>::name_t& name) + { + *this = name; + } + + self_t& operator =(const typename TypeValues<T>::name_t& name) + { + mValue = name; + return *this; } - protected: + bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) + { + if (new_name) + { + // reset block + mValue = defaultBatchValue(); + } + return mValue.deserializeBlock(p, name_stack_range, new_name); + } + + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const + { + const BaseBlock* base_block = diff_block + ? &(diff_block->mValue) + : NULL; + mValue.serializeBlock(p, name_stack, base_block); + } + + bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const + { + return mValue.inspectBlock(p, name_stack, min_count, max_count); + } + + bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) + { + if (overwrite) + { + mValue = defaultBatchValue(); + return mValue.mergeBlock(block_data, source, overwrite); + } + return false; + } + + bool validateBlock(bool emit_errors = true) const + { + return mValue.validateBlock(emit_errors); + } + + static BlockDescriptor& getBlockDescriptor() + { + return T::getBlockDescriptor(); + } + + mutable bool mValidated; // lazy validation flag - }; - template<typename T, typename BLOCK_IDENTIFIER> - struct IsBlock<BaseBlock::Lazy<T, IS_BLOCK>, BLOCK_IDENTIFIER> - { - typedef IS_BLOCK value_t; - }; + private: + static const T& defaultBatchValue() + { + static T default_value; + return default_value; + } - template<typename T, typename BLOCK_IDENTIFIER> - struct IsBlock<BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_IDENTIFIER> - { - typedef NOT_BLOCK value_t; + T mValue; }; - //template<typename T, typename BLOCK_IDENTIFIER> - //struct IsBlock<BaseBlock::Lazy<T, void>, BLOCK_IDENTIFIER> - //{ - // typedef typename IsBlock<T>::value_t value_t; - //}; - - template<typename T> + template<typename T, typename BLOCK_T> class ParamValue <BaseBlock::Lazy<T, IS_BLOCK>, TypeValues<BaseBlock::Lazy<T, IS_BLOCK> >, - IS_BLOCK> + BLOCK_T> : public TypeValues<T> { public: - typedef ParamValue <BaseBlock::Lazy<T, IS_BLOCK>, TypeValues<BaseBlock::Lazy<T, IS_BLOCK> >, IS_BLOCK> self_t; + typedef ParamValue <BaseBlock::Lazy<T, IS_BLOCK>, TypeValues<BaseBlock::Lazy<T, IS_BLOCK> >, BLOCK_T> self_t; typedef const T& value_assignment_t; typedef T value_t; + typedef BaseBlock::Lazy<T, IS_BLOCK> default_value_t; ParamValue() : mValue(), mValidated(false) {} - ParamValue(const BaseBlock::Lazy<T, IS_BLOCK>& other) + ParamValue(const default_value_t& other) : mValue(other), mValidated(false) {} @@ -2052,6 +2089,21 @@ namespace LLInitParam return mValue.get(); } + void operator ()(const typename TypeValues<T>::name_t& name) + { + *this = name; + } + + self_t& operator =(const typename TypeValues<T>::name_t& name) + { + if (TypeValues<T>::getValueFromName(name, mValue.get())) + { + setValueName(name); + } + + return *this; + } + bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) { return mValue.get().deserializeBlock(p, name_stack_range, new_name); @@ -2074,7 +2126,7 @@ namespace LLInitParam bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) { - return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite); + return source.mValue.empty() || mValue.get().mergeBlock(block_data, source, overwrite); } bool validateBlock(bool emit_errors = true) const @@ -2094,6 +2146,79 @@ namespace LLInitParam BaseBlock::Lazy<T, IS_BLOCK> mValue; }; + template<typename T, typename BLOCK_T> + class ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, + TypeValues<BaseBlock::Lazy<T, NOT_BLOCK> >, + BLOCK_T> + : public TypeValues<T> + { + public: + typedef ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, TypeValues<BaseBlock::Lazy<T, NOT_BLOCK> >, BLOCK_T> self_t; + typedef const T& value_assignment_t; + typedef T value_t; + typedef BaseBlock::Lazy<T, NOT_BLOCK> default_value_t; + + ParamValue() + : mValue(), + mValidated(false) + {} + + ParamValue(const default_value_t& other) + : mValue(other), + mValidated(false) + {} + + ParamValue(const T& value) + : mValue(value), + mValidated(false) + {} + + void setValue(value_assignment_t val) + { + mValue.set(val); + } + + value_assignment_t getValue() const + { + return mValue.get(); + } + + T& getValue() + { + return mValue.get(); + } + + operator value_assignment_t() const + { + return mValue.get(); + } + + value_assignment_t operator()() const + { + return mValue.get(); + } + + void operator ()(const typename TypeValues<T>::name_t& name) + { + *this = name; + } + + self_t& operator =(const typename TypeValues<T>::name_t& name) + { + if (TypeValues<T>::getValueFromName(name, mValue.get())) + { + setValueName(name); + } + + return *this; + } + + mutable bool mValidated; // lazy validation flag + + private: + BaseBlock::Lazy<T, NOT_BLOCK> mValue; + }; + template <> class ParamValue <LLSD, TypeValues<LLSD>, @@ -2104,12 +2229,13 @@ namespace LLInitParam public: typedef ParamValue<LLSD, TypeValues<LLSD>, NOT_BLOCK> self_t; typedef const LLSD& value_assignment_t; + typedef LLSD default_value_t; ParamValue() : mValidated(false) {} - ParamValue(value_assignment_t other) + ParamValue(const default_value_t& other) : mValue(other), mValidated(false) {} @@ -2122,7 +2248,6 @@ namespace LLInitParam operator value_assignment_t() const { return mValue; } value_assignment_t operator()() const { return mValue; } - // block param interface bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; @@ -2143,7 +2268,7 @@ namespace LLInitParam template<typename T> class CustomParamValue - : public Block<ParamValue<T, TypeValues<T> > >, + : public Block<ParamValue<T, TypeValues<T>, typename IsBlock<T>::value_t > >, public TypeValues<T> { public: @@ -2154,14 +2279,16 @@ namespace LLInitParam BLOCK_AUTHORITATIVE // mValue is derived from the block parameters, which are authoritative } EValueAge; - typedef ParamValue<T, TypeValues<T> > derived_t; + typedef ParamValue<T, TypeValues<T>, typename IsBlock<T>::value_t > derived_t; typedef CustomParamValue<T> self_t; typedef Block<derived_t> block_t; typedef const T& value_assignment_t; + typedef T default_value_t; typedef T value_t; + typedef void baseblock_base_class_t; - CustomParamValue(const T& value = T()) + CustomParamValue(const default_value_t& value = T()) : mValue(value), mValueAge(VALUE_AUTHORITATIVE), mValidated(false) @@ -2316,6 +2443,20 @@ namespace LLInitParam return getValue(); } + void operator ()(const typename TypeValues<T>::name_t& name) + { + *this = name; + } + + self_t& operator =(const typename TypeValues<T>::name_t& name) + { + if (TypeValues<T>::getValueFromName(name, mValue)) + { + setValueName(name); + } + + return *this; + } protected: // use this from within updateValueFromBlock() to set the value without making it authoritative diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index 3c89fa3aaf..ce8c8411ea 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -130,7 +130,7 @@ struct Any : public LLInitParam::Block<Any, Occurs> struct All : public LLInitParam::Block<All, Occurs> { - Multiple< Lazy<Element> > elements; + Multiple< Lazy<Element, IS_BLOCK> > elements; All() : elements("element") @@ -141,11 +141,11 @@ struct All : public LLInitParam::Block<All, Occurs> struct Choice : public LLInitParam::ChoiceBlock<Choice, Occurs> { - Alternative< Lazy<Element> > element; - Alternative< Lazy<Group> > group; - Alternative< Lazy<Choice> > choice; - Alternative< Lazy<Sequence> > sequence; - Alternative< Lazy<Any> > any; + Alternative< Lazy<Element, IS_BLOCK> > element; + Alternative< Lazy<Group, IS_BLOCK> > group; + Alternative< Lazy<Choice, IS_BLOCK> > choice; + Alternative< Lazy<Sequence, IS_BLOCK> > sequence; + Alternative< Lazy<Any, IS_BLOCK> > any; Choice() : element("element"), @@ -159,11 +159,11 @@ struct Choice : public LLInitParam::ChoiceBlock<Choice, Occurs> struct Sequence : public LLInitParam::ChoiceBlock<Sequence, Occurs> { - Alternative< Lazy<Element> > element; - Alternative< Lazy<Group> > group; - Alternative< Lazy<Choice> > choice; - Alternative< Lazy<Sequence> > sequence; - Alternative< Lazy<Any> > any; + Alternative< Lazy<Element, IS_BLOCK> > element; + Alternative< Lazy<Group, IS_BLOCK> > group; + Alternative< Lazy<Choice, IS_BLOCK> > choice; + Alternative< Lazy<Sequence, IS_BLOCK> > sequence; + Alternative< Lazy<Any, IS_BLOCK> > any; }; struct GroupContents : public LLInitParam::ChoiceBlock<GroupContents, Occurs> @@ -248,7 +248,7 @@ struct ComplexType : public LLInitParam::Block<ComplexType, ComplexTypeContents> Optional<bool> mixed; Multiple<Attribute> attribute; - Multiple< Lazy<Element> > elements; + Multiple< Lazy<Element, IS_BLOCK > > elements; ComplexType() : name("name"), @@ -343,7 +343,7 @@ void LLXSDWriter::writeXSD(const std::string& type_name, LLXMLNodePtr node, cons { Schema schema(xml_namespace); - schema.root_element.name = type_name; + schema.root_element.super_t::param_value_t::name = type_name; Choice& choice = schema.root_element.complexType.choice; choice.minOccurs = 0; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index f47cce9a4d..c483aa58c9 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -248,7 +248,7 @@ struct LLVOAvatarCollisionVolumeInfo : public LLInitParam::Block<LLVOAvatarColli struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock<LLVOAvatarChildJoint> { - Alternative<Lazy<struct LLVOAvatarBoneInfo> > bone; + Alternative<Lazy<struct LLVOAvatarBoneInfo, IS_BLOCK> > bone; Alternative<LLVOAvatarCollisionVolumeInfo> collision_volume; LLVOAvatarChildJoint() -- cgit v1.2.3 From fc780921c1e3c411014fe22a31a0fe4d0fd0b2cf Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 12 Apr 2012 18:14:00 -0700 Subject: attempted fix of gcc build --- indra/llxuixml/llinitparam.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 0c53b36bad..75c09125eb 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -399,7 +399,7 @@ namespace LLInitParam {}; //TODO: implement in terms of owned_ptr - template<typename T, typename BLOCK_T = IsBlock<T>::value_t > + template<typename T, typename BLOCK_T = typename IsBlock<T>::value_t > class Lazy { public: @@ -815,8 +815,8 @@ namespace LLInitParam template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > struct ParamIterator { - typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> >::const_iterator const_iterator; - typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> >::iterator iterator; + typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::const_iterator const_iterator; + typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::iterator iterator; }; // specialize for custom parsing/decomposition of specific classes @@ -824,14 +824,14 @@ namespace LLInitParam template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>, bool HAS_MULTIPLE_VALUES = false, - typename VALUE_IS_BLOCK = typename IsBlock<ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> >::value_t> + typename VALUE_IS_BLOCK = typename IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value_t> class TypedParam : public Param, - public ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> + public ParamValue<T, NAME_VALUE_LOOKUP> { public: typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t; - typedef ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> param_value_t; + typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; typedef typename param_value_t::value_assignment_t value_assignment_t; typedef typename param_value_t::default_value_t default_value_t; @@ -983,10 +983,10 @@ namespace LLInitParam template <typename T, typename NAME_VALUE_LOOKUP> class TypedParam<T, NAME_VALUE_LOOKUP, false, IS_BLOCK> : public Param, - public ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> + public ParamValue<T, NAME_VALUE_LOOKUP> { public: - typedef ParamValue<T, NAME_VALUE_LOOKUP, typename IsBlock<T>::value_t> param_value_t; + typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; typedef typename param_value_t::value_assignment_t value_assignment_t; typedef typename param_value_t::default_value_t default_value_t; typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_BLOCK> self_t; @@ -1918,7 +1918,7 @@ namespace LLInitParam template<typename T, typename BLOCK_IDENTIFIER> struct IsBlock<ParamValue<BaseBlock::Batch<T>, TypeValues<BaseBlock::Batch<T> >, typename IsBlock<BaseBlock::Batch<T> >::value_t >, BLOCK_IDENTIFIER> { - typedef typename IsBlock<ParamValue<T, TypeValues<T>, typename IsBlock<T>::value_t > >::value_t value_t; + typedef typename IsBlock<ParamValue<T, TypeValues<T> > >::value_t value_t; }; template<typename T, typename BLOCK_T> @@ -1929,7 +1929,7 @@ namespace LLInitParam { public: typedef ParamValue <BaseBlock::Batch<T>, TypeValues<BaseBlock::Batch<T> >, BLOCK_T> self_t; - typedef ParamValue<T, TypeValues<T>, typename IsBlock<T>::value_t > param_value_t; + typedef ParamValue<T, TypeValues<T> > param_value_t; typedef const T& value_assignment_t; typedef T value_t; typedef T default_value_t; @@ -2268,7 +2268,7 @@ namespace LLInitParam template<typename T> class CustomParamValue - : public Block<ParamValue<T, TypeValues<T>, typename IsBlock<T>::value_t > >, + : public Block<ParamValue<T, TypeValues<T> > >, public TypeValues<T> { public: @@ -2279,7 +2279,7 @@ namespace LLInitParam BLOCK_AUTHORITATIVE // mValue is derived from the block parameters, which are authoritative } EValueAge; - typedef ParamValue<T, TypeValues<T>, typename IsBlock<T>::value_t > derived_t; + typedef ParamValue<T, TypeValues<T> > derived_t; typedef CustomParamValue<T> self_t; typedef Block<derived_t> block_t; typedef const T& value_assignment_t; -- cgit v1.2.3 From 61d202a15d70ec56e46bca2edadd49cfd5cbb956 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 13 Apr 2012 11:48:37 -0700 Subject: renamed Lazy to Atomic --- indra/llui/llloadingindicator.h | 2 +- indra/llxuixml/llinitparam.h | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h index 4998a57263..ffcb329f42 100644 --- a/indra/llui/llloadingindicator.h +++ b/indra/llui/llloadingindicator.h @@ -63,7 +63,7 @@ public: struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> { Optional<F32> images_per_sec; - Optional<Batch<Images> > images; + Optional<Atomic<Images> > images; Params() : images_per_sec("images_per_sec", 1.0f), diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 75c09125eb..dcbbf9f0a7 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -395,7 +395,7 @@ namespace LLInitParam typedef LLInitParam::NOT_BLOCK NOT_BLOCK; template<typename T> - class Batch + class Atomic {}; //TODO: implement in terms of owned_ptr @@ -1916,19 +1916,19 @@ namespace LLInitParam }; template<typename T, typename BLOCK_IDENTIFIER> - struct IsBlock<ParamValue<BaseBlock::Batch<T>, TypeValues<BaseBlock::Batch<T> >, typename IsBlock<BaseBlock::Batch<T> >::value_t >, BLOCK_IDENTIFIER> + struct IsBlock<ParamValue<BaseBlock::Atomic<T>, TypeValues<BaseBlock::Atomic<T> >, typename IsBlock<BaseBlock::Atomic<T> >::value_t >, BLOCK_IDENTIFIER> { typedef typename IsBlock<ParamValue<T, TypeValues<T> > >::value_t value_t; }; template<typename T, typename BLOCK_T> - class ParamValue <BaseBlock::Batch<T>, - TypeValues<BaseBlock::Batch<T> >, + class ParamValue <BaseBlock::Atomic<T>, + TypeValues<BaseBlock::Atomic<T> >, BLOCK_T> : public TypeValues<T> { public: - typedef ParamValue <BaseBlock::Batch<T>, TypeValues<BaseBlock::Batch<T> >, BLOCK_T> self_t; + typedef ParamValue <BaseBlock::Atomic<T>, TypeValues<BaseBlock::Atomic<T> >, BLOCK_T> self_t; typedef ParamValue<T, TypeValues<T> > param_value_t; typedef const T& value_assignment_t; typedef T value_t; @@ -1985,8 +1985,7 @@ namespace LLInitParam { if (new_name) { - // reset block - mValue = defaultBatchValue(); + resetToDefault(); } return mValue.deserializeBlock(p, name_stack_range, new_name); } @@ -2008,7 +2007,7 @@ namespace LLInitParam { if (overwrite) { - mValue = defaultBatchValue(); + resetToDefault(); return mValue.mergeBlock(block_data, source, overwrite); } return false; @@ -2028,10 +2027,10 @@ namespace LLInitParam mutable bool mValidated; // lazy validation flag private: - static const T& defaultBatchValue() + void resetToDefault() { static T default_value; - return default_value; + mValue = default_value; } T mValue; -- cgit v1.2.3 From 5b4990ce6a7fbf5d757e86362d134061fa54a1e9 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 13 Apr 2012 12:51:34 -0700 Subject: more LLInitParam cleanup cleaned up typedefs, and hid those that aren't part of the interface --- indra/llxuixml/llinitparam.h | 387 ++++++++++++++++++++--------------------- indra/llxuixml/llxuiparser.cpp | 2 +- 2 files changed, 193 insertions(+), 196 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index dcbbf9f0a7..09617209a8 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -387,111 +387,112 @@ namespace LLInitParam typedef IS_BLOCK value_t; }; - class BaseBlock + //TODO: implement in terms of owned_ptr + template<typename T> + class LazyValue { public: - // lift block tags into baseblock namespace so derived classes do not need to qualify them - typedef LLInitParam::IS_BLOCK IS_BLOCK; - typedef LLInitParam::NOT_BLOCK NOT_BLOCK; + LazyValue() + : mPtr(NULL) + {} - template<typename T> - class Atomic - {}; + ~LazyValue() + { + delete mPtr; + } - //TODO: implement in terms of owned_ptr - template<typename T, typename BLOCK_T = typename IsBlock<T>::value_t > - class Lazy + LazyValue(const T& value) { - public: - Lazy() - : mPtr(NULL) - {} + mPtr = new T(value); + } - ~Lazy() + LazyValue(const LazyValue& other) + { + if (other.mPtr) { - delete mPtr; + mPtr = new T(*other.mPtr); } - - Lazy(const T& value) + else { - mPtr = new T(value); + mPtr = NULL; } + } - Lazy(const Lazy& other) + LazyValue& operator = (const LazyValue& other) + { + if (other.mPtr) { - if (other.mPtr) - { - mPtr = new T(*other.mPtr); - } - else - { - mPtr = NULL; - } + mPtr = new T(*other.mPtr); } - - Lazy& operator = (const Lazy& other) + else { - if (other.mPtr) - { - mPtr = new T(*other.mPtr); - } - else - { - mPtr = NULL; - } - return *this; + mPtr = NULL; } + return *this; + } - bool operator==(const Lazy& other) const - { - if (empty() || other.empty()) return false; - return *mPtr == *other.mPtr; - } + bool operator==(const LazyValue& other) const + { + if (empty() || other.empty()) return false; + return *mPtr == *other.mPtr; + } - bool empty() const - { - return mPtr == NULL; - } + bool empty() const + { + return mPtr == NULL; + } - void set(const T& other) - { - delete mPtr; - mPtr = new T(other); - } + void set(const T& other) + { + delete mPtr; + mPtr = new T(other); + } - const T& get() const - { - return *ensureInstance(); - } + const T& get() const + { + return *ensureInstance(); + } - T& get() - { - return *ensureInstance(); - } + T& get() + { + return *ensureInstance(); + } - operator const T&() const - { - return get(); - } + operator const T&() const + { + return get(); + } - private: - // lazily allocate an instance of T - T* ensureInstance() const + private: + // lazily allocate an instance of T + T* ensureInstance() const + { + if (mPtr == NULL) { - if (mPtr == NULL) - { - mPtr = new T(); - } - return mPtr; + mPtr = new T(); } + return mPtr; + } - private: - // if you get a compilation error with this, that means you are using a forward declared struct for T - // unfortunately, the type traits we rely on don't work with forward declared typed - //static const int dummy = sizeof(T); + private: - mutable T* mPtr; - }; + mutable T* mPtr; + }; + + class BaseBlock + { + public: + // lift block tags into baseblock namespace so derived classes do not need to qualify them + typedef LLInitParam::IS_BLOCK IS_BLOCK; + typedef LLInitParam::NOT_BLOCK NOT_BLOCK; + + template<typename T> + class Atomic + {}; + + template<typename T, typename BLOCK_T = typename IsBlock<T>::value_t > + class Lazy + {}; // "Multiple" constraint types, put here in root class to avoid ambiguity during use struct AnyAmount @@ -644,21 +645,21 @@ namespace LLInitParam template<typename T, typename NAME_VALUE_LOOKUP, typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t> class ParamValue : public NAME_VALUE_LOOKUP { + typedef ParamValue<T, NAME_VALUE_LOOKUP, VALUE_IS_BLOCK> self_t; + public: - typedef const T& value_assignment_t; typedef T default_value_t; typedef T value_t; - typedef ParamValue<T, NAME_VALUE_LOOKUP, VALUE_IS_BLOCK> self_t; ParamValue(): mValue() {} ParamValue(const default_value_t& other) : mValue(other) {} - void setValue(value_assignment_t val) + void setValue(const value_t& val) { mValue = val; } - value_assignment_t getValue() const + const value_t& getValue() const { return mValue; } @@ -668,12 +669,12 @@ namespace LLInitParam return mValue; } - operator value_assignment_t() const + operator const value_t&() const { return mValue; } - value_assignment_t operator()() const + const value_t& operator()() const { return mValue; } @@ -702,11 +703,10 @@ namespace LLInitParam : public T, public NAME_VALUE_LOOKUP { + typedef ParamValue<T, NAME_VALUE_LOOKUP, IS_BLOCK> self_t; public: - typedef const T& value_assignment_t; typedef T default_value_t; typedef T value_t; - typedef ParamValue<T, NAME_VALUE_LOOKUP, IS_BLOCK> self_t; ParamValue() : T(), @@ -718,12 +718,12 @@ namespace LLInitParam mValidated(false) {} - void setValue(value_assignment_t val) + void setValue(const value_t& val) { *this = val; } - value_assignment_t getValue() const + const value_t& getValue() const { return *this; } @@ -733,12 +733,12 @@ namespace LLInitParam return *this; } - operator value_assignment_t() const + operator const value_t&() const { return *this; } - value_assignment_t operator()() const + const value_t& operator()() const { return *this; } @@ -766,16 +766,15 @@ namespace LLInitParam class ParamValue<std::string, NAME_VALUE_LOOKUP, NOT_BLOCK> : public NAME_VALUE_LOOKUP { + typedef ParamValue<std::string, NAME_VALUE_LOOKUP, NOT_BLOCK> self_t; public: - typedef const std::string& value_assignment_t; typedef std::string default_value_t; typedef std::string value_t; - typedef ParamValue<std::string, NAME_VALUE_LOOKUP, NOT_BLOCK> self_t; ParamValue(): mValue() {} ParamValue(const default_value_t& other) : mValue(other) {} - void setValue(value_assignment_t val) + void setValue(const value_t& val) { if (NAME_VALUE_LOOKUP::getValueFromName(val, mValue)) { @@ -787,7 +786,7 @@ namespace LLInitParam } } - value_assignment_t getValue() const + const value_t& getValue() const { return mValue; } @@ -797,12 +796,12 @@ namespace LLInitParam return mValue; } - operator value_assignment_t() const + operator const value_t&() const { return mValue; } - value_assignment_t operator()() const + const value_t& operator()() const { return mValue; } @@ -829,12 +828,12 @@ namespace LLInitParam : public Param, public ParamValue<T, NAME_VALUE_LOOKUP> { - public: + protected: typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t; typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; - typedef typename param_value_t::value_assignment_t value_assignment_t; + typedef typename param_value_t::value_t value_t; typedef typename param_value_t::default_value_t default_value_t; - + public: using param_value_t::operator(); TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) @@ -930,7 +929,7 @@ namespace LLInitParam } } - void set(value_assignment_t val, bool flag_as_provided = true) + void set(const value_t& val, bool flag_as_provided = true) { param_value_t::clearValueName(); setValue(val); @@ -985,12 +984,12 @@ namespace LLInitParam : public Param, public ParamValue<T, NAME_VALUE_LOOKUP> { - public: - typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; - typedef typename param_value_t::value_assignment_t value_assignment_t; - typedef typename param_value_t::default_value_t default_value_t; + protected: + typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; + typedef typename param_value_t::value_t value_t; + typedef typename param_value_t::default_value_t default_value_t; typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_BLOCK> self_t; - + public: using param_value_t::operator(); TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) @@ -1078,7 +1077,7 @@ namespace LLInitParam } // assign block contents to this param-that-is-a-block - void set(value_assignment_t val, bool flag_as_provided = true) + void set(const value_t& val, bool flag_as_provided = true) { setValue(val); param_value_t::clearValueName(); @@ -1157,15 +1156,14 @@ namespace LLInitParam class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> : public Param { - public: - typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t; - typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP, typename IsBlock<VALUE_TYPE>::value_t> param_value_t; - typedef typename std::vector<param_value_t> container_t; - typedef const container_t& value_assignment_t; - typedef container_t default_value_t; - - typedef typename param_value_t::value_t value_t; + protected: + typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t; + typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP, typename IsBlock<VALUE_TYPE>::value_t> param_value_t; + typedef typename std::vector<param_value_t> container_t; + typedef container_t default_value_t; + typedef typename param_value_t::value_t value_t; + public: TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) { @@ -1259,7 +1257,7 @@ namespace LLInitParam } } - void set(value_assignment_t val, bool flag_as_provided = true) + void set(const container_t& val, bool flag_as_provided = true) { mValues = val; setProvided(flag_as_provided); @@ -1293,9 +1291,9 @@ namespace LLInitParam } // implicit conversion - operator value_assignment_t() const { return mValues; } + operator const container_t&() const { return mValues; } // explicit conversion - value_assignment_t operator()() const { return mValues; } + const container_t& operator()() const { return mValues; } typedef typename container_t::iterator iterator; typedef typename container_t::const_iterator const_iterator; @@ -1357,14 +1355,15 @@ namespace LLInitParam class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_BLOCK> : public Param { + protected: + typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_BLOCK> self_t; + typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP, typename IsBlock<VALUE_TYPE>::value_t> param_value_t; + typedef typename std::vector<param_value_t> container_t; + typedef typename param_value_t::value_t value_t; + typedef container_t default_value_t; + typedef typename container_t::iterator iterator; + typedef typename container_t::const_iterator const_iterator; public: - typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_BLOCK> self_t; - typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP, typename IsBlock<VALUE_TYPE>::value_t> param_value_t; - typedef typename std::vector<param_value_t> container_t; - typedef const container_t& value_assignment_t; - typedef typename param_value_t::value_t value_t; - typedef container_t default_value_t; - TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) { @@ -1453,7 +1452,7 @@ namespace LLInitParam param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count); } - void set(value_assignment_t val, bool flag_as_provided = true) + void set(const container_t& val, bool flag_as_provided = true) { mValues = val; setProvided(flag_as_provided); @@ -1485,12 +1484,10 @@ namespace LLInitParam } // implicit conversion - operator value_assignment_t() const { return mValues; } + operator const container_t&() const { return mValues; } // explicit conversion - value_assignment_t operator()() const { return mValues; } + const container_t& operator()() const { return mValues; } - typedef typename container_t::iterator iterator; - typedef typename container_t::const_iterator const_iterator; iterator begin() { return mValues.begin(); } iterator end() { return mValues.end(); } const_iterator begin() const { return mValues.begin(); } @@ -1626,14 +1623,13 @@ namespace LLInitParam template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false> { - public: - friend class ChoiceBlock<DERIVED_BLOCK>; - - typedef Alternative<T, NAME_VALUE_LOOKUP> self_t; typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; - typedef typename super_t::value_assignment_t value_assignment_t; + typedef typename super_t::value_t value_t; typedef typename super_t::default_value_t default_value_t; + public: + friend class ChoiceBlock<DERIVED_BLOCK>; + using super_t::operator =; explicit Alternative(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) @@ -1656,27 +1652,27 @@ namespace LLInitParam static_cast<enclosing_block_t&>(Param::enclosingBlock()).paramChanged(*this, true); } - void chooseAs(value_assignment_t val) + void chooseAs(const value_t& val) { super_t::set(val); } - void operator =(value_assignment_t val) + void operator =(const value_t& val) { super_t::set(val); } - void operator()(typename super_t::value_assignment_t val) + void operator()(typename const value_t& val) { super_t::set(val); } - operator value_assignment_t() const + operator const value_t&() const { return (*this)(); } - value_assignment_t operator()() const + const value_t& operator()() const { if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this) { @@ -1691,7 +1687,7 @@ namespace LLInitParam } private: - T mOriginalValue; + default_value_t mOriginalValue; }; public: @@ -1715,6 +1711,8 @@ namespace LLInitParam : public BASE_BLOCK { typedef Block<DERIVED_BLOCK, BASE_BLOCK> self_t; + + protected: typedef Block<DERIVED_BLOCK, BASE_BLOCK> block_t; public: @@ -1748,11 +1746,11 @@ namespace LLInitParam template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false> { - public: typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; - typedef typename super_t::value_assignment_t value_assignment_t; + typedef typename super_t::value_t value_t; typedef typename super_t::default_value_t default_value_t; + public: using super_t::operator(); using super_t::operator =; @@ -1762,13 +1760,13 @@ namespace LLInitParam //#pragma message("Parsing LLInitParam::Block::Optional") } - Optional& operator =(value_assignment_t val) + Optional& operator =(const value_t& val) { set(val); return *this; } - DERIVED_BLOCK& operator()(value_assignment_t val) + DERIVED_BLOCK& operator()(const value_t& val) { super_t::set(val); return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1778,12 +1776,12 @@ namespace LLInitParam template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false> { - public: typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t; - typedef typename super_t::value_assignment_t value_assignment_t; + typedef typename super_t::value_t value_t; typedef typename super_t::default_value_t default_value_t; + public: using super_t::operator(); using super_t::operator =; @@ -1792,13 +1790,13 @@ namespace LLInitParam : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, &validate, 1, 1) {} - Mandatory& operator =(value_assignment_t val) + Mandatory& operator =(const value_t& val) { set(val); return *this; } - DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) + DERIVED_BLOCK& operator()(typename const value_t& val) { super_t::set(val); return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1815,25 +1813,27 @@ namespace LLInitParam template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> > class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true> { - public: typedef TypedParam<T, NAME_VALUE_LOOKUP, true> super_t; typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t; typedef typename super_t::container_t container_t; - typedef typename super_t::value_assignment_t value_assignment_t; - typedef typename super_t::iterator iterator; - typedef typename super_t::const_iterator const_iterator; + typedef typename super_t::value_t value_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, true> super_t; + + public: + typedef typename super_t::iterator iterator; + typedef typename super_t::const_iterator const_iterator; explicit Multiple(const char* name = "") : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) {} - Multiple& operator =(value_assignment_t val) + Multiple& operator =(const container_t& val) { set(val); return *this; } - DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) + DERIVED_BLOCK& operator()(typename const container_t& val) { super_t::set(val); return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1893,7 +1893,7 @@ namespace LLInitParam protected: template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, typename is_block> void changeDefault(TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>& param, - typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_assignment_t value) + const typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_t& value) { if (!param.isProvided()) { @@ -1927,12 +1927,11 @@ namespace LLInitParam BLOCK_T> : public TypeValues<T> { - public: typedef ParamValue <BaseBlock::Atomic<T>, TypeValues<BaseBlock::Atomic<T> >, BLOCK_T> self_t; - typedef ParamValue<T, TypeValues<T> > param_value_t; - typedef const T& value_assignment_t; - typedef T value_t; - typedef T default_value_t; + + public: + typedef T value_t; + typedef T default_value_t; ParamValue() : mValue(), @@ -1944,7 +1943,7 @@ namespace LLInitParam mValidated(false) {} - void setValue(value_assignment_t val) + void setValue(const value_t& val) { mValue.setValue(val); } @@ -1959,12 +1958,12 @@ namespace LLInitParam return mValue; } - operator value_assignment_t() const + operator const value_t&() const { return mValue; } - value_assignment_t operator()() const + const value_t& operator()() const { return mValue; } @@ -2042,11 +2041,11 @@ namespace LLInitParam BLOCK_T> : public TypeValues<T> { - public: typedef ParamValue <BaseBlock::Lazy<T, IS_BLOCK>, TypeValues<BaseBlock::Lazy<T, IS_BLOCK> >, BLOCK_T> self_t; - typedef const T& value_assignment_t; - typedef T value_t; - typedef BaseBlock::Lazy<T, IS_BLOCK> default_value_t; + + public: + typedef T value_t; + typedef LazyValue<T> default_value_t; ParamValue() : mValue(), @@ -2063,12 +2062,12 @@ namespace LLInitParam mValidated(false) {} - void setValue(value_assignment_t val) + void setValue(const value_t& val) { mValue.set(val); } - value_assignment_t getValue() const + const value_t& getValue() const { return mValue.get(); } @@ -2078,12 +2077,12 @@ namespace LLInitParam return mValue.get(); } - operator value_assignment_t() const + operator const value_t&() const { return mValue.get(); } - value_assignment_t operator()() const + const value_t& operator()() const { return mValue.get(); } @@ -2142,7 +2141,7 @@ namespace LLInitParam mutable bool mValidated; // lazy validation flag private: - BaseBlock::Lazy<T, IS_BLOCK> mValue; + LazyValue<T> mValue; }; template<typename T, typename BLOCK_T> @@ -2151,11 +2150,11 @@ namespace LLInitParam BLOCK_T> : public TypeValues<T> { - public: typedef ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, TypeValues<BaseBlock::Lazy<T, NOT_BLOCK> >, BLOCK_T> self_t; - typedef const T& value_assignment_t; - typedef T value_t; - typedef BaseBlock::Lazy<T, NOT_BLOCK> default_value_t; + + public: + typedef T value_t; + typedef LazyValue<T> default_value_t; ParamValue() : mValue(), @@ -2172,12 +2171,12 @@ namespace LLInitParam mValidated(false) {} - void setValue(value_assignment_t val) + void setValue(const value_t& val) { mValue.set(val); } - value_assignment_t getValue() const + const value_t& getValue() const { return mValue.get(); } @@ -2187,12 +2186,12 @@ namespace LLInitParam return mValue.get(); } - operator value_assignment_t() const + operator const value_t&() const { return mValue.get(); } - value_assignment_t operator()() const + const value_t& operator()() const { return mValue.get(); } @@ -2215,7 +2214,7 @@ namespace LLInitParam mutable bool mValidated; // lazy validation flag private: - BaseBlock::Lazy<T, NOT_BLOCK> mValue; + LazyValue<T> mValue; }; template <> @@ -2226,9 +2225,8 @@ namespace LLInitParam public BaseBlock { public: - typedef ParamValue<LLSD, TypeValues<LLSD>, NOT_BLOCK> self_t; - typedef const LLSD& value_assignment_t; - typedef LLSD default_value_t; + typedef LLSD value_t; + typedef LLSD default_value_t; ParamValue() : mValidated(false) @@ -2239,13 +2237,13 @@ namespace LLInitParam mValidated(false) {} - void setValue(value_assignment_t val) { mValue = val; } + void setValue(const value_t& val) { mValue = val; } - value_assignment_t getValue() const { return mValue; } + const value_t& getValue() const { return mValue; } LLSD& getValue() { return mValue; } - operator value_assignment_t() const { return mValue; } - value_assignment_t operator()() const { return mValue; } + operator const value_t&() const { return mValue; } + const value_t& operator()() const { return mValue; } // block param interface bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); @@ -2281,7 +2279,6 @@ namespace LLInitParam typedef ParamValue<T, TypeValues<T> > derived_t; typedef CustomParamValue<T> self_t; typedef Block<derived_t> block_t; - typedef const T& value_assignment_t; typedef T default_value_t; typedef T value_t; typedef void baseblock_base_class_t; @@ -2410,7 +2407,7 @@ namespace LLInitParam } } - void setValue(value_assignment_t val) + void setValue(const value_t& val) { derived_t& typed_param = static_cast<derived_t&>(*this); // set param version number to be up to date, so we ignore block contents @@ -2420,7 +2417,7 @@ namespace LLInitParam static_cast<derived_t*>(this)->updateBlockFromValue(false); } - value_assignment_t getValue() const + const value_t& getValue() const { validateBlock(true); return mValue; @@ -2432,12 +2429,12 @@ namespace LLInitParam return mValue; } - operator value_assignment_t() const + operator const value_t&() const { return getValue(); } - value_assignment_t operator()() const + const value_t& operator()() const { return getValue(); } @@ -2459,7 +2456,7 @@ namespace LLInitParam protected: // use this from within updateValueFromBlock() to set the value without making it authoritative - void updateValue(value_assignment_t value) + void updateValue(const value_t& value) { mValue = value; } diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index ce8c8411ea..2e1f8888d0 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -343,7 +343,7 @@ void LLXSDWriter::writeXSD(const std::string& type_name, LLXMLNodePtr node, cons { Schema schema(xml_namespace); - schema.root_element.super_t::param_value_t::name = type_name; + schema.root_element.name = type_name; Choice& choice = schema.root_element.complexType.choice; choice.minOccurs = 0; -- cgit v1.2.3 From 3fdcb8751a1f36dbce9d7a3fd1d785160d356d3a Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Fri, 13 Apr 2012 23:31:01 +0300 Subject: CHUI-91 FIXED Moved block list to a separate People floater tab. --- indra/newview/llchathistory.cpp | 3 ++- indra/newview/llfloaterpreference.cpp | 3 ++- indra/newview/llfloatersidepanelcontainer.cpp | 5 +--- indra/newview/llpanelblockedlist.cpp | 16 ++----------- indra/newview/llpanelblockedlist.h | 1 - indra/newview/llpanelpeople.cpp | 18 +++++--------- .../skins/default/xui/en/floater_people.xml | 10 ++------ .../default/xui/en/menu_people_friends_view.xml | 4 ---- .../default/xui/en/menu_people_nearby_view.xml | 9 ------- .../default/xui/en/menu_people_recent_view.xml | 4 ---- .../default/xui/en/panel_block_list_sidetray.xml | 28 ++-------------------- .../newview/skins/default/xui/en/panel_people.xml | 28 +++++++++++++++++++++- 12 files changed, 44 insertions(+), 85 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index f530d10ddc..5bdfb5adbc 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -143,7 +143,8 @@ public: { LLMuteList::getInstance()->add(LLMute(getAvatarId(), mFrom, LLMute::OBJECT)); - LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD().with("blocked_to_select", getAvatarId())); + LLFloaterSidePanelContainer::showPanel("people", "panel_people", + LLSD().with("people_panel_tab_name", "blocked_panel").with("blocked_to_select", getAvatarId())); } } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index a333989e7e..caf4a305b3 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1501,7 +1501,8 @@ void LLFloaterPreference::onChangeMaturity() // but the UI for this will still be enabled void LLFloaterPreference::onClickBlockList() { - LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); + LLFloaterSidePanelContainer::showPanel("people", "panel_people", + LLSD().with("people_panel_tab_name", "blocked_panel")); } void LLFloaterPreference::onClickProxySettings() diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index be7a53491d..977fdbbc46 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -66,10 +66,7 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(view->getParent()); if (container) { - LLSD new_params = params; - new_params[LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME] = panel_name; - container->onOpen(new_params); - + container->openPanel(panel_name, params); panel = container->getCurrentPanel(); } else if ((panel = dynamic_cast<LLPanel*>(view)) != NULL) diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index 5c85ec438c..d2dff63948 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -69,8 +69,6 @@ BOOL LLPanelBlockedList::postBuild() mBlockedList = getChild<LLScrollListCtrl>("blocked"); mBlockedList->setCommitOnSelectionChange(TRUE); - childSetCommitCallback("back", boost::bind(&LLPanelBlockedList::onBackBtnClick, this), NULL); - LLMuteList::getInstance()->addObserver(this); refreshBlockedList(); @@ -99,7 +97,8 @@ void LLPanelBlockedList::selectBlocked(const LLUUID& mute_id) void LLPanelBlockedList::showPanelAndSelect(const LLUUID& idToSelect) { - LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD().with(BLOCKED_PARAM_NAME, idToSelect)); + LLFloaterSidePanelContainer::showPanel("people", "panel_people", + LLSD().with("people_panel_tab_name", "blocked_panel").with(BLOCKED_PARAM_NAME, idToSelect)); } @@ -130,17 +129,6 @@ void LLPanelBlockedList::updateButtons() getChildView("Unblock")->setEnabled(hasSelected); } - - -void LLPanelBlockedList::onBackBtnClick() -{ - LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent()); - if(parent) - { - parent->openPreviousPanel(); - } -} - void LLPanelBlockedList::onRemoveBtnClick() { std::string name = mBlockedList->getSelectedItemLabel(); diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h index 74ad82e32d..97236ecdbf 100644 --- a/indra/newview/llpanelblockedlist.h +++ b/indra/newview/llpanelblockedlist.h @@ -68,7 +68,6 @@ private: void updateButtons(); // UI callbacks - void onBackBtnClick(); void onRemoveBtnClick(); void onPickBtnClick(); void onBlockByNameClick(); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index aceee7cf23..1c63b2a930 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -72,6 +72,7 @@ static const std::string NEARBY_TAB_NAME = "nearby_panel"; static const std::string FRIENDS_TAB_NAME = "friends_panel"; static const std::string GROUP_TAB_NAME = "groups_panel"; static const std::string RECENT_TAB_NAME = "recent_panel"; +static const std::string BLOCKED_TAB_NAME = "blocked_panel"; // blocked avatars static const std::string COLLAPSED_BY_USER = "collapsed_by_user"; @@ -886,6 +887,9 @@ LLUUID LLPanelPeople::getCurrentItemID() const if (cur_tab == GROUP_TAB_NAME) return mGroupList->getSelectedUUID(); + if (cur_tab == BLOCKED_TAB_NAME) + return LLUUID::null; // FIXME? + llassert(0 && "unknown tab selected"); return LLUUID::null; } @@ -906,6 +910,8 @@ void LLPanelPeople::getCurrentItemIDs(uuid_vec_t& selected_uuids) const mRecentList->getSelectedUUIDs(selected_uuids); else if (cur_tab == GROUP_TAB_NAME) mGroupList->getSelectedUUIDs(selected_uuids); + else if (cur_tab == BLOCKED_TAB_NAME) + selected_uuids.clear(); // FIXME? else llassert(0 && "unknown tab selected"); @@ -1228,10 +1234,6 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata) mAllFriendList->showPermissions(show_permissions); mOnlineFriendList->showPermissions(show_permissions); } - else if (chosen_item == "panel_block_list_sidetray") - { - LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); - } } void LLPanelPeople::onGroupsViewSortMenuItemClicked(const LLSD& userdata) @@ -1264,10 +1266,6 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata) { setSortOrder(mNearbyList, E_SORT_BY_DISTANCE); } - else if (chosen_item == "panel_block_list_sidetray") - { - LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); - } } bool LLPanelPeople::onNearbyViewSortMenuItemCheck(const LLSD& userdata) @@ -1301,10 +1299,6 @@ void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata) { mRecentList->toggleIcons(); } - else if (chosen_item == "panel_block_list_sidetray") - { - LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); - } } bool LLPanelPeople::onFriendsViewSortMenuItemCheck(const LLSD& userdata) diff --git a/indra/newview/skins/default/xui/en/floater_people.xml b/indra/newview/skins/default/xui/en/floater_people.xml index d6d8431150..029e4464ea 100644 --- a/indra/newview/skins/default/xui/en/floater_people.xml +++ b/indra/newview/skins/default/xui/en/floater_people.xml @@ -14,13 +14,13 @@ single_instance="true" reuse_instance="true" title="PEOPLE" - width="333"> + width="390"> <panel_container default_panel_name="panel_people" follows="all" height="570" name="main_panel" - width="333"> + width="390"> <panel class="panel_people" name="panel_people" @@ -31,11 +31,5 @@ filename="panel_group_info_sidetray.xml" label="Group Profile" font="SansSerifBold"/> - <panel - class="panel_block_list_sidetray" - name="panel_block_list_sidetray" - filename="panel_block_list_sidetray.xml" - label="Blocked Residents & Objects" - font="SansSerifBold"/> </panel_container> </floater> diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml index be23e91587..14a3e1f13d 100644 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml @@ -19,8 +19,4 @@ function="CheckControl" parameter="FriendsListShowPermissions" /> </menu_item_check> - <menu_item_separator layout="topleft" /> - <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> - <menu_item_call.on_click function="People.Friends.ViewSort.Action" parameter="panel_block_list_sidetray" /> - </menu_item_call> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml index 187dd3bcb5..4c94cf53af 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml @@ -19,13 +19,4 @@ function="ToggleControl" parameter="NearbyListShowMap" /> </menu_item_check> - <menu_item_separator - layout="topleft" /> - <menu_item_call - name="show_blocked_list" - label="Show Blocked Residents & Objects"> - <menu_item_call.on_click - function="People.Nearby.ViewSort.Action" - userdata="panel_block_list_sidetray" /> - </menu_item_call> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml index 5520bc993c..0eaca47d9a 100644 --- a/indra/newview/skins/default/xui/en/menu_people_recent_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml @@ -11,8 +11,4 @@ function="CheckControl" parameter="RecentListShowIcons" /> </menu_item_check> - <menu_item_separator layout="topleft" /> - <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> - <menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="panel_block_list_sidetray" /> - </menu_item_call> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml index 1e6a31d388..84b772d256 100644 --- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -9,38 +9,14 @@ min_height="350" min_width="240" width="280"> - <button - follows="top|left" - height="24" - image_hover_unselected="BackButton_Over" - image_pressed="BackButton_Press" - image_unselected="BackButton_Off" - layout="topleft" - name="back" - left="4" - tab_stop="false" - top="1" - width="30"/> - <text - follows="top|left|right" - font="SansSerifLargeBold" - height="20" - layout="topleft" - left_pad="10" - name="title_text" - text_color="white" - top="5" - width="250"> - Block List - </text> <scroll_list follows="all" - height="190" + height="220" layout="topleft" left="5" name="blocked" tool_tip="List of currently blocked Residents" - top="30" + top="0" width="270"> <scroll_list.columns name="item_name" /> diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index ad4a840106..03b6c4fb8b 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -66,7 +66,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M tab_position="top" top="0" halign="center" - width="319"> + right="-5"> <!-- ================================= NEARBY tab =========================== --> @@ -606,6 +606,32 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M top_pad="0" width="307" /> </panel> + +<!-- ================================= BLOCKED tab ========================== --> + + <panel + background_opaque="true" + background_visible="true" + bg_alpha_color="DkGray" + bg_opaque_color="DkGray" + follows="all" + height="383" + label="BLOCKED" + layout="topleft" + left="0" + help_topic="people_blocked_tab" + name="blocked_panel" + top="0" + width="313"> + <panel + class="panel_block_list_sidetray" + height="383" + name="panel_block_list_sidetray" + filename="panel_block_list_sidetray.xml" + label="Blocked Residents & Objects" + font="SansSerifBold" + width="313" /> + </panel> </tab_container> <panel follows="bottom|left|right" -- cgit v1.2.3 From 82c9b0fbbca6f61e57464a6126ae36a59b13d6ed Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 13 Apr 2012 23:07:48 -0700 Subject: fixed build all param values now support named values uniformly --- indra/llui/llui.cpp | 24 +- indra/llui/llui.h | 8 +- indra/llui/lluiimage.cpp | 4 +- indra/llui/lluiimage.h | 2 +- indra/llui/tests/llurlentry_stub.cpp | 16 +- indra/llui/tests/llurlmatch_test.cpp | 16 +- indra/llxuixml/llinitparam.h | 690 +++++++++++++++-------------------- indra/llxuixml/llxuiparser.cpp | 24 +- indra/newview/llvoavatar.cpp | 2 +- 9 files changed, 345 insertions(+), 441 deletions(-) (limited to 'indra') diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 6b74c5a6be..b52b0355fe 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -2107,7 +2107,7 @@ const LLView* LLUI::resolvePath(const LLView* context, const std::string& path) namespace LLInitParam { - ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) + ParamValue<LLUIColor>::ParamValue(const LLUIColor& color) : super_t(color), red("red"), green("green"), @@ -2118,7 +2118,7 @@ namespace LLInitParam updateBlockFromValue(false); } - void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock() + void ParamValue<LLUIColor>::updateValueFromBlock() { if (control.isProvided() && !control().empty()) { @@ -2130,7 +2130,7 @@ namespace LLInitParam } } - void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue(bool make_block_authoritative) + void ParamValue<LLUIColor>::updateBlockFromValue(bool make_block_authoritative) { LLColor4 color = getValue(); red.set(color.mV[VRED], make_block_authoritative); @@ -2146,7 +2146,7 @@ namespace LLInitParam && !(b->getFontDesc() < a->getFontDesc()); } - ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) + ParamValue<const LLFontGL*>::ParamValue(const LLFontGL* fontp) : super_t(fontp), name("name"), size("size"), @@ -2160,7 +2160,7 @@ namespace LLInitParam updateBlockFromValue(false); } - void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() + void ParamValue<const LLFontGL*>::updateValueFromBlock() { const LLFontGL* res_fontp = LLFontGL::getFontByName(name); if (res_fontp) @@ -2183,7 +2183,7 @@ namespace LLInitParam } } - void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue(bool make_block_authoritative) + void ParamValue<const LLFontGL*>::updateBlockFromValue(bool make_block_authoritative) { if (getValue()) { @@ -2193,7 +2193,7 @@ namespace LLInitParam } } - ParamValue<LLRect, TypeValues<LLRect> >::ParamValue(const LLRect& rect) + ParamValue<LLRect>::ParamValue(const LLRect& rect) : super_t(rect), left("left"), top("top"), @@ -2205,7 +2205,7 @@ namespace LLInitParam updateBlockFromValue(false); } - void ParamValue<LLRect, TypeValues<LLRect> >::updateValueFromBlock() + void ParamValue<LLRect>::updateValueFromBlock() { LLRect rect; @@ -2269,7 +2269,7 @@ namespace LLInitParam updateValue(rect); } - void ParamValue<LLRect, TypeValues<LLRect> >::updateBlockFromValue(bool make_block_authoritative) + void ParamValue<LLRect>::updateBlockFromValue(bool make_block_authoritative) { // because of the ambiguity in specifying a rect by position and/or dimensions // we use the lowest priority pairing so that any valid pairing in xui @@ -2286,7 +2286,7 @@ namespace LLInitParam height.set(value.getHeight(), make_block_authoritative); } - ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::ParamValue(const LLCoordGL& coord) + ParamValue<LLCoordGL>::ParamValue(const LLCoordGL& coord) : super_t(coord), x("x"), y("y") @@ -2294,12 +2294,12 @@ namespace LLInitParam updateBlockFromValue(false); } - void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateValueFromBlock() + void ParamValue<LLCoordGL>::updateValueFromBlock() { updateValue(LLCoordGL(x, y)); } - void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateBlockFromValue(bool make_block_authoritative) + void ParamValue<LLCoordGL>::updateBlockFromValue(bool make_block_authoritative) { x.set(getValue().mX, make_block_authoritative); y.set(getValue().mY, make_block_authoritative); diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 28e84fa444..618ed2fc42 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -512,7 +512,7 @@ public: namespace LLInitParam { template<> - class ParamValue<LLRect, TypeValues<LLRect> > + class ParamValue<LLRect> : public CustomParamValue<LLRect> { typedef CustomParamValue<LLRect> super_t; @@ -531,7 +531,7 @@ namespace LLInitParam }; template<> - class ParamValue<LLUIColor, TypeValues<LLUIColor> > + class ParamValue<LLUIColor> : public CustomParamValue<LLUIColor> { typedef CustomParamValue<LLUIColor> super_t; @@ -549,7 +549,7 @@ namespace LLInitParam }; template<> - class ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> > + class ParamValue<const LLFontGL*> : public CustomParamValue<const LLFontGL* > { typedef CustomParamValue<const LLFontGL*> super_t; @@ -589,7 +589,7 @@ namespace LLInitParam template<> - class ParamValue<LLCoordGL, TypeValues<LLCoordGL> > + class ParamValue<LLCoordGL> : public CustomParamValue<LLCoordGL> { typedef CustomParamValue<LLCoordGL> super_t; diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp index 1d9ce29ba9..6ae42c8852 100644 --- a/indra/llui/lluiimage.cpp +++ b/indra/llui/lluiimage.cpp @@ -155,7 +155,7 @@ void LLUIImage::onImageLoaded() namespace LLInitParam { - void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() + void ParamValue<LLUIImage*>::updateValueFromBlock() { // The keyword "none" is specifically requesting a null image // do not default to current value. Used to overwrite template images. @@ -172,7 +172,7 @@ namespace LLInitParam } } - void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue(bool make_block_authoritative) + void ParamValue<LLUIImage*>::updateBlockFromValue(bool make_block_authoritative) { if (getValue() == NULL) { diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h index b9b90fee71..b86ea67505 100644 --- a/indra/llui/lluiimage.h +++ b/indra/llui/lluiimage.h @@ -92,7 +92,7 @@ protected: namespace LLInitParam { template<> - class ParamValue<LLUIImage*, TypeValues<LLUIImage*>, NOT_BLOCK > + class ParamValue<LLUIImage*> : public CustomParamValue<LLUIImage*> { typedef boost::add_reference<boost::add_const<LLUIImage*>::type>::type T_const_ref; diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index 20bac5ff55..9cb6a89eee 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -127,14 +127,14 @@ namespace LLInitParam bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } bool BaseBlock::validateBlock(bool emit_errors) const { return true; } - ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) + ParamValue<LLUIColor>::ParamValue(const LLUIColor& color) : super_t(color) {} - void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock() + void ParamValue<LLUIColor>::updateValueFromBlock() {} - void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue(bool) + void ParamValue<LLUIColor>::updateBlockFromValue(bool) {} bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) @@ -142,14 +142,14 @@ namespace LLInitParam return false; } - ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) + ParamValue<const LLFontGL*>::ParamValue(const LLFontGL* fontp) : super_t(fontp) {} - void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() + void ParamValue<const LLFontGL*>::updateValueFromBlock() {} - void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue(bool) + void ParamValue<const LLFontGL*>::updateBlockFromValue(bool) {} void TypeValues<LLFontGL::HAlign>::declareValues() @@ -161,10 +161,10 @@ namespace LLInitParam void TypeValues<LLFontGL::ShadowType>::declareValues() {} - void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() + void ParamValue<LLUIImage*>::updateValueFromBlock() {} - void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue(bool) + void ParamValue<LLUIImage*>::updateBlockFromValue(bool) {} diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index 9119e7d1fe..36402f5b27 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -97,14 +97,14 @@ namespace LLInitParam bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } bool BaseBlock::validateBlock(bool emit_errors) const { return true; } - ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) + ParamValue<LLUIColor>::ParamValue(const LLUIColor& color) : super_t(color) {} - void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock() + void ParamValue<LLUIColor>::updateValueFromBlock() {} - void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue(bool) + void ParamValue<LLUIColor>::updateBlockFromValue(bool) {} bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) @@ -113,14 +113,14 @@ namespace LLInitParam } - ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) + ParamValue<const LLFontGL*>::ParamValue(const LLFontGL* fontp) : super_t(fontp) {} - void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() + void ParamValue<const LLFontGL*>::updateValueFromBlock() {} - void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue(bool) + void ParamValue<const LLFontGL*>::updateBlockFromValue(bool) {} void TypeValues<LLFontGL::HAlign>::declareValues() @@ -132,10 +132,10 @@ namespace LLInitParam void TypeValues<LLFontGL::ShadowType>::declareValues() {} - void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() + void ParamValue<LLUIImage*>::updateValueFromBlock() {} - void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue(bool) + void ParamValue<LLUIImage*>::updateBlockFromValue(bool) {} bool ParamCompare<LLUIImage*, false>::equals( diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 09617209a8..7e2dd3989a 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -77,24 +77,118 @@ namespace LLInitParam // helper functions and classes typedef ptrdiff_t param_handle_t; + struct IS_A_BLOCK {}; + struct NOT_BLOCK {}; + + // these templates allow us to distinguish between template parameters + // that derive from BaseBlock and those that don't + template<typename T, typename BLOCK_IDENTIFIER = void> + struct IsBlock + { + typedef NOT_BLOCK value_t; + }; + + template<typename T> + struct IsBlock<T, typename T::baseblock_base_class_t> + { + typedef IS_A_BLOCK value_t; + }; + + + template<typename T, typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t> + class ParamValue + { + typedef ParamValue<T, VALUE_IS_BLOCK> self_t; + + public: + typedef T default_value_t; + typedef T value_t; + + ParamValue(): mValue() {} + ParamValue(const default_value_t& other) : mValue(other) {} + + void setValue(const value_t& val) + { + mValue = val; + } + + const value_t& getValue() const + { + return mValue; + } + + T& getValue() + { + return mValue; + } + + protected: + T mValue; + }; + + template<typename T> + class ParamValue<T, IS_A_BLOCK> + : public T + { + typedef ParamValue<T, IS_A_BLOCK> self_t; + public: + typedef T default_value_t; + typedef T value_t; + + ParamValue() + : T(), + mValidated(false) + {} + + ParamValue(const default_value_t& other) + : T(other), + mValidated(false) + {} + + void setValue(const value_t& val) + { + *this = val; + } + + const value_t& getValue() const + { + return *this; + } + + T& getValue() + { + return *this; + } + + protected: + mutable bool mValidated; // lazy validation flag + }; + // empty default implementation of key cache // leverages empty base class optimization template <typename T> class TypeValues + : public ParamValue<T> { private: struct Inaccessable{}; + typedef typename ParamValue<T>::value_t value_t; public: typedef std::map<std::string, T> value_name_map_t; typedef Inaccessable name_t; + typedef TypeValues<T> type_value_t; + + TypeValues(const value_t& val) + : ParamValue(val) + {} void setValueName(const std::string& key) {} std::string getValueName() const { return ""; } - std::string calcValueName(const T& value) const { return ""; } + std::string calcValueName(const value_t& value) const { return ""; } void clearValueName() const {} - static bool getValueFromName(const std::string& name, T& value) + static bool getValueFromName(const std::string& name, value_t& value) { return false; } @@ -109,15 +203,36 @@ namespace LLInitParam return NULL; } + void assignNamedValue(const Inaccessable& name) + {} + + operator const value_t&() const + { + return getValue(); + } + + const value_t& operator()() const + { + return getValue(); + } + static value_name_map_t* getValueNames() {return NULL;} }; - template <typename T, typename DERIVED_TYPE = TypeValues<T> > + template <typename T, typename DERIVED_TYPE = TypeValues<T>, bool IS_SPECIALIZED = true > class TypeValuesHelper + : public ParamValue<T> { + typedef TypeValuesHelper<T, DERIVED_TYPE, IS_SPECIALIZED> self_t; + typedef typename ParamValue<T>::value_t value_t; public: typedef typename std::map<std::string, T> value_name_map_t; typedef std::string name_t; + typedef self_t type_value_t; + + TypeValuesHelper(const value_t& val) + : ParamValue(val) + {} //TODO: cache key by index to save on param block size void setValueName(const std::string& value_name) @@ -130,7 +245,7 @@ namespace LLInitParam return mValueName; } - std::string calcValueName(const T& value) const + std::string calcValueName(const value_t& value) const { value_name_map_t* map = getValueNames(); for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end(); @@ -151,7 +266,7 @@ namespace LLInitParam mValueName.clear(); } - static bool getValueFromName(const std::string& name, T& value) + static bool getValueFromName(const std::string& name, value_t& value) { value_name_map_t* map = getValueNames(); typename value_name_map_t::iterator found_it = map->find(name); @@ -193,18 +308,80 @@ namespace LLInitParam return &sValues; } - static void declare(const std::string& name, const T& value) + static void declare(const std::string& name, const value_t& value) { (*getValueNames())[name] = value; } + void operator ()(const std::string& name) + { + *this = name; + } + + void assignNamedValue(const std::string& name) + { + if (getValueFromName(name, getValue())) + { + setValueName(name); + } + } + + operator const value_t&() const + { + return getValue(); + } + + const value_t& operator()() const + { + return getValue(); + } + protected: - static void getName(const std::string& name, const T& value) + static void getName(const std::string& name, const value_t& value) {} mutable std::string mValueName; }; + template <typename DERIVED_TYPE> + class TypeValuesHelper<std::string, DERIVED_TYPE, true> + : public TypeValuesHelper<std::string, DERIVED_TYPE, false> + { + public: + TypeValuesHelper(const std::string& val) + : TypeValuesHelper(val) + {} + + void operator ()(const std::string& name) + { + *this = name; + } + + self_t& operator =(const std::string& name) + { + if (getValueFromName(name, getValue())) + { + setValueName(name); + } + else + { + setValue(name); + } + return *this; + } + + operator const value_t&() const + { + return getValue(); + } + + const value_t& operator()() const + { + return getValue(); + } + + }; + class Parser { LOG_CLASS(Parser); @@ -370,23 +547,6 @@ namespace LLInitParam class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed }; - struct IS_BLOCK {}; - struct NOT_BLOCK {}; - - // these templates allow us to distinguish between template parameters - // that derive from BaseBlock and those that don't - template<typename T, typename BLOCK_IDENTIFIER = void> - struct IsBlock - { - typedef NOT_BLOCK value_t; - }; - - template<typename T> - struct IsBlock<T, typename T::baseblock_base_class_t> - { - typedef IS_BLOCK value_t; - }; - //TODO: implement in terms of owned_ptr template<typename T> class LazyValue @@ -483,8 +643,8 @@ namespace LLInitParam { public: // lift block tags into baseblock namespace so derived classes do not need to qualify them - typedef LLInitParam::IS_BLOCK IS_BLOCK; - typedef LLInitParam::NOT_BLOCK NOT_BLOCK; + typedef LLInitParam::IS_A_BLOCK IS_A_BLOCK; + typedef LLInitParam::NOT_BLOCK NOT_A_BLOCK; template<typename T> class Atomic @@ -640,182 +800,12 @@ namespace LLInitParam U32 mIsProvided:1; }; - - - template<typename T, typename NAME_VALUE_LOOKUP, typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t> - class ParamValue : public NAME_VALUE_LOOKUP - { - typedef ParamValue<T, NAME_VALUE_LOOKUP, VALUE_IS_BLOCK> self_t; - - public: - typedef T default_value_t; - typedef T value_t; - - ParamValue(): mValue() {} - ParamValue(const default_value_t& other) : mValue(other) {} - - void setValue(const value_t& val) - { - mValue = val; - } - - const value_t& getValue() const - { - return mValue; - } - - T& getValue() - { - return mValue; - } - - operator const value_t&() const - { - return mValue; - } - - const value_t& operator()() const - { - return mValue; - } - - void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) - { - *this = name; - } - - self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) - { - if (NAME_VALUE_LOOKUP::getValueFromName(name, mValue)) - { - setValueName(name); - } - - return *this; - } - - protected: - T mValue; - }; - - template<typename T, typename NAME_VALUE_LOOKUP> - class ParamValue<T, NAME_VALUE_LOOKUP, IS_BLOCK> - : public T, - public NAME_VALUE_LOOKUP - { - typedef ParamValue<T, NAME_VALUE_LOOKUP, IS_BLOCK> self_t; - public: - typedef T default_value_t; - typedef T value_t; - - ParamValue() - : T(), - mValidated(false) - {} - - ParamValue(const default_value_t& other) - : T(other), - mValidated(false) - {} - - void setValue(const value_t& val) - { - *this = val; - } - - const value_t& getValue() const - { - return *this; - } - - T& getValue() - { - return *this; - } - - operator const value_t&() const - { - return *this; - } - - const value_t& operator()() const - { - return *this; - } - - void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) - { - *this = name; - } - - self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) - { - if (NAME_VALUE_LOOKUP::getValueFromName(name, *this)) - { - setValueName(name); - } - - return *this; - } - - protected: - mutable bool mValidated; // lazy validation flag - }; - - template<typename NAME_VALUE_LOOKUP> - class ParamValue<std::string, NAME_VALUE_LOOKUP, NOT_BLOCK> - : public NAME_VALUE_LOOKUP - { - typedef ParamValue<std::string, NAME_VALUE_LOOKUP, NOT_BLOCK> self_t; - public: - typedef std::string default_value_t; - typedef std::string value_t; - - ParamValue(): mValue() {} - ParamValue(const default_value_t& other) : mValue(other) {} - - void setValue(const value_t& val) - { - if (NAME_VALUE_LOOKUP::getValueFromName(val, mValue)) - { - NAME_VALUE_LOOKUP::setValueName(val); - } - else - { - mValue = val; - } - } - - const value_t& getValue() const - { - return mValue; - } - - std::string& getValue() - { - return mValue; - } - - operator const value_t&() const - { - return mValue; - } - - const value_t& operator()() const - { - return mValue; - } - - protected: - std::string mValue; - }; - - + template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > struct ParamIterator { - typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::const_iterator const_iterator; - typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::iterator iterator; + typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::const_iterator const_iterator; + typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::iterator iterator; }; // specialize for custom parsing/decomposition of specific classes @@ -823,22 +813,23 @@ namespace LLInitParam template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>, bool HAS_MULTIPLE_VALUES = false, - typename VALUE_IS_BLOCK = typename IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value_t> + typename VALUE_IS_BLOCK = typename IsBlock<ParamValue<T> >::value_t> class TypedParam : public Param, - public ParamValue<T, NAME_VALUE_LOOKUP> + public NAME_VALUE_LOOKUP::type_value_t { protected: typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t; - typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; + typedef ParamValue<T> param_value_t; typedef typename param_value_t::value_t value_t; typedef typename param_value_t::default_value_t default_value_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; public: - using param_value_t::operator(); + using named_value_t::operator(); TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr), - param_value_t(value) + named_value_t(value) { if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { @@ -862,7 +853,7 @@ namespace LLInitParam } // try to parse a known named value - if(param_value_t::valueNamesExist()) + if(named_value_t::valueNamesExist()) { // try to parse a known named value std::string name; @@ -870,7 +861,7 @@ namespace LLInitParam { // try to parse a per type named value - if (param_value_t::getValueFromName(name, typed_param.getValue())) + if (named_value_t::getValueFromName(name, typed_param.getValue())) { typed_param.setValueName(name); typed_param.setProvided(); @@ -923,22 +914,23 @@ namespace LLInitParam // tell parser about our actual type parser.inspectValue<T>(name_stack, min_count, max_count, NULL); // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) - if (param_value_t::getPossibleValues()) + if (named_value_t::getPossibleValues()) { - parser.inspectValue<std::string>(name_stack, min_count, max_count, param_value_t::getPossibleValues()); + parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); } } void set(const value_t& val, bool flag_as_provided = true) { - param_value_t::clearValueName(); + named_value_t::clearValueName(); setValue(val); setProvided(flag_as_provided); } - self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) + self_t& operator =(const typename named_value_t::name_t& name) { - return static_cast<self_t&>(param_value_t::operator =(name)); + named_value_t::assignNamedValue(name); + return *this; } protected: @@ -980,21 +972,22 @@ namespace LLInitParam // parameter that is a block template <typename T, typename NAME_VALUE_LOOKUP> - class TypedParam<T, NAME_VALUE_LOOKUP, false, IS_BLOCK> + class TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> : public Param, - public ParamValue<T, NAME_VALUE_LOOKUP> + public NAME_VALUE_LOOKUP::type_value_t { protected: - typedef ParamValue<T, NAME_VALUE_LOOKUP> param_value_t; + typedef ParamValue<T> param_value_t; typedef typename param_value_t::value_t value_t; typedef typename param_value_t::default_value_t default_value_t; - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_BLOCK> self_t; + typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> self_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; public: - using param_value_t::operator(); + using named_value_t::operator(); TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr), - param_value_t(value) + named_value_t(value) { if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { @@ -1013,14 +1006,14 @@ namespace LLInitParam return true; } - if(param_value_t::valueNamesExist()) + if(named_value_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (param_value_t::getValueFromName(name, typed_param.getValue())) + if (named_value_t::getValueFromName(name, typed_param.getValue())) { typed_param.setValueName(name); typed_param.setProvided(); @@ -1045,9 +1038,9 @@ namespace LLInitParam std::string key = typed_param.getValueName(); if (!key.empty()) { - if (!parser.writeValue(key, name_stack)) + if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key)) { - return; + parser.writeValue(key, name_stack); } } else @@ -1058,8 +1051,16 @@ namespace LLInitParam static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) { - // I am a param that is also a block, so just recurse into my contents const self_t& typed_param = static_cast<const self_t&>(param); + + // tell parser about our actual type + parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL); + // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) + if (named_value_t::getPossibleValues()) + { + parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); + } + typed_param.inspectBlock(parser, name_stack, min_count, max_count); } @@ -1080,29 +1081,31 @@ namespace LLInitParam void set(const value_t& val, bool flag_as_provided = true) { setValue(val); - param_value_t::clearValueName(); + named_value_t::clearValueName(); // force revalidation of block // next call to isProvided() will update provision status based on validity param_value_t::mValidated = false; setProvided(flag_as_provided); } - self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) + self_t& operator =(const typename named_value_t::name_t& name) { - return static_cast<self_t&>(param_value_t::operator =(name)); + named_value_t::assignNamedValue(name); + return *this; } // propagate changed status up to enclosing block /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided) { param_value_t::paramChanged(changed_param, user_provided); + named_value_t::clearValueName(); + if (user_provided) { // a child param has been explicitly changed // so *some* aspect of this block is now provided param_value_t::mValidated = false; setProvided(); - param_value_t::clearValueName(); } else { @@ -1157,11 +1160,12 @@ namespace LLInitParam : public Param { protected: - typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t; - typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP, typename IsBlock<VALUE_TYPE>::value_t> param_value_t; - typedef typename std::vector<param_value_t> container_t; - typedef container_t default_value_t; - typedef typename param_value_t::value_t value_t; + typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t; + typedef ParamValue<VALUE_TYPE> param_value_t; + typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t; + typedef container_t default_value_t; + typedef typename param_value_t::value_t value_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; public: TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) @@ -1193,14 +1197,14 @@ namespace LLInitParam } // try to parse a known named value - if(param_value_t::valueNamesExist()) + if(named_value_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (param_value_t::getValueFromName(name, value)) + if (named_value_t::getValueFromName(name, value)) { typed_param.add(value); typed_param.mValues.back().setValueName(name); @@ -1251,9 +1255,9 @@ namespace LLInitParam static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) { parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL); - if (param_value_t::getPossibleValues()) + if (named_value_t::getPossibleValues()) { - parser.inspectValue<std::string>(name_stack, min_count, max_count, param_value_t::getPossibleValues()); + parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); } } @@ -1265,25 +1269,23 @@ namespace LLInitParam param_value_t& add() { - mValues.push_back(param_value_t(value_t())); + mValues.push_back(value_t()); Param::setProvided(); return mValues.back(); } void add(const value_t& item) { - param_value_t param_value; - param_value.setValue(item); - mValues.push_back(param_value); + mValues.push_back(item); setProvided(); } - void add(const typename param_value_t::name_t& name) + void add(const typename named_value_t::name_t& name) { value_t value; // try to parse a per type named value - if (param_value_t::getValueFromName(name, value)) + if (named_value_t::getValueFromName(name, value)) { add(value); mValues.back().setValueName(name); @@ -1352,17 +1354,18 @@ namespace LLInitParam // container of block parameters template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> - class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_BLOCK> + class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> : public Param { protected: - typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_BLOCK> self_t; - typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP, typename IsBlock<VALUE_TYPE>::value_t> param_value_t; - typedef typename std::vector<param_value_t> container_t; - typedef typename param_value_t::value_t value_t; - typedef container_t default_value_t; - typedef typename container_t::iterator iterator; - typedef typename container_t::const_iterator const_iterator; + typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> self_t; + typedef ParamValue<VALUE_TYPE> param_value_t; + typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; + typedef typename param_value_t::value_t value_t; + typedef container_t default_value_t; + typedef typename container_t::iterator iterator; + typedef typename container_t::const_iterator const_iterator; public: TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) @@ -1396,14 +1399,14 @@ namespace LLInitParam typed_param.setProvided(); return true; } - else if(param_value_t::valueNamesExist()) + else if(named_value_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (param_value_t::getValueFromName(name, value.getValue())) + if (named_value_t::getValueFromName(name, value.getValue())) { typed_param.mValues.back().setValueName(name); typed_param.setProvided(); @@ -1448,8 +1451,17 @@ namespace LLInitParam static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) { - // I am a vector of blocks, so describe my contents recursively - param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count); + const param_value_t& value_param = param_value_t(value_t()); + + // tell parser about our actual type + parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL); + // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) + if (named_value_t::getPossibleValues()) + { + parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); + } + + value_param.inspectBlock(parser, name_stack, min_count, max_count); } void set(const container_t& val, bool flag_as_provided = true) @@ -1471,12 +1483,12 @@ namespace LLInitParam setProvided(); } - void add(const typename param_value_t::name_t& name) + void add(const typename named_value_t::name_t& name) { value_t value; // try to parse a per type named value - if (param_value_t::getValueFromName(name, value)) + if (named_value_t::getValueFromName(name, value)) { add(value); mValues.back().setValueName(name); @@ -1620,7 +1632,7 @@ namespace LLInitParam // Alternatives are mutually exclusive wrt other Alternatives in the same block. // One alternative in a block will always have isChosen() == true. // At most one alternative in a block will have isProvided() == true. - template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > + template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>::type_value_t > class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false> { typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; @@ -1662,7 +1674,7 @@ namespace LLInitParam super_t::set(val); } - void operator()(typename const value_t& val) + void operator()(const value_t& val) { super_t::set(val); } @@ -1743,7 +1755,7 @@ namespace LLInitParam // // Nested classes for declaring parameters // - template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > + template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>::type_value_t > class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false> { typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; @@ -1773,7 +1785,7 @@ namespace LLInitParam } }; - template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > + template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>::type_value_t > class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false> { typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; @@ -1796,7 +1808,7 @@ namespace LLInitParam return *this; } - DERIVED_BLOCK& operator()(typename const value_t& val) + DERIVED_BLOCK& operator()(const value_t& val) { super_t::set(val); return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1810,14 +1822,13 @@ namespace LLInitParam }; - template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> > + template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T>::type_value_t > class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true> { typedef TypedParam<T, NAME_VALUE_LOOKUP, true> super_t; typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t; typedef typename super_t::container_t container_t; typedef typename super_t::value_t value_t; - typedef TypedParam<T, NAME_VALUE_LOOKUP, true> super_t; public: typedef typename super_t::iterator iterator; @@ -1833,7 +1844,7 @@ namespace LLInitParam return *this; } - DERIVED_BLOCK& operator()(typename const container_t& val) + DERIVED_BLOCK& operator()(const container_t& val) { super_t::set(val); return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1904,30 +1915,27 @@ namespace LLInitParam }; template<typename T, typename BLOCK_T> - struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::IS_BLOCK>, TypeValues<BaseBlock::Lazy<T, BaseBlock::IS_BLOCK> >, BLOCK_T >, void> + struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::IS_A_BLOCK>, BLOCK_T >, void> { - typedef IS_BLOCK value_t; + typedef IS_A_BLOCK value_t; }; template<typename T, typename BLOCK_T> - struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::NOT_BLOCK>, TypeValues<BaseBlock::Lazy<T, BaseBlock::NOT_BLOCK> >, BLOCK_T >, void> + struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::NOT_A_BLOCK>, BLOCK_T >, void> { typedef NOT_BLOCK value_t; }; template<typename T, typename BLOCK_IDENTIFIER> - struct IsBlock<ParamValue<BaseBlock::Atomic<T>, TypeValues<BaseBlock::Atomic<T> >, typename IsBlock<BaseBlock::Atomic<T> >::value_t >, BLOCK_IDENTIFIER> + struct IsBlock<ParamValue<BaseBlock::Atomic<T>, typename IsBlock<BaseBlock::Atomic<T> >::value_t >, BLOCK_IDENTIFIER> { - typedef typename IsBlock<ParamValue<T, TypeValues<T> > >::value_t value_t; + typedef typename IsBlock<ParamValue<T> >::value_t value_t; }; template<typename T, typename BLOCK_T> - class ParamValue <BaseBlock::Atomic<T>, - TypeValues<BaseBlock::Atomic<T> >, - BLOCK_T> - : public TypeValues<T> + class ParamValue <BaseBlock::Atomic<T>, BLOCK_T> { - typedef ParamValue <BaseBlock::Atomic<T>, TypeValues<BaseBlock::Atomic<T> >, BLOCK_T> self_t; + typedef ParamValue <BaseBlock::Atomic<T>, BLOCK_T> self_t; public: typedef T value_t; @@ -1945,12 +1953,12 @@ namespace LLInitParam void setValue(const value_t& val) { - mValue.setValue(val); + mValue = val; } const T& getValue() const { - return mValue.getValue(); + return mValue; } T& getValue() @@ -1968,18 +1976,6 @@ namespace LLInitParam return mValue; } - void operator ()(const typename TypeValues<T>::name_t& name) - { - *this = name; - } - - self_t& operator =(const typename TypeValues<T>::name_t& name) - { - mValue = name; - - return *this; - } - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) { if (new_name) @@ -2036,12 +2032,9 @@ namespace LLInitParam }; template<typename T, typename BLOCK_T> - class ParamValue <BaseBlock::Lazy<T, IS_BLOCK>, - TypeValues<BaseBlock::Lazy<T, IS_BLOCK> >, - BLOCK_T> - : public TypeValues<T> + class ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T> { - typedef ParamValue <BaseBlock::Lazy<T, IS_BLOCK>, TypeValues<BaseBlock::Lazy<T, IS_BLOCK> >, BLOCK_T> self_t; + typedef ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T> self_t; public: typedef T value_t; @@ -2087,21 +2080,6 @@ namespace LLInitParam return mValue.get(); } - void operator ()(const typename TypeValues<T>::name_t& name) - { - *this = name; - } - - self_t& operator =(const typename TypeValues<T>::name_t& name) - { - if (TypeValues<T>::getValueFromName(name, mValue.get())) - { - setValueName(name); - } - - return *this; - } - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) { return mValue.get().deserializeBlock(p, name_stack_range, new_name); @@ -2145,12 +2123,9 @@ namespace LLInitParam }; template<typename T, typename BLOCK_T> - class ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, - TypeValues<BaseBlock::Lazy<T, NOT_BLOCK> >, - BLOCK_T> - : public TypeValues<T> + class ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> { - typedef ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, TypeValues<BaseBlock::Lazy<T, NOT_BLOCK> >, BLOCK_T> self_t; + typedef ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> self_t; public: typedef T value_t; @@ -2196,21 +2171,6 @@ namespace LLInitParam return mValue.get(); } - void operator ()(const typename TypeValues<T>::name_t& name) - { - *this = name; - } - - self_t& operator =(const typename TypeValues<T>::name_t& name) - { - if (TypeValues<T>::getValueFromName(name, mValue.get())) - { - setValueName(name); - } - - return *this; - } - mutable bool mValidated; // lazy validation flag private: @@ -2218,11 +2178,8 @@ namespace LLInitParam }; template <> - class ParamValue <LLSD, - TypeValues<LLSD>, - NOT_BLOCK> - : public TypeValues<LLSD>, - public BaseBlock + class ParamValue <LLSD, NOT_BLOCK> + : public BaseBlock { public: typedef LLSD value_t; @@ -2265,8 +2222,7 @@ namespace LLInitParam template<typename T> class CustomParamValue - : public Block<ParamValue<T, TypeValues<T> > >, - public TypeValues<T> + : public Block<ParamValue<T> > { public: typedef enum e_value_age @@ -2276,12 +2232,12 @@ namespace LLInitParam BLOCK_AUTHORITATIVE // mValue is derived from the block parameters, which are authoritative } EValueAge; - typedef ParamValue<T, TypeValues<T> > derived_t; - typedef CustomParamValue<T> self_t; - typedef Block<derived_t> block_t; - typedef T default_value_t; - typedef T value_t; - typedef void baseblock_base_class_t; + typedef ParamValue<T> derived_t; + typedef CustomParamValue<T> self_t; + typedef Block<derived_t> block_t; + typedef T default_value_t; + typedef T value_t; + typedef void baseblock_base_class_t; CustomParamValue(const default_value_t& value = T()) @@ -2301,8 +2257,6 @@ namespace LLInitParam typed_param.mValueAge = VALUE_AUTHORITATIVE; typed_param.updateBlockFromValue(false); - typed_param.clearValueName(); - return true; } } @@ -2316,18 +2270,8 @@ namespace LLInitParam const derived_t& typed_param = static_cast<const derived_t&>(*this); const derived_t* diff_param = static_cast<const derived_t*>(diff_block); - std::string key = typed_param.getValueName(); - - // first try to write out name of name/value pair - if (!key.empty()) - { - if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key)) - { - parser.writeValue(key, name_stack); - } - } // then try to serialize value directly - else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue())) + if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue())) { if (!parser.writeValue(typed_param.getValue(), name_stack)) @@ -2357,19 +2301,6 @@ namespace LLInitParam } } - bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const - { - // first, inspect with actual type... - parser.inspectValue<T>(name_stack, min_count, max_count, NULL); - if (TypeValues<T>::getPossibleValues()) - { - //...then inspect with possible string values... - parser.inspectValue<std::string>(name_stack, min_count, max_count, TypeValues<T>::getPossibleValues()); - } - // then recursively inspect contents... - return block_t::inspectBlock(parser, name_stack, min_count, max_count); - } - bool validateBlock(bool emit_errors = true) const { if (mValueAge == VALUE_NEEDS_UPDATE) @@ -2377,7 +2308,6 @@ namespace LLInitParam if (block_t::validateBlock(emit_errors)) { // clear stale keyword associated with old value - TypeValues<T>::clearValueName(); mValueAge = BLOCK_AUTHORITATIVE; static_cast<derived_t*>(const_cast<self_t*>(this))->updateValueFromBlock(); return true; @@ -2409,11 +2339,9 @@ namespace LLInitParam void setValue(const value_t& val) { - derived_t& typed_param = static_cast<derived_t&>(*this); // set param version number to be up to date, so we ignore block contents mValueAge = VALUE_AUTHORITATIVE; mValue = val; - typed_param.clearValueName(); static_cast<derived_t*>(this)->updateBlockFromValue(false); } @@ -2429,30 +2357,6 @@ namespace LLInitParam return mValue; } - operator const value_t&() const - { - return getValue(); - } - - const value_t& operator()() const - { - return getValue(); - } - - void operator ()(const typename TypeValues<T>::name_t& name) - { - *this = name; - } - - self_t& operator =(const typename TypeValues<T>::name_t& name) - { - if (TypeValues<T>::getValueFromName(name, mValue)) - { - setValueName(name); - } - - return *this; - } protected: // use this from within updateValueFromBlock() to set the value without making it authoritative diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index 2e1f8888d0..58ed24b08b 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -130,7 +130,7 @@ struct Any : public LLInitParam::Block<Any, Occurs> struct All : public LLInitParam::Block<All, Occurs> { - Multiple< Lazy<Element, IS_BLOCK> > elements; + Multiple< Lazy<Element, IS_A_BLOCK> > elements; All() : elements("element") @@ -141,11 +141,11 @@ struct All : public LLInitParam::Block<All, Occurs> struct Choice : public LLInitParam::ChoiceBlock<Choice, Occurs> { - Alternative< Lazy<Element, IS_BLOCK> > element; - Alternative< Lazy<Group, IS_BLOCK> > group; - Alternative< Lazy<Choice, IS_BLOCK> > choice; - Alternative< Lazy<Sequence, IS_BLOCK> > sequence; - Alternative< Lazy<Any, IS_BLOCK> > any; + Alternative< Lazy<Element, IS_A_BLOCK> > element; + Alternative< Lazy<Group, IS_A_BLOCK> > group; + Alternative< Lazy<Choice, IS_A_BLOCK> > choice; + Alternative< Lazy<Sequence, IS_A_BLOCK> > sequence; + Alternative< Lazy<Any, IS_A_BLOCK> > any; Choice() : element("element"), @@ -159,11 +159,11 @@ struct Choice : public LLInitParam::ChoiceBlock<Choice, Occurs> struct Sequence : public LLInitParam::ChoiceBlock<Sequence, Occurs> { - Alternative< Lazy<Element, IS_BLOCK> > element; - Alternative< Lazy<Group, IS_BLOCK> > group; - Alternative< Lazy<Choice, IS_BLOCK> > choice; - Alternative< Lazy<Sequence, IS_BLOCK> > sequence; - Alternative< Lazy<Any, IS_BLOCK> > any; + Alternative< Lazy<Element, IS_A_BLOCK> > element; + Alternative< Lazy<Group, IS_A_BLOCK> > group; + Alternative< Lazy<Choice, IS_A_BLOCK> > choice; + Alternative< Lazy<Sequence, IS_A_BLOCK> > sequence; + Alternative< Lazy<Any, IS_A_BLOCK> > any; }; struct GroupContents : public LLInitParam::ChoiceBlock<GroupContents, Occurs> @@ -248,7 +248,7 @@ struct ComplexType : public LLInitParam::Block<ComplexType, ComplexTypeContents> Optional<bool> mixed; Multiple<Attribute> attribute; - Multiple< Lazy<Element, IS_BLOCK > > elements; + Multiple< Lazy<Element, IS_A_BLOCK > > elements; ComplexType() : name("name"), diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index c483aa58c9..b420812a3c 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -248,7 +248,7 @@ struct LLVOAvatarCollisionVolumeInfo : public LLInitParam::Block<LLVOAvatarColli struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock<LLVOAvatarChildJoint> { - Alternative<Lazy<struct LLVOAvatarBoneInfo, IS_BLOCK> > bone; + Alternative<Lazy<struct LLVOAvatarBoneInfo, IS_A_BLOCK> > bone; Alternative<LLVOAvatarCollisionVolumeInfo> collision_volume; LLVOAvatarChildJoint() -- cgit v1.2.3 From 7dc9ddff4b775bf78561ef545db281cf47f2240f Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Sun, 15 Apr 2012 20:43:55 -0700 Subject: attempted fix for gcc --- indra/llui/llsdparam.cpp | 6 ++--- indra/llxuixml/llinitparam.h | 55 +++++++++++++++++++++++++++++++------------- 2 files changed, 42 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index 828f809452..bcfb38aa11 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -313,7 +313,7 @@ namespace LLInitParam { // LLSD specialization // block param interface - bool ParamValue<LLSD, TypeValues<LLSD>, NOT_BLOCK>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) + bool ParamValue<LLSD, NOT_BLOCK>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) { LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack); @@ -328,12 +328,12 @@ namespace LLInitParam } //static - void ParamValue<LLSD, TypeValues<LLSD>, NOT_BLOCK>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) + void ParamValue<LLSD, NOT_BLOCK>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) { p.writeValue<LLSD::String>(sd.asString(), name_stack); } - void ParamValue<LLSD, TypeValues<LLSD>, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const + void ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const { // read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) Parser::name_stack_t stack; diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 7e2dd3989a..d4d19d1c13 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -43,6 +43,8 @@ namespace LLInitParam template<typename T> const T& defaultValue() { static T value; return value; } + // wraps comparison operator between any 2 values of the same type + // specialize to handle cases where equality isn't defined well, or at all template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value > struct ParamCompare { @@ -94,7 +96,11 @@ namespace LLInitParam typedef IS_A_BLOCK value_t; }; - + // ParamValue class directly manages the wrapped value + // by holding on to a copy (scalar params) + // or deriving from it (blocks) + // has specializations for custom value behavior + // and "tagged" values like Lazy and Atomic template<typename T, typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t> class ParamValue { @@ -180,7 +186,7 @@ namespace LLInitParam typedef TypeValues<T> type_value_t; TypeValues(const value_t& val) - : ParamValue(val) + : ParamValue<T>(val) {} void setValueName(const std::string& key) {} @@ -208,17 +214,19 @@ namespace LLInitParam operator const value_t&() const { - return getValue(); + return ParamValue<T>::getValue(); } const value_t& operator()() const { - return getValue(); + return ParamValue<T>::getValue(); } static value_name_map_t* getValueNames() {return NULL;} }; + // helper class to implement name value lookups + // and caching of last used name template <typename T, typename DERIVED_TYPE = TypeValues<T>, bool IS_SPECIALIZED = true > class TypeValuesHelper : public ParamValue<T> @@ -231,7 +239,7 @@ namespace LLInitParam typedef self_t type_value_t; TypeValuesHelper(const value_t& val) - : ParamValue(val) + : ParamValue<T>(val) {} //TODO: cache key by index to save on param block size @@ -320,7 +328,7 @@ namespace LLInitParam void assignNamedValue(const std::string& name) { - if (getValueFromName(name, getValue())) + if (getValueFromName(name, ParamValue<T>::getValue())) { setValueName(name); } @@ -328,12 +336,12 @@ namespace LLInitParam operator const value_t&() const { - return getValue(); + return ParamValue<T>::getValue(); } const value_t& operator()() const { - return getValue(); + return ParamValue<T>::getValue(); } protected: @@ -343,11 +351,19 @@ namespace LLInitParam mutable std::string mValueName; }; + // string types can support custom named values, but need + // to disambiguate in code between a string that is a named value + // and a string that is a name template <typename DERIVED_TYPE> class TypeValuesHelper<std::string, DERIVED_TYPE, true> : public TypeValuesHelper<std::string, DERIVED_TYPE, false> { public: + typedef TypeValuesHelper<std::string, DERIVED_TYPE, true> self_t; + typedef std::string value_t; + typedef std::string name_t; + typedef self_t type_value_t; + TypeValuesHelper(const std::string& val) : TypeValuesHelper(val) {} @@ -359,7 +375,7 @@ namespace LLInitParam self_t& operator =(const std::string& name) { - if (getValueFromName(name, getValue())) + if (getValueFromName(name, ParamValue<T>::getValue())) { setValueName(name); } @@ -372,16 +388,17 @@ namespace LLInitParam operator const value_t&() const { - return getValue(); + return ParamValue<T>::getValue(); } const value_t& operator()() const { - return getValue(); + return ParamValue<T>::getValue(); } }; + // parser base class with mechanisms for registering readers/writers/inspectors of different types class Parser { LOG_CLASS(Parser); @@ -639,6 +656,8 @@ namespace LLInitParam mutable T* mPtr; }; + // root class of all parameter blocks + class BaseBlock { public: @@ -808,8 +827,12 @@ namespace LLInitParam typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::iterator iterator; }; - // specialize for custom parsing/decomposition of specific classes - // e.g. TypedParam<LLRect> has left, top, right, bottom, etc... + // wrapper for parameter with a known type + // specialized to handle 4 cases: + // simple "scalar" value + // parameter that is itself a block + // multiple scalar values, stored in a vector + // multiple blocks, stored in a vector template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>, bool HAS_MULTIPLE_VALUES = false, @@ -1098,7 +1121,6 @@ namespace LLInitParam /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided) { param_value_t::paramChanged(changed_param, user_provided); - named_value_t::clearValueName(); if (user_provided) { @@ -1106,6 +1128,7 @@ namespace LLInitParam // so *some* aspect of this block is now provided param_value_t::mValidated = false; setProvided(); + named_value_t::clearValueName(); } else { @@ -1472,7 +1495,7 @@ namespace LLInitParam param_value_t& add() { - mValues.push_back(value_t()); + mValues.push_back(value_t()) setProvided(); return mValues.back(); } @@ -1632,7 +1655,7 @@ namespace LLInitParam // Alternatives are mutually exclusive wrt other Alternatives in the same block. // One alternative in a block will always have isChosen() == true. // At most one alternative in a block will have isProvided() == true. - template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>::type_value_t > + template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t > class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false> { typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; -- cgit v1.2.3 From 3547815a8541a6fcb67f652e095c8d4692ef359d Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Sun, 15 Apr 2012 20:46:55 -0700 Subject: fixed minor typo --- indra/llxuixml/llinitparam.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index d4d19d1c13..fdcdf81294 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -1495,7 +1495,7 @@ namespace LLInitParam param_value_t& add() { - mValues.push_back(value_t()) + mValues.push_back(value_t()); setProvided(); return mValues.back(); } -- cgit v1.2.3 From 1cbe0f68c59554e197158c9000dca617cb028056 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Sun, 15 Apr 2012 23:49:26 -0700 Subject: another round of gcc fixes --- indra/llxuixml/llinitparam.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index fdcdf81294..9135b200ab 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -360,6 +360,7 @@ namespace LLInitParam { public: typedef TypeValuesHelper<std::string, DERIVED_TYPE, true> self_t; + typedef TypeValuesHelper<std::string, DERIVED_TYPE, false> base_t; typedef std::string value_t; typedef std::string name_t; typedef self_t type_value_t; @@ -375,25 +376,25 @@ namespace LLInitParam self_t& operator =(const std::string& name) { - if (getValueFromName(name, ParamValue<T>::getValue())) + if (base_t::getValueFromName(name, ParamValue<std::string>::getValue())) { - setValueName(name); + base_t::setValueName(name); } else { - setValue(name); + ParamValue<std::string>::setValue(name); } return *this; } operator const value_t&() const { - return ParamValue<T>::getValue(); + return ParamValue<std::string>::getValue(); } const value_t& operator()() const { - return ParamValue<T>::getValue(); + return ParamValue<std::string>::getValue(); } }; @@ -1778,7 +1779,7 @@ namespace LLInitParam // // Nested classes for declaring parameters // - template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>::type_value_t > + template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t > class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false> { typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; @@ -1808,7 +1809,7 @@ namespace LLInitParam } }; - template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>::type_value_t > + template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t > class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false> { typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t; @@ -1845,7 +1846,7 @@ namespace LLInitParam }; - template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T>::type_value_t > + template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t > class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true> { typedef TypedParam<T, NAME_VALUE_LOOKUP, true> super_t; -- cgit v1.2.3 From f7668cd09d300fb4ad63ac6ad8880432d2da6c7f Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Mon, 16 Apr 2012 13:50:10 -0700 Subject: more gcc build fixin --- indra/llxuixml/llinitparam.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 9135b200ab..afb6868c4b 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -179,11 +179,11 @@ namespace LLInitParam { private: struct Inaccessable{}; - typedef typename ParamValue<T>::value_t value_t; public: typedef std::map<std::string, T> value_name_map_t; typedef Inaccessable name_t; typedef TypeValues<T> type_value_t; + typedef typename ParamValue<T>::value_t value_t; TypeValues(const value_t& val) : ParamValue<T>(val) @@ -232,11 +232,11 @@ namespace LLInitParam : public ParamValue<T> { typedef TypeValuesHelper<T, DERIVED_TYPE, IS_SPECIALIZED> self_t; - typedef typename ParamValue<T>::value_t value_t; public: typedef typename std::map<std::string, T> value_name_map_t; typedef std::string name_t; typedef self_t type_value_t; + typedef typename ParamValue<T>::value_t value_t; TypeValuesHelper(const value_t& val) : ParamValue<T>(val) @@ -845,10 +845,11 @@ namespace LLInitParam protected: typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t; typedef ParamValue<T> param_value_t; - typedef typename param_value_t::value_t value_t; typedef typename param_value_t::default_value_t default_value_t; typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; public: + typedef typename param_value_t::value_t value_t; + using named_value_t::operator(); TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) @@ -1002,12 +1003,12 @@ namespace LLInitParam { protected: typedef ParamValue<T> param_value_t; - typedef typename param_value_t::value_t value_t; typedef typename param_value_t::default_value_t default_value_t; typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> self_t; typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; public: using named_value_t::operator(); + typedef typename param_value_t::value_t value_t; TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr), @@ -1188,10 +1189,11 @@ namespace LLInitParam typedef ParamValue<VALUE_TYPE> param_value_t; typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t; typedef container_t default_value_t; - typedef typename param_value_t::value_t value_t; typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; public: + typedef typename param_value_t::value_t value_t; + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) { @@ -1386,11 +1388,12 @@ namespace LLInitParam typedef ParamValue<VALUE_TYPE> param_value_t; typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t; typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; - typedef typename param_value_t::value_t value_t; typedef container_t default_value_t; typedef typename container_t::iterator iterator; typedef typename container_t::const_iterator const_iterator; public: + typedef typename param_value_t::value_t value_t; + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) { -- cgit v1.2.3 From cfb2803f1e01cc9596ba3c6dae9679adb454819e Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Sat, 14 Apr 2012 01:10:23 +0300 Subject: CHUI-78 WIP Remove bottom button bar from the people panel. By the way, removed the "Activate" button from the Groups tab. --- indra/newview/llpanelpeople.cpp | 99 ------ indra/newview/llpanelpeople.h | 9 - .../newview/skins/default/xui/en/panel_people.xml | 380 ++++----------------- 3 files changed, 71 insertions(+), 417 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 1c63b2a930..a9da9e0cbf 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -509,16 +509,8 @@ LLPanelPeople::LLPanelPeople() mCommitCallbackRegistrar.add("People.AddFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this)); mCommitCallbackRegistrar.add("People.AddFriendWizard", boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked, this)); mCommitCallbackRegistrar.add("People.DelFriend", boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked, this)); - mCommitCallbackRegistrar.add("People.Group.Activate", boost::bind(&LLPanelPeople::onActivateButtonClicked, this)); mCommitCallbackRegistrar.add("People.Group.Minus", boost::bind(&LLPanelPeople::onGroupMinusButtonClicked, this)); - mCommitCallbackRegistrar.add("People.ViewProfile", boost::bind(&LLPanelPeople::onViewProfileButtonClicked, this)); - mCommitCallbackRegistrar.add("People.GroupInfo", boost::bind(&LLPanelPeople::onGroupInfoButtonClicked, this)); mCommitCallbackRegistrar.add("People.Chat", boost::bind(&LLPanelPeople::onChatButtonClicked, this)); - mCommitCallbackRegistrar.add("People.IM", boost::bind(&LLPanelPeople::onImButtonClicked, this)); - mCommitCallbackRegistrar.add("People.Call", boost::bind(&LLPanelPeople::onCallButtonClicked, this)); - mCommitCallbackRegistrar.add("People.GroupCall", boost::bind(&LLPanelPeople::onGroupCallButtonClicked, this)); - mCommitCallbackRegistrar.add("People.Teleport", boost::bind(&LLPanelPeople::onTeleportButtonClicked, this)); - mCommitCallbackRegistrar.add("People.Share", boost::bind(&LLPanelPeople::onShareButtonClicked, this)); mCommitCallbackRegistrar.add("People.Group.Plus.Action", boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked, this, _2)); mCommitCallbackRegistrar.add("People.Friends.ViewSort.Action", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked, this, _2)); @@ -770,24 +762,9 @@ void LLPanelPeople::updateRecentList() mRecentList->setDirty(); } -void LLPanelPeople::buttonSetVisible(std::string btn_name, BOOL visible) -{ - // To make sure we're referencing the right widget (a child of the button bar). - LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name); - button->setVisible(visible); -} - -void LLPanelPeople::buttonSetEnabled(const std::string& btn_name, bool enabled) -{ - // To make sure we're referencing the right widget (a child of the button bar). - LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name); - button->setEnabled(enabled); -} - void LLPanelPeople::updateButtons() { std::string cur_tab = getActiveTabName(); - bool nearby_tab_active = (cur_tab == NEARBY_TAB_NAME); bool friends_tab_active = (cur_tab == FRIENDS_TAB_NAME); bool group_tab_active = (cur_tab == GROUP_TAB_NAME); //bool recent_tab_active = (cur_tab == RECENT_TAB_NAME); @@ -798,27 +775,14 @@ void LLPanelPeople::updateButtons() bool item_selected = (selected_uuids.size() == 1); bool multiple_selected = (selected_uuids.size() >= 1); - buttonSetVisible("group_info_btn", group_tab_active); - buttonSetVisible("chat_btn", group_tab_active); - buttonSetVisible("view_profile_btn", !group_tab_active); - buttonSetVisible("im_btn", !group_tab_active); - buttonSetVisible("call_btn", !group_tab_active); - buttonSetVisible("group_call_btn", group_tab_active); - buttonSetVisible("teleport_btn", friends_tab_active); - buttonSetVisible("share_btn", nearby_tab_active || friends_tab_active); - if (group_tab_active) { - bool cur_group_active = true; - if (item_selected) { selected_id = mGroupList->getSelectedUUID(); - cur_group_active = (gAgent.getGroupID() == selected_id); } LLPanel* groups_panel = mTabContainer->getCurrentPanel(); - groups_panel->getChildView("activate_btn")->setEnabled(item_selected && !cur_group_active); // "none" or a non-active group selected groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected } else @@ -844,19 +808,6 @@ void LLPanelPeople::updateButtons() } } } - - bool enable_calls = LLVoiceClient::getInstance()->isVoiceWorking() && LLVoiceClient::getInstance()->voiceEnabled(); - - buttonSetEnabled("view_profile_btn",item_selected); - buttonSetEnabled("share_btn", item_selected); - buttonSetEnabled("im_btn", multiple_selected); // allow starting the friends conference for multiple selection - buttonSetEnabled("call_btn", multiple_selected && enable_calls); - buttonSetEnabled("teleport_btn", multiple_selected && LLAvatarActions::canOfferTeleport(selected_uuids)); - - bool none_group_selected = item_selected && selected_id.isNull(); - buttonSetEnabled("group_info_btn", !none_group_selected); - buttonSetEnabled("group_call_btn", !none_group_selected && enable_calls); - buttonSetEnabled("chat_btn", !none_group_selected); } std::string LLPanelPeople::getActiveTabName() const @@ -1082,12 +1033,6 @@ void LLPanelPeople::onAvatarListCommitted(LLAvatarList* list) updateButtons(); } -void LLPanelPeople::onViewProfileButtonClicked() -{ - LLUUID id = getCurrentItemID(); - LLAvatarActions::showProfile(id); -} - void LLPanelPeople::onAddFriendButtonClicked() { LLUUID id = getCurrentItemID(); @@ -1141,11 +1086,6 @@ void LLPanelPeople::onDeleteFriendButtonClicked() } } -void LLPanelPeople::onGroupInfoButtonClicked() -{ - LLGroupActions::show(getCurrentItemID()); -} - void LLPanelPeople::onChatButtonClicked() { LLUUID group_id = getCurrentItemID(); @@ -1169,11 +1109,6 @@ void LLPanelPeople::onImButtonClicked() } } -void LLPanelPeople::onActivateButtonClicked() -{ - LLGroupActions::activate(mGroupList->getSelectedUUID()); -} - // static void LLPanelPeople::onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names) { @@ -1327,40 +1262,6 @@ bool LLPanelPeople::onRecentViewSortMenuItemCheck(const LLSD& userdata) return false; } -void LLPanelPeople::onCallButtonClicked() -{ - uuid_vec_t selected_uuids; - getCurrentItemIDs(selected_uuids); - - if (selected_uuids.size() == 1) - { - // initiate a P2P voice chat with the selected user - LLAvatarActions::startCall(getCurrentItemID()); - } - else if (selected_uuids.size() > 1) - { - // initiate an ad-hoc voice chat with multiple users - LLAvatarActions::startAdhocCall(selected_uuids); - } -} - -void LLPanelPeople::onGroupCallButtonClicked() -{ - LLGroupActions::startCall(getCurrentItemID()); -} - -void LLPanelPeople::onTeleportButtonClicked() -{ - uuid_vec_t selected_uuids; - getCurrentItemIDs(selected_uuids); - LLAvatarActions::offerTeleport(selected_uuids); -} - -void LLPanelPeople::onShareButtonClicked() -{ - LLAvatarActions::share(getCurrentItemID()); -} - void LLPanelPeople::onMoreButtonClicked() { // *TODO: not implemented yet diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 765e62ffa6..c99bc532ab 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -80,27 +80,18 @@ private: std::string getActiveTabName() const; LLUUID getCurrentItemID() const; void getCurrentItemIDs(uuid_vec_t& selected_uuids) const; - void buttonSetVisible(std::string btn_name, BOOL visible); - void buttonSetEnabled(const std::string& btn_name, bool enabled); void showGroupMenu(LLMenuGL* menu); void setSortOrder(LLAvatarList* list, ESortOrder order, bool save = true); // UI callbacks void onFilterEdit(const std::string& search_string); void onTabSelected(const LLSD& param); - void onViewProfileButtonClicked(); void onAddFriendButtonClicked(); void onAddFriendWizButtonClicked(); void onDeleteFriendButtonClicked(); - void onGroupInfoButtonClicked(); void onChatButtonClicked(); void onImButtonClicked(); - void onCallButtonClicked(); - void onGroupCallButtonClicked(); - void onTeleportButtonClicked(); - void onShareButtonClicked(); void onMoreButtonClicked(); - void onActivateButtonClicked(); void onAvatarListDoubleClicked(LLUICtrl* ctrl); void onAvatarListCommitted(LLAvatarList* list); bool onGroupPlusButtonValidate(); diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 03b6c4fb8b..f2f6bdd84d 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -55,8 +55,8 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="AltMiniMapToolTipMsg" value="[REGION](Double-click to teleport, shift-drag to pan)"/> <tab_container + bottom="-10" follows="all" - height="419" layout="topleft" left="3" name="tabs" @@ -75,15 +75,15 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M background_visible="true" bg_alpha_color="DkGray" bg_opaque_color="DkGray" + bottom="-1" follows="all" - height="383" label="NEARBY" layout="topleft" left="0" help_topic="people_nearby_tab" name="nearby_panel" - top="0" - width="313"> + right="-1" + top="0"> <panel follows="left|top|right" height="27" @@ -91,20 +91,20 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left="0" name="nearby_buttons_panel" - top="0" - width="313"> + right="-1" + top="0"> <filter_editor follows="left|top|right" height="23" layout="topleft" - left="3" + left="6" label="Filter People" max_length_chars="300" name="nearby_filter_input" text_color="Black" text_pad_left="10" - top="2" - width="167" /> + top="4" + width="178" /> <menu_button follows="right" height="25" @@ -113,11 +113,11 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" - left_pad="10" + left_pad="7" menu_filename="menu_people_nearby_view.xml" menu_position="bottomleft" name="nearby_view_btn" - top="1" + top="3" width="31" /> <menu_button follows="right" @@ -131,7 +131,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M menu_filename="menu_people_nearby_sort.xml" menu_position="bottomleft" name="nearby_sort_btn" - top="1" + top_delta="0" width="31" /> <button follows="right" @@ -143,7 +143,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left_pad="2" name="add_friend_btn" - top="1" + top_delta="0" width="31"> <commit_callback function="People.AddFriend" /> @@ -159,7 +159,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left_pad="2" layout="topleft" name="nearby_del_btn" - top="1" + top_delta="0" width="31"> <commit_callback function="People.DelFriend" /> @@ -168,13 +168,13 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M <layout_stack clip="false" follows="all" - height="355" + height="410" layout="topleft" left="0" mouse_opaque="false" orientation="vertical" - top_pad="0" - width="313"> + right="-1" + top_pad="0"> <layout_panel height="142" layout="topleft" @@ -191,16 +191,16 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left="3" mouse_opaque="false" name="Net Map" - top="4" - width="305"/> + right="-1" + top="4" /> </layout_panel> <layout_panel height="213" layout="topleft" min_dim="100" mouse_opaque="false" - user_resize="true" - width="313"> + right="-1" + user_resize="true"> <avatar_list allow_select="true" follows="all" @@ -211,8 +211,8 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M keep_one_selected="false" multi_select="true" name="avatar_list" - top="2" - width="306" /> + right="-1" + top="2" /> </layout_panel> </layout_stack> </panel> @@ -224,15 +224,15 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M background_visible="true" bg_alpha_color="DkGray" bg_opaque_color="DkGray" + bottom="-1" follows="all" - height="383" label="MY FRIENDS" layout="topleft" left="0" help_topic="people_friends_tab" name="friends_panel" - top="0" - width="313"> + right="-1" + top="0"> <panel follows="left|top|right" height="27" @@ -240,20 +240,20 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left="0" name="friends_buttons_panel" - top="0" - width="313"> + right="-1" + top="0"> <filter_editor follows="left|top|right" height="23" layout="topleft" - left="3" + left="6" label="Filter People" max_length_chars="300" name="friends_filter_input" text_color="Black" text_pad_left="10" - top="2" - width="167" /> + top="4" + width="177" /> <menu_button follows="right" height="25" @@ -262,11 +262,11 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" - left_pad="10" + left_pad="8" menu_filename="menu_people_friends_view.xml" menu_position="bottomleft" name="friends_view_btn" - top="1" + top="3" width="31" /> <menu_button follows="right" @@ -280,7 +280,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M menu_filename="menu_people_friends_sort.xml" menu_position="bottomleft" name="friends_sort_btn" - top="1" + top_delta="0" width="31" /> <button follows="right" @@ -292,7 +292,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left_pad="2" name="friends_add_btn" - top="1" + top_delta="0" width="31"> <commit_callback function="People.AddFriendWizard" /> @@ -307,7 +307,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left_pad="2" layout="topleft" name="friends_del_btn" - top="1" + top_delta="0" width="31"> <commit_callback function="People.DelFriend" /> @@ -318,12 +318,12 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" follows="all" - height="356" + height="408" layout="topleft" left="3" name="friends_accordion" - top_pad="0" - width="307"> + right="-2" + top_pad="2"> <accordion_tab layout="topleft" height="172" @@ -365,8 +365,8 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M height="450" left="13" name="no_friends_help_text" + right="-13" top="37" - width="293" wrap="true" /> </panel> @@ -377,15 +377,15 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M background_visible="true" bg_alpha_color="DkGray" bg_opaque_color="DkGray" + bottom="-1" follows="all" - height="383" label="MY GROUPS" layout="topleft" left="0" help_topic="people_groups_tab" name="groups_panel" - top="0" - width="313"> + right="-1" + top="0"> <!-- *NOTE: no_groups_msg & group_list attributes are not defined as translatable in VLT. See EXT-5931 Values are set from appropriate strings at the top of file via LLPeoplePanel::postBuild() @@ -397,20 +397,20 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left="0" name="groups_buttons_panel" - top="0" - width="313"> + right="-1" + top="0"> <filter_editor follows="left|top|right" height="23" layout="topleft" - left="3" + left="6" label="Filter Groups" max_length_chars="300" name="groups_filter_input" text_color="Black" text_pad_left="10" - top="2" - width="134" /> + top="4" + width="177" /> <menu_button follows="right" height="25" @@ -419,11 +419,11 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" - left_pad="10" + left_pad="8" menu_filename="menu_people_groups_view.xml" menu_position="bottomleft" name="groups_view_btn" - top="1" + top="3" width="31" /> <menu_button enabled="false" @@ -436,23 +436,8 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left_pad="2" name="groups_sort_btn" - top="1" + top_delta="0" width="31" /> - <button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Activate_Checkmark" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="2" - name="activate_btn" - top="1" - width="31"> - <commit_callback - function="People.Group.Activate" /> - </button> <menu_button follows="right" height="25" @@ -465,7 +450,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M menu_filename="menu_group_plus.xml" menu_position="bottomleft" name="minus_btn" - top="1" + top_delta="0" width="31"> <validate_callback function="People.Group.Plus.Validate" /> @@ -480,7 +465,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left_pad="2" layout="topleft" name="minus_btn" - top="1" + top_delta="0" width="31"> <commit_callback function="People.Group.Minus" /> @@ -489,12 +474,12 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M <group_list allow_select="true" follows="all" - height="356" + height="406" layout="topleft" left="3" name="group_list" - top_pad="0" - width="307" /> + right="-2" + top_pad="4" /> </panel> <!-- ================================= RECENT tab =========================== --> @@ -511,8 +496,8 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left="0" help_topic="people_recent_tab" name="recent_panel" - top="0" - width="313"> + right="-1" + top="0"> <panel follows="left|top|right" height="27" @@ -520,20 +505,20 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left="0" name="recent_buttons_panel" - top="0" - width="313"> + right="-1" + top="0"> <filter_editor follows="left|top|right" height="23" layout="topleft" - left="3" + left="6" label="Filter People" max_length_chars="300" name="recent_filter_input" text_color="Black" text_pad_left="10" - top="2" - width="167" /> + top="4" + width="177" /> <menu_button follows="right" height="25" @@ -542,11 +527,11 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" - left_pad="10" + left_pad="8" menu_filename="menu_people_recent_view.xml" menu_position="bottomleft" name="recent_view_btn" - top="1" + top="3" width="31" /> <menu_button follows="right" @@ -560,7 +545,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M menu_filename="menu_people_recent_sort.xml" menu_position="bottomleft" name="recent_sort_btn" - top="1" + top_delta="0" width="31" /> <button follows="right" @@ -572,7 +557,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left_pad="2" name="add_friend_btn" - top="1" + top_delta="0" width="31"> <commit_callback function="People.AddFriend" /> @@ -588,7 +573,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left_pad="2" layout="topleft" name="recent_del_btn" - top="1" + top_delta="0" width="31"> <commit_callback function="People.DelFriend" /> @@ -597,14 +582,14 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M <avatar_list allow_select="true" follows="all" - height="356" + height="351" layout="topleft" left="3" multi_select="true" name="avatar_list" show_last_interaction_time="true" - top_pad="0" - width="307" /> + right="-2" + top_pad="4" /> </panel> <!-- ================================= BLOCKED tab ========================== --> @@ -633,227 +618,4 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M width="313" /> </panel> </tab_container> - <panel - follows="bottom|left|right" - height="23" - layout="topleft" - left="8" - top_pad="4" - name="button_bar" - width="313"> - -<!--********************************Profile; IM; Call, Share, Teleport********************************--> - <layout_stack - follows="bottom|left|right" - height="23" - layout="topleft" - name="bottom_bar_ls" - left="0" - orientation="horizontal" - top_pad="0" - width="313"> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left="0" - name="view_profile_btn_lp" - auto_resize="true" - width="68"> - <button - follows="bottom|left|right" - height="23" - label="Profile" - layout="topleft" - left="1" - name="view_profile_btn" - tool_tip="Show picture, groups, and other Residents information" - top="0" - width="67"> - <commit_callback - function="People.ViewProfile" /> - </button> - </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left_pad="3" - name="im_btn_lp" - auto_resize="true" - width="41"> - <button - follows="bottom|left|right" - left="1" - height="23" - label="IM" - layout="topleft" - name="im_btn" - tool_tip="Open instant message session" - top="0" - width="40"> - <commit_callback - function="People.IM" /> - </button> - </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left_pad="3" - name="call_btn_lp" - auto_resize="true" - width="52"> - <button - follows="bottom|left|right" - left="1" - height="23" - label="Call" - layout="topleft" - name="call_btn" - tool_tip="Call this Resident" - top="0" - width="51"> - <commit_callback - function="People.Call" /> - </button> - </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left_pad="3" - name="share_btn_lp" - auto_resize="true" - width="66"> - <button - follows="bottom|left|right" - left="1" - height="23" - label="Share" - layout="topleft" - name="share_btn" - tool_tip="Share an inventory item" - top="0" - width="65"> - <commit_callback - function="People.Share" /> - </button> - </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left_pad="3" - name="teleport_btn_lp" - auto_resize="true" - width="77"> - <button - follows="bottom|left|right" - left="1" - height="23" - label="Teleport" - layout="topleft" - name="teleport_btn" - tool_tip="Offer teleport" - top="0" - width="76"> - <commit_callback - function="People.Teleport" /> - </button> - </layout_panel> - </layout_stack> - -<!--********************************Group Profile; Group Chat; Group Call buttons************************--> - <layout_stack - follows="bottom|left|right" - height="23" - layout="topleft" - mouse_opaque="false" - name="bottom_bar_ls1" - left="0" - orientation="horizontal" - top="0" - width="313"> - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left="0" - mouse_opaque="false" - name="group_info_btn_lp" - auto_resize="true" - width="108"> - <button - follows="bottom|left|right" - left="1" - height="23" - label="Group Profile" - layout="topleft" - mouse_opaque="false" - name="group_info_btn" - tool_tip="Show group information" - top="0" - width="107"> - <commit_callback - function="People.GroupInfo" /> - </button> - </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left_pad="3" - mouse_opaque="false" - name="chat_btn_lp" - auto_resize="true" - width="101"> - <button - follows="bottom|left|right" - left="1" - height="23" - label="Group Chat" - layout="topleft" - mouse_opaque="false" - name="chat_btn" - tool_tip="Open chat session" - top="0" - width="100"> - <commit_callback - function="People.Chat" /> - </button> - </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left_pad="3" - mouse_opaque="false" - name="group_call_btn_lp" - auto_resize="true" - width="96"> - <button - follows="bottom|left|right" - left="1" - height="23" - label="Group Call" - layout="topleft" - mouse_opaque="false" - name="group_call_btn" - tool_tip="Call this group" - top="0" - width="95"> - <commit_callback - function="People.GroupCall" /> - </button> - </layout_panel> - </layout_stack> - </panel> </panel> -- cgit v1.2.3 From 33e78bfe64240f71bcc40ca34950770ce549dc69 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Sat, 14 Apr 2012 02:04:37 +0300 Subject: CHUI-78 WIP Re-combined view and sort menus in the People panel. --- .../default/xui/en/menu_people_friends_sort.xml | 26 ---------------- .../default/xui/en/menu_people_friends_view.xml | 21 +++++++++++++ .../skins/default/xui/en/menu_people_groups.xml | 4 +-- .../default/xui/en/menu_people_nearby_sort.xml | 36 ---------------------- .../default/xui/en/menu_people_nearby_view.xml | 31 +++++++++++++++++++ .../default/xui/en/menu_people_recent_sort.xml | 26 ---------------- .../default/xui/en/menu_people_recent_view.xml | 21 +++++++++++++ .../newview/skins/default/xui/en/panel_people.xml | 35 +++++++++++---------- 8 files changed, 93 insertions(+), 107 deletions(-) delete mode 100644 indra/newview/skins/default/xui/en/menu_people_friends_sort.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_people_recent_sort.xml (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_sort.xml deleted file mode 100644 index 532e295386..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_friends_sort.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu - name="menu_group_plus" - left="0" bottom="0" visible="false" - mouse_opaque="false"> - <menu_item_check - label="Sort by Name" - name="sort_name"> - <menu_item_check.on_click - function="People.Friends.ViewSort.Action" - parameter="sort_name" /> - <menu_item_check.on_check - function="People.Friends.ViewSort.CheckItem" - parameter="sort_name" /> - </menu_item_check> - <menu_item_check - label="Sort by Status" - name="sort_status"> - <menu_item_check.on_click - function="People.Friends.ViewSort.Action" - parameter="sort_status" /> - <menu_item_check.on_check - function="People.Friends.ViewSort.CheckItem" - parameter="sort_status" /> - </menu_item_check> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml index 14a3e1f13d..eab7b8c085 100644 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml @@ -3,6 +3,27 @@ name="menu_group_plus" left="0" bottom="0" visible="false" mouse_opaque="false"> + <menu_item_check + label="Sort by Name" + name="sort_name"> + <menu_item_check.on_click + function="People.Friends.ViewSort.Action" + parameter="sort_name" /> + <menu_item_check.on_check + function="People.Friends.ViewSort.CheckItem" + parameter="sort_name" /> + </menu_item_check> + <menu_item_check + label="Sort by Status" + name="sort_status"> + <menu_item_check.on_click + function="People.Friends.ViewSort.Action" + parameter="sort_status" /> + <menu_item_check.on_check + function="People.Friends.ViewSort.CheckItem" + parameter="sort_status" /> + </menu_item_check> + <menu_item_separator layout="topleft" /> <menu_item_check name="view_icons" label="View People Icons"> <menu_item_check.on_click function="People.Friends.ViewSort.Action" diff --git a/indra/newview/skins/default/xui/en/menu_people_groups.xml b/indra/newview/skins/default/xui/en/menu_people_groups.xml index 8f89d37dbb..3a450258fa 100644 --- a/indra/newview/skins/default/xui/en/menu_people_groups.xml +++ b/indra/newview/skins/default/xui/en/menu_people_groups.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<menu name="menu_group_plus" +<toggleable_menu name="menu_group_plus" left="0" bottom="0" visible="false" mouse_opaque="false" opaque="true" color="MenuDefaultBgColor"> <menu_item_call @@ -54,4 +54,4 @@ function="People.Groups.Enable" parameter="leave" /> </menu_item_call> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml deleted file mode 100644 index cf7f4f4fce..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu - name="menu_group_plus" - left="0" bottom="0" visible="false" - mouse_opaque="false"> - <menu_item_check - label="Sort by Recent Speakers" - name="sort_by_recent_speakers"> - <menu_item_check.on_click - function="People.Nearby.ViewSort.Action" - parameter="sort_by_recent_speakers"/> - <menu_item_check.on_check - function="People.Nearby.ViewSort.CheckItem" - parameter="sort_by_recent_speakers"/> - </menu_item_check> - <menu_item_check - label="Sort by Name" - name="sort_name"> - <menu_item_check.on_click - function="People.Nearby.ViewSort.Action" - parameter="sort_name"/> - <menu_item_check.on_check - function="People.Nearby.ViewSort.CheckItem" - parameter="sort_name"/> - </menu_item_check> - <menu_item_check - label="Sort by Distance" - name="sort_distance"> - <menu_item_check.on_click - function="People.Nearby.ViewSort.Action" - parameter="sort_distance"/> - <menu_item_check.on_check - function="People.Nearby.ViewSort.CheckItem" - parameter="sort_distance"/> - </menu_item_check> - </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml index 4c94cf53af..da88ca9f4d 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml @@ -3,6 +3,37 @@ name="menu_group_plus" left="0" bottom="0" visible="false" mouse_opaque="false"> + <menu_item_check + label="Sort by Recent Speakers" + name="sort_by_recent_speakers"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="sort_by_recent_speakers"/> + <menu_item_check.on_check + function="People.Nearby.ViewSort.CheckItem" + parameter="sort_by_recent_speakers"/> + </menu_item_check> + <menu_item_check + label="Sort by Name" + name="sort_name"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="sort_name"/> + <menu_item_check.on_check + function="People.Nearby.ViewSort.CheckItem" + parameter="sort_name"/> + </menu_item_check> + <menu_item_check + label="Sort by Distance" + name="sort_distance"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="sort_distance"/> + <menu_item_check.on_check + function="People.Nearby.ViewSort.CheckItem" + parameter="sort_distance"/> + </menu_item_check> + <menu_item_separator layout="topleft" /> <menu_item_check name="view_icons" label="View People Icons"> <menu_item_check.on_click function="People.Nearby.ViewSort.Action" diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_sort.xml deleted file mode 100644 index f14be88780..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_recent_sort.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu - name="menu_group_plus" - left="0" bottom="0" visible="false" - mouse_opaque="false"> - <menu_item_check - label="Sort by Most Recent" - name="sort_most"> - <menu_item_check.on_click - function="People.Recent.ViewSort.Action" - parameter="sort_recent" /> - <menu_item_check.on_check - function="People.Recent.ViewSort.CheckItem" - parameter="sort_recent" /> - </menu_item_check> - <menu_item_check - label="Sort by Name" - name="sort_name"> - <menu_item_check.on_click - function="People.Recent.ViewSort.Action" - parameter="sort_name" /> - <menu_item_check.on_check - function="People.Recent.ViewSort.CheckItem" - parameter="sort_name" /> - </menu_item_check> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml index 0eaca47d9a..1dbc90dd2b 100644 --- a/indra/newview/skins/default/xui/en/menu_people_recent_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml @@ -3,6 +3,27 @@ name="menu_group_plus" left="0" bottom="0" visible="false" mouse_opaque="false"> + <menu_item_check + label="Sort by Most Recent" + name="sort_most"> + <menu_item_check.on_click + function="People.Recent.ViewSort.Action" + parameter="sort_recent" /> + <menu_item_check.on_check + function="People.Recent.ViewSort.CheckItem" + parameter="sort_recent" /> + </menu_item_check> + <menu_item_check + label="Sort by Name" + name="sort_name"> + <menu_item_check.on_click + function="People.Recent.ViewSort.Action" + parameter="sort_name" /> + <menu_item_check.on_check + function="People.Recent.ViewSort.CheckItem" + parameter="sort_name" /> + </menu_item_check> + <menu_item_separator layout="topleft" /> <menu_item_check name="view_icons" label="View People Icons"> <menu_item_check.on_click function="People.Recent.ViewSort.Action" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index f2f6bdd84d..ca28e3153c 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -114,9 +114,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="7" - menu_filename="menu_people_nearby_view.xml" + menu_filename="menu_people_nearby_gear.xml" menu_position="bottomleft" - name="nearby_view_btn" + name="nearby_gear_btn" top="3" width="31" /> <menu_button @@ -128,9 +128,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="2" - menu_filename="menu_people_nearby_sort.xml" + menu_filename="menu_people_nearby_view.xml" menu_position="bottomleft" - name="nearby_sort_btn" + name="nearby_view_btn" top_delta="0" width="31" /> <button @@ -263,9 +263,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="8" - menu_filename="menu_people_friends_view.xml" + menu_filename="menu_people_friends_gear.xml" menu_position="bottomleft" - name="friends_view_btn" + name="friends_gear_btn" top="3" width="31" /> <menu_button @@ -277,9 +277,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="2" - menu_filename="menu_people_friends_sort.xml" + menu_filename="menu_people_friends_view.xml" menu_position="bottomleft" - name="friends_sort_btn" + name="friends_view_btn" top_delta="0" width="31" /> <button @@ -420,13 +420,12 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="8" - menu_filename="menu_people_groups_view.xml" + menu_filename="menu_people_groups.xml" menu_position="bottomleft" - name="groups_view_btn" + name="groups_gear_btn" top="3" width="31" /> <menu_button - enabled="false" follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" @@ -435,7 +434,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="2" - name="groups_sort_btn" + menu_filename="menu_people_groups_view.xml" + menu_position="bottomleft" + name="groups_view_btn" top_delta="0" width="31" /> <menu_button @@ -449,7 +450,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left_pad="2" menu_filename="menu_group_plus.xml" menu_position="bottomleft" - name="minus_btn" + name="plus_btn" top_delta="0" width="31"> <validate_callback @@ -528,9 +529,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="8" - menu_filename="menu_people_recent_view.xml" + menu_filename="menu_people_recent_gear.xml" menu_position="bottomleft" - name="recent_view_btn" + name="recent_gear_btn" top="3" width="31" /> <menu_button @@ -542,9 +543,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="2" - menu_filename="menu_people_recent_sort.xml" + menu_filename="menu_people_recent_view.xml" menu_position="bottomleft" - name="recent_sort_btn" + name="recent_view_btn" top_delta="0" width="31" /> <button -- cgit v1.2.3 From 2412401e4c705c7073be845bba74353d446bd017 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Sat, 14 Apr 2012 21:03:36 +0300 Subject: CHUI-78 WIP Minor cleanup. --- indra/llui/llmenubutton.cpp | 6 +++--- indra/newview/lllistcontextmenu.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 98f7e0540c..320f62d5c1 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -76,7 +76,7 @@ void LLMenuButton::hideMenu() { if(mMenuHandle.isDead()) return; - LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get()); + LLToggleableMenu* menu = getMenu(); if (menu) { menu->setVisible(FALSE); @@ -132,7 +132,7 @@ BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask ) return TRUE; } - LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get()); + LLToggleableMenu* menu = getMenu(); if (menu && menu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE) { menu->setVisible(FALSE); @@ -160,7 +160,7 @@ void LLMenuButton::toggleMenu() if(mMenuHandle.isDead()) return; - LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get()); + LLToggleableMenu* menu = getMenu(); if (!menu) return; // Store the button rectangle to toggle menu visibility if a mouse event diff --git a/indra/newview/lllistcontextmenu.h b/indra/newview/lllistcontextmenu.h index fabd68ee20..04d3314829 100644 --- a/indra/newview/lllistcontextmenu.h +++ b/indra/newview/lllistcontextmenu.h @@ -37,7 +37,7 @@ class LLContextMenu; /** * Context menu for single or multiple list items. * - * Derived classes must implement contextMenu(). + * Derived classes must implement createMenu(). * * Typical usage: * <code> -- cgit v1.2.3 From 590890173216570ca834ba1ead66db1a25952247 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Sat, 14 Apr 2012 21:04:37 +0300 Subject: CHUI-78 WIP Made the gear buttons spawn the avatar list context menu. --- indra/newview/llpanelpeople.cpp | 14 ++++++++++++++ indra/newview/llpanelpeople.h | 1 + indra/newview/skins/default/xui/en/panel_people.xml | 21 +++++++++------------ 3 files changed, 24 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index a9da9e0cbf..6c3f07920b 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -511,6 +511,7 @@ LLPanelPeople::LLPanelPeople() mCommitCallbackRegistrar.add("People.DelFriend", boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked, this)); mCommitCallbackRegistrar.add("People.Group.Minus", boost::bind(&LLPanelPeople::onGroupMinusButtonClicked, this)); mCommitCallbackRegistrar.add("People.Chat", boost::bind(&LLPanelPeople::onChatButtonClicked, this)); + mCommitCallbackRegistrar.add("People.Gear", boost::bind(&LLPanelPeople::onGearButtonClicked, this, _1)); mCommitCallbackRegistrar.add("People.Group.Plus.Action", boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked, this, _2)); mCommitCallbackRegistrar.add("People.Friends.ViewSort.Action", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked, this, _2)); @@ -806,6 +807,11 @@ void LLPanelPeople::updateButtons() { cur_panel->getChildView("friends_del_btn")->setEnabled(multiple_selected); } + + if (!group_tab_active) + { + cur_panel->getChildView("gear_btn")->setEnabled(multiple_selected); + } } } } @@ -1093,6 +1099,14 @@ void LLPanelPeople::onChatButtonClicked() LLGroupActions::startIM(group_id); } +void LLPanelPeople::onGearButtonClicked(LLUICtrl* btn) +{ + uuid_vec_t selected_uuids; + getCurrentItemIDs(selected_uuids); + // Spawn at bottom left corner of the button. + LLPanelPeopleMenus::gNearbyMenu.show(btn, selected_uuids, 0, 0); +} + void LLPanelPeople::onImButtonClicked() { uuid_vec_t selected_uuids; diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index c99bc532ab..da27f83074 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -90,6 +90,7 @@ private: void onAddFriendWizButtonClicked(); void onDeleteFriendButtonClicked(); void onChatButtonClicked(); + void onGearButtonClicked(LLUICtrl* btn); void onImButtonClicked(); void onMoreButtonClicked(); void onAvatarListDoubleClicked(LLUICtrl* ctrl); diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index ca28e3153c..262c7cbf2c 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -105,7 +105,8 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M text_pad_left="10" top="4" width="178" /> - <menu_button + <button + commit_callback.function="People.Gear" follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" @@ -114,9 +115,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="7" - menu_filename="menu_people_nearby_gear.xml" - menu_position="bottomleft" - name="nearby_gear_btn" + name="gear_btn" top="3" width="31" /> <menu_button @@ -254,7 +253,8 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M text_pad_left="10" top="4" width="177" /> - <menu_button + <button + commit_callback.function="People.Gear" follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" @@ -263,9 +263,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="8" - menu_filename="menu_people_friends_gear.xml" - menu_position="bottomleft" - name="friends_gear_btn" + name="gear_btn" top="3" width="31" /> <menu_button @@ -520,7 +518,8 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M text_pad_left="10" top="4" width="177" /> - <menu_button + <button + commit_callback.function="People.Gear" follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" @@ -529,9 +528,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="8" - menu_filename="menu_people_recent_gear.xml" - menu_position="bottomleft" - name="recent_gear_btn" + name="gear_btn" top="3" width="31" /> <menu_button -- cgit v1.2.3 From 3adf89351359210f6f8a0f33cef94733a815dea1 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Sat, 14 Apr 2012 22:28:49 +0300 Subject: CHU-78 WIP Subtle cleanup. --- indra/llui/llmenubutton.cpp | 13 +++++-------- indra/llui/llmenugl.cpp | 5 ----- indra/llui/llmenugl.h | 2 -- 3 files changed, 5 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 320f62d5c1..746ade4648 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -74,8 +74,6 @@ boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_sign void LLMenuButton::hideMenu() { - if(mMenuHandle.isDead()) return; - LLToggleableMenu* menu = getMenu(); if (menu) { @@ -120,7 +118,7 @@ void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_T BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask ) { - if (mMenuHandle.isDead()) return FALSE; + if (!getMenu()) return FALSE; if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key)) { @@ -158,8 +156,6 @@ void LLMenuButton::toggleMenu() return; } - if(mMenuHandle.isDead()) return; - LLToggleableMenu* menu = getMenu(); if (!menu) return; @@ -189,7 +185,8 @@ void LLMenuButton::toggleMenu() void LLMenuButton::updateMenuOrigin() { - if (mMenuHandle.isDead()) return; + LLToggleableMenu* menu = getMenu(); + if (!menu) return; LLRect rect = getRect(); @@ -198,12 +195,12 @@ void LLMenuButton::updateMenuOrigin() case MP_TOP_LEFT: { mX = rect.mLeft; - mY = rect.mTop + mMenuHandle.get()->getRect().getHeight(); + mY = rect.mTop + menu->getRect().getHeight(); break; } case MP_TOP_RIGHT: { - const LLRect& menu_rect = mMenuHandle.get()->getRect(); + const LLRect& menu_rect = menu->getRect(); mX = rect.mRight - menu_rect.getWidth(); mY = rect.mTop + menu_rect.getHeight(); break; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 95ecbb1c94..62b695fedb 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -4021,11 +4021,6 @@ BOOL LLContextMenu::handleRightMouseUp( S32 x, S32 y, MASK mask ) return result; } -void LLContextMenu::draw() -{ - LLMenuGL::draw(); -} - BOOL LLContextMenu::appendContextSubMenu(LLContextMenu *menu) { diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 36f3ba34b9..c6ee5434b0 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -668,8 +668,6 @@ public: // can't set visibility directly, must call show or hide virtual void setVisible (BOOL visible); - virtual void draw (); - virtual void show (S32 x, S32 y); virtual void hide (); -- cgit v1.2.3 From aa4a9059037d3e75d2c93d7889b460978d41fde1 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine <vsavchuk@productengine.com> Date: Tue, 17 Apr 2012 15:44:04 +0300 Subject: CHUI-91 ADDITIONAL_FIX Minor visual layout fixes. --- indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml | 9 +++++---- indra/newview/skins/default/xui/en/panel_people.xml | 9 ++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml index 84b772d256..18532da593 100644 --- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -4,20 +4,21 @@ follows="left|top|right|bottom" height="305" layout="topleft" + left="0" name="block_list_panel" help_topic="blocked_list" min_height="350" min_width="240" - width="280"> + right="-1"> <scroll_list follows="all" height="220" layout="topleft" - left="5" + left="3" name="blocked" tool_tip="List of currently blocked Residents" - top="0" - width="270"> + right="-1" + top="1"> <scroll_list.columns name="item_name" /> <scroll_list.columns diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 262c7cbf2c..abfb9c7a36 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -604,16 +604,19 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left="0" help_topic="people_blocked_tab" name="blocked_panel" - top="0" - width="313"> + right="-1" + top="0"> <panel class="panel_block_list_sidetray" height="383" name="panel_block_list_sidetray" filename="panel_block_list_sidetray.xml" + follows="all" label="Blocked Residents & Objects" + left="0" font="SansSerifBold" - width="313" /> + top="0" + right="-1" /> </panel> </tab_container> </panel> -- cgit v1.2.3 From 37186d452fcb94b13e34d01aa801e7db17ee353e Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 17 Apr 2012 14:13:31 -0700 Subject: CHUI-86 WIP Investigate voice-dot with name tag integration added draw3D to LLUIImage to encapsulate display of image in projective 3D space --- indra/llui/llui.cpp | 152 +++++++++++++++++++---------------------- indra/llui/llui.h | 3 +- indra/llui/lluiimage.cpp | 44 ++++++++++++ indra/llui/lluiimage.h | 4 +- indra/newview/llhudnametag.cpp | 96 ++++++++++++-------------- 5 files changed, 160 insertions(+), 139 deletions(-) (limited to 'indra') diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index b52b0355fe..46882850cc 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1464,144 +1464,132 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left, gGL.popUIMatrix(); } -void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, - const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, - const U32 edges) +void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, + const LLVector3& width_vec, const LLVector3& height_vec) { - LLVector3 left_border_width = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? border_width : LLVector3::zero; - LLVector3 right_border_width = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? border_width : LLVector3::zero; - - LLVector3 top_border_height = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? border_height : LLVector3::zero; - LLVector3 bottom_border_height = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? border_height : LLVector3::zero; - - gGL.begin(LLRender::QUADS); { // draw bottom left - gGL.texCoord2f(0.f, 0.f); + gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom); gGL.vertex3f(0.f, 0.f, 0.f); - gGL.texCoord2f(border_scale.mV[VX], 0.f); - gGL.vertex3fv(left_border_width.mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(0.f, border_scale.mV[VY]); - gGL.vertex3fv(bottom_border_height.mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); // draw bottom middle - gGL.texCoord2f(border_scale.mV[VX], 0.f); - gGL.vertex3fv(left_border_width.mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); - gGL.vertex3fv((width_vec - right_border_width).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); // draw bottom right - gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); - gGL.vertex3fv((width_vec - right_border_width).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); - gGL.texCoord2f(1.f, 0.f); + gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom); gGL.vertex3fv(width_vec.mV); - gGL.texCoord2f(1.f, border_scale.mV[VY]); - gGL.vertex3fv((width_vec + bottom_border_height).mV); + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); // draw left - gGL.texCoord2f(0.f, border_scale.mV[VY]); - gGL.vertex3fv(bottom_border_height.mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((height_vec - top_border_height).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); // draw middle - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); // draw right - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(1.f, border_scale.mV[VY]); - gGL.vertex3fv((width_vec + bottom_border_height).mV); + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); // draw top left - gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((height_vec - top_border_height).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], 1.f); - gGL.vertex3fv((left_border_width + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); - gGL.texCoord2f(0.f, 1.f); + gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop); gGL.vertex3fv((height_vec).mV); // draw top middle - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); - gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], 1.f); - gGL.vertex3fv((left_border_width + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); // draw top right - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f, 1.f); + gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop); gGL.vertex3fv((width_vec + height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); - gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); } gGL.end(); } -void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec) -{ - gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP); -} void LLUI::initClass(const settings_map_t& settings, LLImageProviderInterface* image_provider, diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 618ed2fc42..eafae10c49 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -127,8 +127,7 @@ typedef enum e_rounded_edge void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL); void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec); +void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLVector3& width_vec, const LLVector3& height_vec); inline void gl_rect_2d( const LLRect& rect, BOOL filled ) { diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp index 6ae42c8852..a4886dabb0 100644 --- a/indra/llui/lluiimage.cpp +++ b/indra/llui/lluiimage.cpp @@ -112,6 +112,50 @@ void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& drawSolid(border_rect, color); } +void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, + const LLRect& rect, const LLColor4& color) +{ + F32 border_scale = 1.f; + F32 border_height = (1.f - mScaleRegion.getHeight()) * getHeight(); + F32 border_width = (1.f - mScaleRegion.getWidth()) * getWidth(); + if (rect.getHeight() < border_height || rect.getWidth() < border_width) + { + if(border_height - rect.getHeight() > border_width - rect.getWidth()) + { + border_scale = (F32)rect.getHeight() / border_height; + } + else + { + border_scale = (F32)rect.getWidth() / border_width; + } + } + + LLUI::pushMatrix(); + { + LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis); + LLUI::translate(rect_origin.mV[VX], + rect_origin.mV[VY], + rect_origin.mV[VZ]); + gGL.getTexUnit(0)->bind(getImage()); + gGL.color4fv(color.mV); + + LLRectf center_uv_rect(mClipRegion.mLeft + mScaleRegion.mLeft * mClipRegion.getWidth(), + mClipRegion.mBottom + mScaleRegion.mTop * mClipRegion.getHeight(), + mClipRegion.mLeft + mScaleRegion.mRight * mClipRegion.getWidth(), + mClipRegion.mBottom + mScaleRegion.mBottom * mClipRegion.getHeight()); + gl_segmented_rect_3d_tex(mClipRegion, + center_uv_rect, + LLRectf(border_width * border_scale * 0.5f, + 1.f - (border_height * border_scale * 0.5f), + 1.f - (border_width * border_scale * 0.5f), + border_height * border_scale * 0.5f), + rect.getWidth() * x_axis, + rect.getHeight() * y_axis); + + } LLUI::popMatrix(); +} + + S32 LLUIImage::getWidth() const { // return clipped dimensions of actual image area diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h index b86ea67505..7817ba1c7b 100644 --- a/indra/llui/lluiimage.h +++ b/indra/llui/lluiimage.h @@ -64,7 +64,9 @@ public: void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const; void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); } void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); } - + + void draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, const LLRect& rect, const LLColor4& color); + const std::string& getName() const { return mName; } virtual S32 getWidth() const; diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index cf55954d7d..26c3ee8c7a 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -166,7 +166,6 @@ BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3& } // scale screen size of borders down - //RN: for now, text on hud objects is never occluded LLVector3 x_pixel_vec; LLVector3 y_pixel_vec; @@ -191,7 +190,6 @@ BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3& + (F32)mOffsetY * y_pixel_vec - (width_vec / 2.f) - (height_vec); - //LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); LLVector3 v[] = { @@ -201,18 +199,6 @@ BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3& bg_pos + height_vec, }; - if (debug_render) - { - gGL.begin(LLRender::LINE_STRIP); - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[2].mV); - gGL.vertex3fv(v[3].mV); - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[2].mV); - gGL.end(); - } - LLVector3 dir = end-start; F32 a, b, t; @@ -334,46 +320,48 @@ void LLHUDNameTag::renderText(BOOL for_select) + (y_pixel_vec * screen_offset.mV[VY]); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - LLUI::pushMatrix(); - { - LLVector3 bg_pos = render_position - + (F32)mOffsetY * y_pixel_vec - - (width_vec / 2.f) - - (height_vec); - LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); - - if (for_select) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - S32 name = mSourceObject->mGLName; - LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name); - gGL.color4ubv(coloru.mV); - gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); - LLUI::popMatrix(); - return; - } - else - { - gGL.getTexUnit(0)->bind(imagep->getImage()); - - gGL.color4fv(bg_color.mV); - gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); - - if ( mLabelSegments.size()) - { - LLUI::pushMatrix(); - { - gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); - LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; - LLVector3 label_offset = height_vec - label_height; - LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); - gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); - } - LLUI::popMatrix(); - } - } - } - LLUI::popMatrix(); + LLRect screen_rect; + screen_rect.setCenterAndSize(0, -mHeight / 2 + mOffsetY, mWidth, mHeight); + imagep->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color); + if (mLabelSegments.size()) + { + LLUIImagePtr rect_top_image = LLUI::getUIImage("Rounded_Rect_Top"); + LLRect label_top_rect = screen_rect; + const S32 label_height = llround((mFontp->getLineHeight() * (F32)mLabelSegments.size() + (VERTICAL_PADDING / 3.f))); + label_top_rect.mBottom = label_top_rect.mTop - label_height; + LLColor4 label_top_color = text_color; + label_top_color.mV[VALPHA] = gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor; + + rect_top_image->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color); + + } + //LLUI::pushMatrix(); + //{ + // LLVector3 bg_pos = render_position + // + (F32)mOffsetY * y_pixel_vec + // - (width_vec / 2.f) + // - (height_vec); + // LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); + + // gGL.getTexUnit(0)->bind(imagep->getImage()); + // + // gGL.color4fv(bg_color.mV); + // gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); + // + // if ( mLabelSegments.size()) + // { + // LLUI::pushMatrix(); + // { + // gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); + // LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; + // LLVector3 label_offset = height_vec - label_height; + // LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); + // gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); + // } + // LLUI::popMatrix(); + // } + //} + //LLUI::popMatrix(); F32 y_offset = (F32)mOffsetY; -- cgit v1.2.3 From 234ce663fa52a588662153e6e465a53643c4e0f4 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 17 Apr 2012 15:14:36 -0700 Subject: fixed build --- indra/llui/llui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llui.h b/indra/llui/llui.h index eafae10c49..1fbfbd7a07 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -127,7 +127,7 @@ typedef enum e_rounded_edge void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL); void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLVector3& width_vec, const LLVector3& height_vec); +void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec); inline void gl_rect_2d( const LLRect& rect, BOOL filled ) { -- cgit v1.2.3 From 8c5819bdde26ad748060be53a2b6fefe809ad18b Mon Sep 17 00:00:00 2001 From: Todd Stinson <stinson@lindenlab.com> Date: Tue, 17 Apr 2012 16:42:38 -0700 Subject: CHUI-86: Removing the LLHUDEffect parent class from the LLVoiceVisualizer. #ifdef'ing the code out for now, to be removed later. --- indra/newview/llfollowcam.cpp | 1 - indra/newview/llhudobject.cpp | 8 +- indra/newview/llhudobject.h | 4 +- indra/newview/llvoavatar.cpp | 14 + indra/newview/llvoicevisualizer.cpp | 1267 ++++++++++++++++++----------------- indra/newview/llvoicevisualizer.h | 37 +- 6 files changed, 695 insertions(+), 636 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfollowcam.cpp b/indra/newview/llfollowcam.cpp index b670af1782..47612fe25c 100644 --- a/indra/newview/llfollowcam.cpp +++ b/indra/newview/llfollowcam.cpp @@ -38,7 +38,6 @@ std::vector<LLFollowCamParams*> LLFollowCamMgr::sParamStack; //------------------------------------------------------- // constants //------------------------------------------------------- -const F32 ONE_HALF = 0.5; const F32 FOLLOW_CAM_ZOOM_FACTOR = 0.1f; const F32 FOLLOW_CAM_MIN_ZOOM_AMOUNT = 0.1f; const F32 DISTANCE_EPSILON = 0.0001f; diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp index 95d57d08d8..06b0c3c6c8 100644 --- a/indra/newview/llhudobject.cpp +++ b/indra/newview/llhudobject.cpp @@ -232,9 +232,11 @@ LLHUDEffect *LLHUDObject::addHUDEffect(const U8 type) case LL_HUD_EFFECT_LOOKAT: hud_objectp = new LLHUDEffectLookAt(type); break; - case LL_HUD_EFFECT_VOICE_VISUALIZER: - hud_objectp = new LLVoiceVisualizer(type); - break; +#ifdef XXX_STINSON_CHUI_REWORK + case LL_HUD_EFFECT_VOICE_VISUALIZER: + hud_objectp = new LLVoiceVisualizer(type); + break; +#endif // XXX_STINSON_CHUI_REWORK case LL_HUD_EFFECT_POINTAT: hud_objectp = new LLHUDEffectPointAt(type); break; diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h index 2f7a98c86c..6f8be41177 100644 --- a/indra/newview/llhudobject.h +++ b/indra/newview/llhudobject.h @@ -94,7 +94,9 @@ public: LL_HUD_EFFECT_EDIT, LL_HUD_EFFECT_LOOKAT, LL_HUD_EFFECT_POINTAT, - LL_HUD_EFFECT_VOICE_VISUALIZER, // Ventrella +#ifdef XXX_STINSON_CHUI_REWORK + LL_HUD_EFFECT_VOICE_VISUALIZER, // Ventrella +#endif // XXX_STINSON_CHUI_REWORK LL_HUD_NAME_TAG, LL_HUD_EFFECT_BLOB }; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index b420812a3c..e1d29da664 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -709,9 +709,13 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, LLMemType mt(LLMemType::MTYPE_AVATAR); //VTResume(); // VTune +#ifdef XXX_STINSON_CHUI_REWORK // mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim ); +#else // XXX_STINSON_CHUI_REWORK + mVoiceVisualizer = new LLVoiceVisualizer(); +#endif // XXX_STINSON_CHUI_REWORK lldebugs << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << llendl; @@ -870,7 +874,11 @@ void LLVOAvatar::markDead() mNameText = NULL; sNumVisibleChatBubbles--; } +#ifdef XXX_STINSON_CHUI_REWORK mVoiceVisualizer->markDead(); +#else // XXX_STINSON_CHUI_REWORK + mVoiceVisualizer->setStopSpeaking(); +#endif // XXX_STINSON_CHUI_REWORK LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ; LLViewerObject::markDead(); } @@ -1328,7 +1336,9 @@ void LLVOAvatar::initInstance(void) //VTPause(); // VTune +#ifdef XXX_STINSON_CHUI_REWORK mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) ); +#endif // XXX_STINSON_CHUI_REWORK } @@ -2424,6 +2434,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) { +#ifdef XXX_STINSON_CHUI_REWORK bool render_visualizer = voice_enabled; // Don't render the user's own voice visualizer when in mouselook, or when opening the mic is disabled. @@ -2436,6 +2447,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) } mVoiceVisualizer->setVoiceEnabled(render_visualizer); +#endif // XXX_STINSON_CHUI_REWORK if ( voice_enabled ) { @@ -2511,6 +2523,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) } } +#ifdef XXX_STINSON_CHUI_REWORK //-------------------------------------------------------------------------------------------- // here we get the approximate head position and set as sound source for the voice symbol // (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing) @@ -2528,6 +2541,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) tagPos[VZ] += ( mBodySize[VZ] + 0.125f ); mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos ); } +#endif // XXX_STINSON_CHUI_REWORK }//if ( voiceEnabled ) } diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index 47060720e7..dcf33bce10 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -1,625 +1,642 @@ -/** - * @file llvoicevisualizer.cpp - * @brief Draws in-world speaking indicators. - * - * $LicenseInfo:firstyear=2000&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -//---------------------------------------------------------------------- -// Voice Visualizer -// author: JJ Ventrella -// (information about this stuff can be found in "llvoicevisualizer.h") -//---------------------------------------------------------------------- -#include "llviewerprecompiledheaders.h" -#include "llviewercontrol.h" -#include "llglheaders.h" -#include "llsphere.h" -#include "llvoicevisualizer.h" -#include "llviewercamera.h" -#include "llviewerobject.h" -#include "llviewertexture.h" -#include "llviewertexturelist.h" -#include "llvoiceclient.h" -#include "llrender.h" - -//brent's wave image -//29de489d-0491-fb00-7dab-f9e686d31e83 - - -//-------------------------------------------------------------------------------------- -// sound symbol constants -//-------------------------------------------------------------------------------------- -const F32 HEIGHT_ABOVE_HEAD = 0.3f; // how many meters vertically above the av's head the voice symbol will appear -const F32 RED_THRESHOLD = LLVoiceClient::OVERDRIVEN_POWER_LEVEL; // value above which speaking amplitude causes the voice symbol to turn red -const F32 GREEN_THRESHOLD = 0.2f; // value above which speaking amplitude causes the voice symbol to turn green -const F32 FADE_OUT_DURATION = 0.4f; // how many seconds it takes for a pair of waves to fade away -const F32 EXPANSION_RATE = 1.0f; // how many seconds it takes for the waves to expand to twice their original size -const F32 EXPANSION_MAX = 1.5f; // maximum size scale to which the waves can expand before popping back to 1.0 -const F32 WAVE_WIDTH_SCALE = 0.03f; // base width of the waves -const F32 WAVE_HEIGHT_SCALE = 0.02f; // base height of the waves -const F32 BASE_BRIGHTNESS = 0.7f; // gray level of the voice indicator when quiet (below green threshold) -const F32 DOT_SIZE = 0.05f; // size of the dot billboard texture -const F32 DOT_OPACITY = 0.7f; // how opaque the dot is -const F32 WAVE_MOTION_RATE = 1.5f; // scalar applied to consecutive waves as a function of speaking amplitude - -//-------------------------------------------------------------------------------------- -// gesticulation constants -//-------------------------------------------------------------------------------------- -const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE = 0.2f; -const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE = 1.0f; - -//-------------------------------------------------------------------------------------- -// other constants -//-------------------------------------------------------------------------------------- -const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code. -const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL - - -//------------------------------------------------------------------ -// handles parameter updates -//------------------------------------------------------------------ -static bool handleVoiceVisualizerPrefsChanged(const LLSD& newvalue) -{ - // Note: Ignore the specific event value, we look up the ones we want - LLVoiceVisualizer::setPreferences(); - return true; -} - -//------------------------------------------------------------------ -// Initialize the statics -//------------------------------------------------------------------ -bool LLVoiceVisualizer::sPrefsInitialized = false; -BOOL LLVoiceVisualizer::sLipSyncEnabled = FALSE; -F32* LLVoiceVisualizer::sOoh = NULL; -F32* LLVoiceVisualizer::sAah = NULL; -U32 LLVoiceVisualizer::sOohs = 0; -U32 LLVoiceVisualizer::sAahs = 0; -F32 LLVoiceVisualizer::sOohAahRate = 0.0f; -F32* LLVoiceVisualizer::sOohPowerTransfer = NULL; -U32 LLVoiceVisualizer::sOohPowerTransfers = 0; -F32 LLVoiceVisualizer::sOohPowerTransfersf = 0.0f; -F32* LLVoiceVisualizer::sAahPowerTransfer = NULL; -U32 LLVoiceVisualizer::sAahPowerTransfers = 0; -F32 LLVoiceVisualizer::sAahPowerTransfersf = 0.0f; - - -//----------------------------------------------- -// constructor -//----------------------------------------------- -LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) -:LLHUDEffect( type ) -{ - mCurrentTime = mTimer.getTotalSeconds(); - mPreviousTime = mCurrentTime; - mStartTime = mCurrentTime; - mVoiceSourceWorldPosition = LLVector3( 0.0f, 0.0f, 0.0f ); - mSpeakingAmplitude = 0.0f; - mCurrentlySpeaking = false; - mVoiceEnabled = false; - mMinGesticulationAmplitude = DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE; - mMaxGesticulationAmplitude = DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE; - mSoundSymbol.mActive = true; - mSoundSymbol.mPosition = LLVector3( 0.0f, 0.0f, 0.0f ); - - mTimer.reset(); - - const char* sound_level_img[] = - { - "voice_meter_dot.j2c", - "voice_meter_rings.j2c", - "voice_meter_rings.j2c", - "voice_meter_rings.j2c", - "voice_meter_rings.j2c", - "voice_meter_rings.j2c", - "voice_meter_rings.j2c" - }; - - for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) - { - mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; - mSoundSymbol.mTexture [i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FALSE, LLViewerTexture::BOOST_UI); - mSoundSymbol.mWaveActive [i] = false; - mSoundSymbol.mWaveOpacity [i] = 1.0f; - mSoundSymbol.mWaveExpansion [i] = 1.0f; - } - - mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); - - // The first instance loads the initial state from prefs. - if (!sPrefsInitialized) - { - setPreferences(); - - // Set up our listener to get updates on all prefs values we care about. - gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); - gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); - gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); - gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); - gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); - gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); - - sPrefsInitialized = true; - } - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m ) -{ - mMinGesticulationAmplitude = m; - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setMaxGesticulationAmplitude( F32 m ) -{ - mMaxGesticulationAmplitude = m; - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setVoiceEnabled( bool v ) -{ - mVoiceEnabled = v; - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setStartSpeaking() -{ - mStartTime = mTimer.getTotalSeconds(); - mCurrentlySpeaking = true; - mSoundSymbol.mActive = true; - -}//--------------------------------------------------- - - -//--------------------------------------------------- -bool LLVoiceVisualizer::getCurrentlySpeaking() -{ - return mCurrentlySpeaking; - -}//--------------------------------------------------- - - -//--------------------------------------------------- -void LLVoiceVisualizer::setStopSpeaking() -{ - mCurrentlySpeaking = false; - mSpeakingAmplitude = 0.0f; - -}//--------------------------------------------------- - - -//--------------------------------------------------- -void LLVoiceVisualizer::setSpeakingAmplitude( F32 a ) -{ - mSpeakingAmplitude = a; - -}//--------------------------------------------------- - - -//--------------------------------------------------- -void LLVoiceVisualizer::setPreferences( ) -{ - sLipSyncEnabled = gSavedSettings.getBOOL("LipSyncEnabled"); - sOohAahRate = gSavedSettings.getF32("LipSyncOohAahRate"); - - std::string oohString = gSavedSettings.getString("LipSyncOoh"); - lipStringToF32s (oohString, sOoh, sOohs); - - std::string aahString = gSavedSettings.getString("LipSyncAah"); - lipStringToF32s (aahString, sAah, sAahs); - - std::string oohPowerString = gSavedSettings.getString("LipSyncOohPowerTransfer"); - lipStringToF32s (oohPowerString, sOohPowerTransfer, sOohPowerTransfers); - sOohPowerTransfersf = (F32) sOohPowerTransfers; - - std::string aahPowerString = gSavedSettings.getString("LipSyncAahPowerTransfer"); - lipStringToF32s (aahPowerString, sAahPowerTransfer, sAahPowerTransfers); - sAahPowerTransfersf = (F32) sAahPowerTransfers; - -}//--------------------------------------------------- - - -//--------------------------------------------------- -// convert a string of digits to an array of floats. -// the result for each digit is the value of the -// digit multiplied by 0.11 -//--------------------------------------------------- -void LLVoiceVisualizer::lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ) -{ - delete[] out_F32s; // get rid of the current array - - count_F32s = in_string.length(); - if (count_F32s == 0) - { - // we don't like zero length arrays - - count_F32s = 1; - out_F32s = new F32[1]; - out_F32s[0] = 0.0f; - } - else - { - out_F32s = new F32[count_F32s]; - - for (U32 i=0; i<count_F32s; i++) - { - // we convert the characters 0 to 9 to their numeric value - // anything else we take the low order four bits with a ceiling of 9 - - U8 digit = in_string[i]; - U8 four_bits = digit % 16; - if (four_bits > 9) - { - four_bits = 9; - } - out_F32s[i] = 0.11f * (F32) four_bits; - } - } - -}//--------------------------------------------------- - - -//-------------------------------------------------------------------------- -// find the amount to blend the ooh and aah mouth morphs -//-------------------------------------------------------------------------- -void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah ) -{ - if( ( sLipSyncEnabled == TRUE ) && mCurrentlySpeaking ) - { - U32 transfer_index = (U32) (sOohPowerTransfersf * mSpeakingAmplitude); - if (transfer_index >= sOohPowerTransfers) - { - transfer_index = sOohPowerTransfers - 1; - } - F32 transfer_ooh = sOohPowerTransfer[transfer_index]; - - transfer_index = (U32) (sAahPowerTransfersf * mSpeakingAmplitude); - if (transfer_index >= sAahPowerTransfers) - { - transfer_index = sAahPowerTransfers - 1; - } - F32 transfer_aah = sAahPowerTransfer[transfer_index]; - - F64 current_time = mTimer.getTotalSeconds(); - F64 elapsed_time = current_time - mStartTime; - U32 elapsed_frames = (U32) (elapsed_time * sOohAahRate); - U32 elapsed_oohs = elapsed_frames % sOohs; - U32 elapsed_aahs = elapsed_frames % sAahs; - - ooh = transfer_ooh * sOoh[elapsed_oohs]; - aah = transfer_aah * sAah[elapsed_aahs]; - - /* - llinfos << " elapsed frames " << elapsed_frames - << " ooh " << ooh - << " aah " << aah - << " transfer ooh" << transfer_ooh - << " transfer aah" << transfer_aah - << " start time " << mStartTime - << " current time " << current_time - << " elapsed time " << elapsed_time - << " elapsed oohs " << elapsed_oohs - << " elapsed aahs " << elapsed_aahs - << llendl; - */ - } - else - { - ooh = 0.0f; - aah = 0.0f; - } - -}//--------------------------------------------------- - - -//--------------------------------------------------- -// this method is inherited from HUD Effect -//--------------------------------------------------- -void LLVoiceVisualizer::render() -{ - if ( ! mVoiceEnabled ) - { - return; - } - - if ( mSoundSymbol.mActive ) - { - mPreviousTime = mCurrentTime; - mCurrentTime = mTimer.getTotalSeconds(); - - //--------------------------------------------------------------- - // set the sound symbol position over the source (avatar's head) - //--------------------------------------------------------------- - mSoundSymbol.mPosition = mVoiceSourceWorldPosition + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD; - - //--------------------------------------------------------------- - // some gl state - //--------------------------------------------------------------- - LLGLSPipelineAlpha alpha_blend; - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - - //------------------------------------------------------------- - // create coordinates of the geometry for the dot - //------------------------------------------------------------- - LLViewerCamera* camera = LLViewerCamera::getInstance(); - LLVector3 l = camera->getLeftAxis() * DOT_SIZE; - LLVector3 u = camera->getUpAxis() * DOT_SIZE; - - LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u; - LLVector3 bottomRight = mSoundSymbol.mPosition - l - u; - LLVector3 topLeft = mSoundSymbol.mPosition + l + u; - LLVector3 topRight = mSoundSymbol.mPosition - l + u; - - //----------------------------- - // bind texture 0 (the dot) - //----------------------------- - gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[0]); - - //------------------------------------------------------------- - // now render the dot - //------------------------------------------------------------- - gGL.color4fv( LLColor4( 1.0f, 1.0f, 1.0f, DOT_OPACITY ).mV ); - - gGL.begin( LLRender::TRIANGLE_STRIP ); - gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV ); - gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); - gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); - gGL.end(); - - gGL.begin( LLRender::TRIANGLE_STRIP ); - gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); - gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV ); - gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); - gGL.end(); - - - - //-------------------------------------------------------------------------------------- - // if currently speaking, trigger waves (1 through 6) based on speaking amplitude - //-------------------------------------------------------------------------------------- - if ( mCurrentlySpeaking ) - { - F32 min = 0.2f; - F32 max = 0.7f; - F32 fraction = ( mSpeakingAmplitude - min ) / ( max - min ); - - // in case mSpeakingAmplitude > max.... - if ( fraction > 1.0f ) - { - fraction = 1.0f; - } - - S32 level = 1 + (int)( fraction * ( NUM_VOICE_SYMBOL_WAVES - 2 ) ); - - for (int i=0; i<level+1; i++) - { - mSoundSymbol.mWaveActive [i] = true; - mSoundSymbol.mWaveOpacity [i] = 1.0f; - mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; - } - - } // if currently speaking - - //--------------------------------------------------- - // determine color - //--------------------------------------------------- - F32 red = 0.0f; - F32 green = 0.0f; - F32 blue = 0.0f; - if ( mSpeakingAmplitude < RED_THRESHOLD ) - { - if ( mSpeakingAmplitude < GREEN_THRESHOLD ) - { - red = BASE_BRIGHTNESS; - green = BASE_BRIGHTNESS; - blue = BASE_BRIGHTNESS; - } - else - { - //--------------------------------------------------- - // fade from gray to bright green - //--------------------------------------------------- - F32 fraction = ( mSpeakingAmplitude - GREEN_THRESHOLD ) / ( 1.0f - GREEN_THRESHOLD ); - red = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS ); - green = BASE_BRIGHTNESS + fraction * ( 1.0f - BASE_BRIGHTNESS ); - blue = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS ); - } - } - else - { - //--------------------------------------------------- - // redish - //--------------------------------------------------- - red = 1.0f; - green = 0.2f; - blue = 0.2f; - } - - for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) - { - if ( mSoundSymbol.mWaveActive[i] ) - { - F32 fadeOutFraction = (F32)( mCurrentTime - mSoundSymbol.mWaveFadeOutStartTime[i] ) / FADE_OUT_DURATION; - - mSoundSymbol.mWaveOpacity[i] = 1.0f - fadeOutFraction; - - if ( mSoundSymbol.mWaveOpacity[i] < 0.0f ) - { - mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; - mSoundSymbol.mWaveOpacity [i] = 0.0f; - mSoundSymbol.mWaveActive [i] = false; - } - - //---------------------------------------------------------------------------------- - // This is where we calculate the expansion of the waves - that is, the - // rate at which they are scaled greater than 1.0 so that they grow over time. - //---------------------------------------------------------------------------------- - F32 timeSlice = (F32)( mCurrentTime - mPreviousTime ); - F32 waveSpeed = mSpeakingAmplitude * WAVE_MOTION_RATE; - mSoundSymbol.mWaveExpansion[i] *= ( 1.0f + EXPANSION_RATE * timeSlice * waveSpeed ); - - if ( mSoundSymbol.mWaveExpansion[i] > EXPANSION_MAX ) - { - mSoundSymbol.mWaveExpansion[i] = 1.0f; - } - - //---------------------------------------------------------------------------------- - // create geometry for the wave billboard textures - //---------------------------------------------------------------------------------- - F32 width = i * WAVE_WIDTH_SCALE * mSoundSymbol.mWaveExpansion[i]; - F32 height = i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i]; - - LLVector3 l = camera->getLeftAxis() * width; - LLVector3 u = camera->getUpAxis() * height; - - LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u; - LLVector3 bottomRight = mSoundSymbol.mPosition - l - u; - LLVector3 topLeft = mSoundSymbol.mPosition + l + u; - LLVector3 topRight = mSoundSymbol.mPosition - l + u; - - gGL.color4fv( LLColor4( red, green, blue, mSoundSymbol.mWaveOpacity[i] ).mV ); - gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[i]); - - - //--------------------------------------------------- - // now, render the mofo - //--------------------------------------------------- - gGL.begin( LLRender::TRIANGLE_STRIP ); - gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV ); - gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); - gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); - gGL.end(); - - gGL.begin( LLRender::TRIANGLE_STRIP ); - gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); - gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV ); - gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); - gGL.end(); - - } //if ( mSoundSymbol.mWaveActive[i] ) - - }// for loop - - }//if ( mSoundSymbol.mActive ) - -}//--------------------------------------------------- - - - - - -//--------------------------------------------------- -void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p ) -{ - mVoiceSourceWorldPosition = p; - -}//--------------------------------------------------- - -//--------------------------------------------------- -VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel() -{ - VoiceGesticulationLevel gesticulationLevel = VOICE_GESTICULATION_LEVEL_OFF; //default - - //----------------------------------------------------------------------------------------- - // Within the range of gesticulation amplitudes, the sound signal is split into - // three equal amplitude regimes, each specifying one of three gesticulation levels. - //----------------------------------------------------------------------------------------- - F32 range = mMaxGesticulationAmplitude - mMinGesticulationAmplitude; - - if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.5f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_HIGH; } - else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.25f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_MEDIUM; } - else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.00000f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_LOW; } - - return gesticulationLevel; - -}//--------------------------------------------------- - - - -//------------------------------------ -// Destructor -//------------------------------------ -LLVoiceVisualizer::~LLVoiceVisualizer() -{ -}//---------------------------------------------- - - -//--------------------------------------------------- -// "packData" is inherited from HUDEffect -//--------------------------------------------------- -void LLVoiceVisualizer::packData(LLMessageSystem *mesgsys) -{ - // Pack the default data - LLHUDEffect::packData(mesgsys); - - // TODO -- pack the relevant data for voice effects - // we'll come up with some cool configurations....TBD - //U8 packed_data[41]; - //mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41); - U8 packed_data = 0; - mesgsys->addBinaryDataFast(_PREHASH_TypeData, &packed_data, 1); -} - - -//--------------------------------------------------- -// "unpackData" is inherited from HUDEffect -//--------------------------------------------------- -void LLVoiceVisualizer::unpackData(LLMessageSystem *mesgsys, S32 blocknum) -{ - // TODO -- find the speaker, unpack binary data, set the properties of this effect - /* - LLHUDEffect::unpackData(mesgsys, blocknum); - LLUUID source_id; - LLUUID target_id; - S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); - if (size != 1) - { - llwarns << "Voice effect with bad size " << size << llendl; - return; - } - mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 1, blocknum); - */ -} - - -//------------------------------------------------------------------ -// this method is inherited from HUD Effect -//------------------------------------------------------------------ -void LLVoiceVisualizer::markDead() -{ - mCurrentlySpeaking = false; - mVoiceEnabled = false; - mSoundSymbol.mActive = false; - - LLHUDEffect::markDead(); -}//------------------------------------------------------------------ - - - - - - - - +/** + * @file llvoicevisualizer.cpp + * @brief Draws in-world speaking indicators. + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//---------------------------------------------------------------------- +// Voice Visualizer +// author: JJ Ventrella +// (information about this stuff can be found in "llvoicevisualizer.h") +//---------------------------------------------------------------------- +#include "llviewerprecompiledheaders.h" +#include "llviewercontrol.h" +#include "llglheaders.h" +#include "llsphere.h" +#include "llvoicevisualizer.h" +#include "llviewercamera.h" +#include "llviewerobject.h" +#include "llviewertexture.h" +#include "llviewertexturelist.h" +#include "llvoiceclient.h" +#include "llrender.h" + +//brent's wave image +//29de489d-0491-fb00-7dab-f9e686d31e83 + + +#ifdef XXX_STINSON_CHUI_REWORK +//-------------------------------------------------------------------------------------- +// sound symbol constants +//-------------------------------------------------------------------------------------- +const F32 HEIGHT_ABOVE_HEAD = 0.3f; // how many meters vertically above the av's head the voice symbol will appear +const F32 RED_THRESHOLD = LLVoiceClient::OVERDRIVEN_POWER_LEVEL; // value above which speaking amplitude causes the voice symbol to turn red +const F32 GREEN_THRESHOLD = 0.2f; // value above which speaking amplitude causes the voice symbol to turn green +const F32 FADE_OUT_DURATION = 0.4f; // how many seconds it takes for a pair of waves to fade away +const F32 EXPANSION_RATE = 1.0f; // how many seconds it takes for the waves to expand to twice their original size +const F32 EXPANSION_MAX = 1.5f; // maximum size scale to which the waves can expand before popping back to 1.0 +const F32 WAVE_WIDTH_SCALE = 0.03f; // base width of the waves +const F32 WAVE_HEIGHT_SCALE = 0.02f; // base height of the waves +const F32 BASE_BRIGHTNESS = 0.7f; // gray level of the voice indicator when quiet (below green threshold) +const F32 DOT_SIZE = 0.05f; // size of the dot billboard texture +const F32 DOT_OPACITY = 0.7f; // how opaque the dot is +const F32 WAVE_MOTION_RATE = 1.5f; // scalar applied to consecutive waves as a function of speaking amplitude +#endif // XXX_STINSON_CHUI_REWORK + +//-------------------------------------------------------------------------------------- +// gesticulation constants +//-------------------------------------------------------------------------------------- +const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE = 0.2f; +const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE = 1.0f; + +#ifdef XXX_STINSON_CHUI_REWORK +//-------------------------------------------------------------------------------------- +// other constants +//-------------------------------------------------------------------------------------- +const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code. +const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL +#endif // XXX_STINSON_CHUI_REWORK + +//------------------------------------------------------------------ +// Initialize the statics +//------------------------------------------------------------------ +bool LLVoiceVisualizer::sPrefsInitialized = false; +BOOL LLVoiceVisualizer::sLipSyncEnabled = FALSE; +F32* LLVoiceVisualizer::sOoh = NULL; +F32* LLVoiceVisualizer::sAah = NULL; +U32 LLVoiceVisualizer::sOohs = 0; +U32 LLVoiceVisualizer::sAahs = 0; +F32 LLVoiceVisualizer::sOohAahRate = 0.0f; +F32* LLVoiceVisualizer::sOohPowerTransfer = NULL; +U32 LLVoiceVisualizer::sOohPowerTransfers = 0; +F32 LLVoiceVisualizer::sOohPowerTransfersf = 0.0f; +F32* LLVoiceVisualizer::sAahPowerTransfer = NULL; +U32 LLVoiceVisualizer::sAahPowerTransfers = 0; +F32 LLVoiceVisualizer::sAahPowerTransfersf = 0.0f; + + +//----------------------------------------------- +// constructor +//----------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK +LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) +#else // XXX_STINSON_CHUI_REWORK +LLVoiceVisualizer::LLVoiceVisualizer() + : LLRefCount(), + mTimer(), + mStartTime(0.0), + mCurrentlySpeaking(false), + mSpeakingAmplitude(0.0f), + mMaxGesticulationAmplitude(DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE), + mMinGesticulationAmplitude(DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE) +#endif // XXX_STINSON_CHUI_REWORK +{ +#ifdef XXX_STINSON_CHUI_REWORK + mCurrentTime = mTimer.getTotalSeconds(); + mPreviousTime = mCurrentTime; + mStartTime = mCurrentTime; +#else // XXX_STINSON_CHUI_REWORK + mStartTime = mTimer.getTotalSeconds(); +#endif // XXX_STINSON_CHUI_REWORK +#ifdef XXX_STINSON_CHUI_REWORK + mVoiceSourceWorldPosition = LLVector3( 0.0f, 0.0f, 0.0f ); + mSpeakingAmplitude = 0.0f; + mCurrentlySpeaking = false; + mVoiceEnabled = false; + mMinGesticulationAmplitude = DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE; + mMaxGesticulationAmplitude = DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE; + mSoundSymbol.mActive = true; + mSoundSymbol.mPosition = LLVector3( 0.0f, 0.0f, 0.0f ); +#endif // XXX_STINSON_CHUI_REWORK + + mTimer.reset(); + +#ifdef XXX_STINSON_CHUI_REWORK + const char* sound_level_img[] = + { + "voice_meter_dot.j2c", + "voice_meter_rings.j2c", + "voice_meter_rings.j2c", + "voice_meter_rings.j2c", + "voice_meter_rings.j2c", + "voice_meter_rings.j2c", + "voice_meter_rings.j2c" + }; + + for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) + { + mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; + mSoundSymbol.mTexture [i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FALSE, LLViewerTexture::BOOST_UI); + mSoundSymbol.mWaveActive [i] = false; + mSoundSymbol.mWaveOpacity [i] = 1.0f; + mSoundSymbol.mWaveExpansion [i] = 1.0f; + } + + mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); +#endif // XXX_STINSON_CHUI_REWORK + + // The first instance loads the initial state from prefs. + if (!sPrefsInitialized) + { + setPreferences(); + + // Set up our listener to get updates on all prefs values we care about. + gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); + gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); + gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); + gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); + gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); + gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); + + sPrefsInitialized = true; + } + +}//--------------------------------------------------- + +#ifdef XXX_STINSON_CHUI_REWORK +//--------------------------------------------------- +void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m ) +{ + mMinGesticulationAmplitude = m; + +}//--------------------------------------------------- + +//--------------------------------------------------- +void LLVoiceVisualizer::setMaxGesticulationAmplitude( F32 m ) +{ + mMaxGesticulationAmplitude = m; + +}//--------------------------------------------------- + +//--------------------------------------------------- +void LLVoiceVisualizer::setVoiceEnabled( bool v ) +{ + mVoiceEnabled = v; + +}//--------------------------------------------------- +#endif // XXX_STINSON_CHUI_REWORK + +//--------------------------------------------------- +void LLVoiceVisualizer::setStartSpeaking() +{ + mStartTime = mTimer.getTotalSeconds(); + mCurrentlySpeaking = true; +#ifdef XXX_STINSON_CHUI_REWORK + mSoundSymbol.mActive = true; +#endif // XXX_STINSON_CHUI_REWORK + +}//--------------------------------------------------- + + +//--------------------------------------------------- +bool LLVoiceVisualizer::getCurrentlySpeaking() +{ + return mCurrentlySpeaking; + +}//--------------------------------------------------- + + +//--------------------------------------------------- +void LLVoiceVisualizer::setStopSpeaking() +{ + mCurrentlySpeaking = false; + mSpeakingAmplitude = 0.0f; + +}//--------------------------------------------------- + + +//--------------------------------------------------- +void LLVoiceVisualizer::setSpeakingAmplitude( F32 a ) +{ + mSpeakingAmplitude = a; + +}//--------------------------------------------------- + +//------------------------------------------------------------------ +// handles parameter updates +//------------------------------------------------------------------ +bool LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged(const LLSD& newvalue) +{ + // Note: Ignore the specific event value, we look up the ones we want + LLVoiceVisualizer::setPreferences(); + return true; +} + +//--------------------------------------------------- +void LLVoiceVisualizer::setPreferences( ) +{ + sLipSyncEnabled = gSavedSettings.getBOOL("LipSyncEnabled"); + sOohAahRate = gSavedSettings.getF32("LipSyncOohAahRate"); + + std::string oohString = gSavedSettings.getString("LipSyncOoh"); + lipStringToF32s (oohString, sOoh, sOohs); + + std::string aahString = gSavedSettings.getString("LipSyncAah"); + lipStringToF32s (aahString, sAah, sAahs); + + std::string oohPowerString = gSavedSettings.getString("LipSyncOohPowerTransfer"); + lipStringToF32s (oohPowerString, sOohPowerTransfer, sOohPowerTransfers); + sOohPowerTransfersf = (F32) sOohPowerTransfers; + + std::string aahPowerString = gSavedSettings.getString("LipSyncAahPowerTransfer"); + lipStringToF32s (aahPowerString, sAahPowerTransfer, sAahPowerTransfers); + sAahPowerTransfersf = (F32) sAahPowerTransfers; + +}//--------------------------------------------------- + + +//--------------------------------------------------- +// convert a string of digits to an array of floats. +// the result for each digit is the value of the +// digit multiplied by 0.11 +//--------------------------------------------------- +void LLVoiceVisualizer::lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ) +{ + delete[] out_F32s; // get rid of the current array + + count_F32s = in_string.length(); + if (count_F32s == 0) + { + // we don't like zero length arrays + + count_F32s = 1; + out_F32s = new F32[1]; + out_F32s[0] = 0.0f; + } + else + { + out_F32s = new F32[count_F32s]; + + for (U32 i=0; i<count_F32s; i++) + { + // we convert the characters 0 to 9 to their numeric value + // anything else we take the low order four bits with a ceiling of 9 + + U8 digit = in_string[i]; + U8 four_bits = digit % 16; + if (four_bits > 9) + { + four_bits = 9; + } + out_F32s[i] = 0.11f * (F32) four_bits; + } + } + +}//--------------------------------------------------- + + +//-------------------------------------------------------------------------- +// find the amount to blend the ooh and aah mouth morphs +//-------------------------------------------------------------------------- +void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah ) +{ + if( ( sLipSyncEnabled == TRUE ) && mCurrentlySpeaking ) + { + U32 transfer_index = (U32) (sOohPowerTransfersf * mSpeakingAmplitude); + if (transfer_index >= sOohPowerTransfers) + { + transfer_index = sOohPowerTransfers - 1; + } + F32 transfer_ooh = sOohPowerTransfer[transfer_index]; + + transfer_index = (U32) (sAahPowerTransfersf * mSpeakingAmplitude); + if (transfer_index >= sAahPowerTransfers) + { + transfer_index = sAahPowerTransfers - 1; + } + F32 transfer_aah = sAahPowerTransfer[transfer_index]; + + F64 current_time = mTimer.getTotalSeconds(); + F64 elapsed_time = current_time - mStartTime; + U32 elapsed_frames = (U32) (elapsed_time * sOohAahRate); + U32 elapsed_oohs = elapsed_frames % sOohs; + U32 elapsed_aahs = elapsed_frames % sAahs; + + ooh = transfer_ooh * sOoh[elapsed_oohs]; + aah = transfer_aah * sAah[elapsed_aahs]; + + /* + llinfos << " elapsed frames " << elapsed_frames + << " ooh " << ooh + << " aah " << aah + << " transfer ooh" << transfer_ooh + << " transfer aah" << transfer_aah + << " start time " << mStartTime + << " current time " << current_time + << " elapsed time " << elapsed_time + << " elapsed oohs " << elapsed_oohs + << " elapsed aahs " << elapsed_aahs + << llendl; + */ + } + else + { + ooh = 0.0f; + aah = 0.0f; + } + +}//--------------------------------------------------- + + +#ifdef XXX_STINSON_CHUI_REWORK +//--------------------------------------------------- +// this method is inherited from HUD Effect +//--------------------------------------------------- +void LLVoiceVisualizer::render() +{ + if ( ! mVoiceEnabled ) + { + return; + } + + if ( mSoundSymbol.mActive ) + { + mPreviousTime = mCurrentTime; + mCurrentTime = mTimer.getTotalSeconds(); + + //--------------------------------------------------------------- + // set the sound symbol position over the source (avatar's head) + //--------------------------------------------------------------- + mSoundSymbol.mPosition = mVoiceSourceWorldPosition + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD; + + //--------------------------------------------------------------- + // some gl state + //--------------------------------------------------------------- + LLGLSPipelineAlpha alpha_blend; + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + + //------------------------------------------------------------- + // create coordinates of the geometry for the dot + //------------------------------------------------------------- + LLViewerCamera* camera = LLViewerCamera::getInstance(); + LLVector3 l = camera->getLeftAxis() * DOT_SIZE; + LLVector3 u = camera->getUpAxis() * DOT_SIZE; + + LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u; + LLVector3 bottomRight = mSoundSymbol.mPosition - l - u; + LLVector3 topLeft = mSoundSymbol.mPosition + l + u; + LLVector3 topRight = mSoundSymbol.mPosition - l + u; + + //----------------------------- + // bind texture 0 (the dot) + //----------------------------- + gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[0]); + + //------------------------------------------------------------- + // now render the dot + //------------------------------------------------------------- + gGL.color4fv( LLColor4( 1.0f, 1.0f, 1.0f, DOT_OPACITY ).mV ); + + gGL.begin( LLRender::TRIANGLE_STRIP ); + gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV ); + gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); + gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); + gGL.end(); + + gGL.begin( LLRender::TRIANGLE_STRIP ); + gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); + gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV ); + gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); + gGL.end(); + + + + //-------------------------------------------------------------------------------------- + // if currently speaking, trigger waves (1 through 6) based on speaking amplitude + //-------------------------------------------------------------------------------------- + if ( mCurrentlySpeaking ) + { + F32 min = 0.2f; + F32 max = 0.7f; + F32 fraction = ( mSpeakingAmplitude - min ) / ( max - min ); + + // in case mSpeakingAmplitude > max.... + if ( fraction > 1.0f ) + { + fraction = 1.0f; + } + + S32 level = 1 + (int)( fraction * ( NUM_VOICE_SYMBOL_WAVES - 2 ) ); + + for (int i=0; i<level+1; i++) + { + mSoundSymbol.mWaveActive [i] = true; + mSoundSymbol.mWaveOpacity [i] = 1.0f; + mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; + } + + } // if currently speaking + + //--------------------------------------------------- + // determine color + //--------------------------------------------------- + F32 red = 0.0f; + F32 green = 0.0f; + F32 blue = 0.0f; + if ( mSpeakingAmplitude < RED_THRESHOLD ) + { + if ( mSpeakingAmplitude < GREEN_THRESHOLD ) + { + red = BASE_BRIGHTNESS; + green = BASE_BRIGHTNESS; + blue = BASE_BRIGHTNESS; + } + else + { + //--------------------------------------------------- + // fade from gray to bright green + //--------------------------------------------------- + F32 fraction = ( mSpeakingAmplitude - GREEN_THRESHOLD ) / ( 1.0f - GREEN_THRESHOLD ); + red = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS ); + green = BASE_BRIGHTNESS + fraction * ( 1.0f - BASE_BRIGHTNESS ); + blue = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS ); + } + } + else + { + //--------------------------------------------------- + // redish + //--------------------------------------------------- + red = 1.0f; + green = 0.2f; + blue = 0.2f; + } + + for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) + { + if ( mSoundSymbol.mWaveActive[i] ) + { + F32 fadeOutFraction = (F32)( mCurrentTime - mSoundSymbol.mWaveFadeOutStartTime[i] ) / FADE_OUT_DURATION; + + mSoundSymbol.mWaveOpacity[i] = 1.0f - fadeOutFraction; + + if ( mSoundSymbol.mWaveOpacity[i] < 0.0f ) + { + mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; + mSoundSymbol.mWaveOpacity [i] = 0.0f; + mSoundSymbol.mWaveActive [i] = false; + } + + //---------------------------------------------------------------------------------- + // This is where we calculate the expansion of the waves - that is, the + // rate at which they are scaled greater than 1.0 so that they grow over time. + //---------------------------------------------------------------------------------- + F32 timeSlice = (F32)( mCurrentTime - mPreviousTime ); + F32 waveSpeed = mSpeakingAmplitude * WAVE_MOTION_RATE; + mSoundSymbol.mWaveExpansion[i] *= ( 1.0f + EXPANSION_RATE * timeSlice * waveSpeed ); + + if ( mSoundSymbol.mWaveExpansion[i] > EXPANSION_MAX ) + { + mSoundSymbol.mWaveExpansion[i] = 1.0f; + } + + //---------------------------------------------------------------------------------- + // create geometry for the wave billboard textures + //---------------------------------------------------------------------------------- + F32 width = i * WAVE_WIDTH_SCALE * mSoundSymbol.mWaveExpansion[i]; + F32 height = i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i]; + + LLVector3 l = camera->getLeftAxis() * width; + LLVector3 u = camera->getUpAxis() * height; + + LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u; + LLVector3 bottomRight = mSoundSymbol.mPosition - l - u; + LLVector3 topLeft = mSoundSymbol.mPosition + l + u; + LLVector3 topRight = mSoundSymbol.mPosition - l + u; + + gGL.color4fv( LLColor4( red, green, blue, mSoundSymbol.mWaveOpacity[i] ).mV ); + gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[i]); + + + //--------------------------------------------------- + // now, render the mofo + //--------------------------------------------------- + gGL.begin( LLRender::TRIANGLE_STRIP ); + gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV ); + gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); + gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); + gGL.end(); + + gGL.begin( LLRender::TRIANGLE_STRIP ); + gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); + gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV ); + gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); + gGL.end(); + + } //if ( mSoundSymbol.mWaveActive[i] ) + + }// for loop + + }//if ( mSoundSymbol.mActive ) + +}//--------------------------------------------------- + +//--------------------------------------------------- +void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p ) +{ + mVoiceSourceWorldPosition = p; + +}//--------------------------------------------------- +#endif // XXX_STINSON_CHUI_REWORK + +//--------------------------------------------------- +VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel() +{ + VoiceGesticulationLevel gesticulationLevel = VOICE_GESTICULATION_LEVEL_OFF; //default + + //----------------------------------------------------------------------------------------- + // Within the range of gesticulation amplitudes, the sound signal is split into + // three equal amplitude regimes, each specifying one of three gesticulation levels. + //----------------------------------------------------------------------------------------- + F32 range = mMaxGesticulationAmplitude - mMinGesticulationAmplitude; + + if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.5f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_HIGH; } + else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.25f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_MEDIUM; } + else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.00000f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_LOW; } + + return gesticulationLevel; + +}//--------------------------------------------------- + + + +//------------------------------------ +// Destructor +//------------------------------------ +LLVoiceVisualizer::~LLVoiceVisualizer() +{ +}//---------------------------------------------- + + +#ifdef XXX_STINSON_CHUI_REWORK +//--------------------------------------------------- +// "packData" is inherited from HUDEffect +//--------------------------------------------------- +void LLVoiceVisualizer::packData(LLMessageSystem *mesgsys) +{ + // Pack the default data + LLHUDEffect::packData(mesgsys); + + // TODO -- pack the relevant data for voice effects + // we'll come up with some cool configurations....TBD + //U8 packed_data[41]; + //mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41); + U8 packed_data = 0; + mesgsys->addBinaryDataFast(_PREHASH_TypeData, &packed_data, 1); +} + + +//--------------------------------------------------- +// "unpackData" is inherited from HUDEffect +//--------------------------------------------------- +void LLVoiceVisualizer::unpackData(LLMessageSystem *mesgsys, S32 blocknum) +{ + // TODO -- find the speaker, unpack binary data, set the properties of this effect + /* + LLHUDEffect::unpackData(mesgsys, blocknum); + LLUUID source_id; + LLUUID target_id; + S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); + if (size != 1) + { + llwarns << "Voice effect with bad size " << size << llendl; + return; + } + mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 1, blocknum); + */ +} + + +//------------------------------------------------------------------ +// this method is inherited from HUD Effect +//------------------------------------------------------------------ +void LLVoiceVisualizer::markDead() +{ + mCurrentlySpeaking = false; + mVoiceEnabled = false; + mSoundSymbol.mActive = false; + + LLHUDEffect::markDead(); +}//------------------------------------------------------------------ + +#endif // XXX_STINSON_CHUI_REWORK diff --git a/indra/newview/llvoicevisualizer.h b/indra/newview/llvoicevisualizer.h index e434c7f3f1..6258de163d 100644 --- a/indra/newview/llvoicevisualizer.h +++ b/indra/newview/llvoicevisualizer.h @@ -42,7 +42,11 @@ #ifndef LL_VOICE_VISUALIZER_H #define LL_VOICE_VISUALIZER_H +#ifdef XXX_STINSON_CHUI_REWORK #include "llhudeffect.h" +#else // XXX_STINSON_CHUI_REWORK +#include "llpointer.h" +#endif // XXX_STINSON_CHUI_REWORK //----------------------------------------------------------------------------------------------- // The values of voice gesticulation represent energy levels for avatar animation, based on @@ -60,34 +64,45 @@ enum VoiceGesticulationLevel NUM_VOICE_GESTICULATION_LEVELS }; +#ifdef XXX_STINSON_CHUI_REWORK const static int NUM_VOICE_SYMBOL_WAVES = 7; +#endif // XXX_STINSON_CHUI_REWORK //---------------------------------------------------- // LLVoiceVisualizer class //---------------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK class LLVoiceVisualizer : public LLHUDEffect +#else // XXX_STINSON_CHUI_REWORK +class LLVoiceVisualizer : public LLRefCount +#endif // XXX_STINSON_CHUI_REWORK { //--------------------------------------------------- // public methods //--------------------------------------------------- public: - LLVoiceVisualizer ( const U8 type ); //constructor +#ifdef XXX_STINSON_CHUI_REWORK + LLVoiceVisualizer( const U8 type ); //constructor +#else // XXX_STINSON_CHUI_REWORK + LLVoiceVisualizer(); //constructor +#endif // XXX_STINSON_CHUI_REWORK ~LLVoiceVisualizer(); //destructor - - friend class LLHUDObject; +#ifdef XXX_STINSON_CHUI_REWORK void setVoiceSourceWorldPosition( const LLVector3 &p ); // this should be the position of the speaking avatar's head void setMinGesticulationAmplitude( F32 ); // the lower range of meaningful amplitude for setting gesticulation level void setMaxGesticulationAmplitude( F32 ); // the upper range of meaningful amplitude for setting gesticulation level +#endif // XXX_STINSON_CHUI_REWORK void setStartSpeaking(); // tell me when the av starts speaking +#ifdef XXX_STINSON_CHUI_REWORK void setVoiceEnabled( bool ); // tell me whether or not the user is voice enabled +#endif // XXX_STINSON_CHUI_REWORK void setSpeakingAmplitude( F32 ); // tell me how loud the av is speaking (ranges from 0 to 1) void setStopSpeaking(); // tell me when the av stops speaking bool getCurrentlySpeaking(); // the get for the above set VoiceGesticulationLevel getCurrentGesticulationLevel(); // based on voice amplitude, I'll give you the current "energy level" of avatar speech - static void setPreferences( ); - static void lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ); // convert a string of digits to an array of floats void lipSyncOohAah( F32& ooh, F32& aah ); +#ifdef XXX_STINSON_CHUI_REWORK void render(); // inherited from HUD Effect void packData(LLMessageSystem *mesgsys); // inherited from HUD Effect void unpackData(LLMessageSystem *mesgsys, S32 blocknum); // inherited from HUD Effect @@ -103,12 +118,17 @@ class LLVoiceVisualizer : public LLHUDEffect //---------------------------------------------------------------------------------------------- void setMaxGesticulationAmplitude(); void setMinGesticulationAmplitude(); +#endif // XXX_STINSON_CHUI_REWORK //--------------------------------------------------- // private members //--------------------------------------------------- private: - + static bool handleVoiceVisualizerPrefsChanged(const LLSD& newvalue); + static void setPreferences( ); + static void lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ); // convert a string of digits to an array of floats + +#ifdef XXX_STINSON_CHUI_REWORK struct SoundSymbol { F32 mWaveExpansion [ NUM_VOICE_SYMBOL_WAVES ]; @@ -119,15 +139,20 @@ class LLVoiceVisualizer : public LLHUDEffect bool mActive; LLVector3 mPosition; }; +#endif // XXX_STINSON_CHUI_REWORK LLFrameTimer mTimer; // so I can ask the current time in seconds F64 mStartTime; // time in seconds when speaking started +#ifdef XXX_STINSON_CHUI_REWORK F64 mCurrentTime; // current time in seconds, captured every step F64 mPreviousTime; // copy of "current time" from last frame SoundSymbol mSoundSymbol; // the sound symbol that appears over the avatar's head bool mVoiceEnabled; // if off, no rendering should happen +#endif // XXX_STINSON_CHUI_REWORK bool mCurrentlySpeaking; // is the user currently speaking? +#ifdef XXX_STINSON_CHUI_REWORK LLVector3 mVoiceSourceWorldPosition; // give this to me every step - I need it to update the sound symbol +#endif // XXX_STINSON_CHUI_REWORK F32 mSpeakingAmplitude; // this should be set as often as possible when the user is speaking F32 mMaxGesticulationAmplitude; // this is the upper-limit of the envelope of detectable gesticulation leves F32 mMinGesticulationAmplitude; // this is the lower-limit of the envelope of detectable gesticulation leves -- cgit v1.2.3 From 42b5dfda161a1e6b92990cd5206bca5ff5b95ab6 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 17 Apr 2012 17:13:48 -0700 Subject: CHUI-86 WIP Investigate voice-dot with name tag integration fixed bad parameters in draw3d...name tags should display properly now --- indra/llui/lluiimage.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp index a4886dabb0..9ed98f941f 100644 --- a/indra/llui/lluiimage.cpp +++ b/indra/llui/lluiimage.cpp @@ -145,10 +145,10 @@ void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, c mClipRegion.mBottom + mScaleRegion.mBottom * mClipRegion.getHeight()); gl_segmented_rect_3d_tex(mClipRegion, center_uv_rect, - LLRectf(border_width * border_scale * 0.5f, - 1.f - (border_height * border_scale * 0.5f), - 1.f - (border_width * border_scale * 0.5f), - border_height * border_scale * 0.5f), + LLRectf(border_width * border_scale * 0.5f / (F32)rect.getWidth(), + (rect.getHeight() - (border_height * border_scale * 0.5f)) / (F32)rect.getHeight(), + (rect.getWidth() - (border_width * border_scale * 0.5f)) / (F32)rect.getWidth(), + (border_height * border_scale * 0.5f) / (F32)rect.getHeight()), rect.getWidth() * x_axis, rect.getHeight() * y_axis); -- cgit v1.2.3 From 4be3ec7234c82f1e2b33d3eb30d5b6cc1eb890ba Mon Sep 17 00:00:00 2001 From: Todd Stinson <stinson@lindenlab.com> Date: Tue, 17 Apr 2012 17:14:37 -0700 Subject: BUILDFIX: Attempting to correct a linux build problem. --- indra/newview/llhudnametag.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 26c3ee8c7a..423a6f8c07 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -321,7 +321,7 @@ void LLHUDNameTag::renderText(BOOL for_select) LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLRect screen_rect; - screen_rect.setCenterAndSize(0, -mHeight / 2 + mOffsetY, mWidth, mHeight); + screen_rect.setCenterAndSize(0, static_cast<S32>(lltrunc(-mHeight / 2 + mOffsetY)), static_cast<S32>(lltrunc(mWidth)), static_cast<S32>(lltrunc(mHeight))); imagep->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color); if (mLabelSegments.size()) { -- cgit v1.2.3 From 448ae4ec9b2351d47253a5fc5c3df47694da8b4b Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 17 Apr 2012 17:18:48 -0700 Subject: CHUI-86 WIP Investigate voice-dot with name tag integration removed dead code --- indra/newview/llhudnametag.cpp | 49 ------------------------------------------ 1 file changed, 49 deletions(-) (limited to 'indra') diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 26c3ee8c7a..d5d31ba30e 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -276,24 +276,6 @@ void LLHUDNameTag::renderText(BOOL for_select) LLColor4 bg_color = LLUIColorTable::instance().getColor("NameTagBackground"); bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); - // maybe a no-op? - //const S32 border_height = 16; - //const S32 border_width = 16; - const S32 border_height = 8; - const S32 border_width = 8; - - // *TODO move this into helper function - F32 border_scale = 1.f; - - if (border_height * 2 > mHeight) - { - border_scale = (F32)mHeight / ((F32)border_height * 2.f); - } - if (border_width * 2 > mWidth) - { - border_scale = llmin(border_scale, (F32)mWidth / ((F32)border_width * 2.f)); - } - // scale screen size of borders down //RN: for now, text on hud objects is never occluded @@ -302,11 +284,8 @@ void LLHUDNameTag::renderText(BOOL for_select) LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec); - LLVector2 border_scale_vec((F32)border_width / (F32)imagep->getTextureWidth(), (F32)border_height / (F32)imagep->getTextureHeight()); LLVector3 width_vec = mWidth * x_pixel_vec; LLVector3 height_vec = mHeight * y_pixel_vec; - LLVector3 scaled_border_width = (F32)llfloor(border_scale * (F32)border_width) * x_pixel_vec; - LLVector3 scaled_border_height = (F32)llfloor(border_scale * (F32)border_height) * y_pixel_vec; mRadius = (width_vec + height_vec).magVec() * 0.5f; @@ -333,35 +312,7 @@ void LLHUDNameTag::renderText(BOOL for_select) label_top_color.mV[VALPHA] = gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor; rect_top_image->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color); - } - //LLUI::pushMatrix(); - //{ - // LLVector3 bg_pos = render_position - // + (F32)mOffsetY * y_pixel_vec - // - (width_vec / 2.f) - // - (height_vec); - // LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); - - // gGL.getTexUnit(0)->bind(imagep->getImage()); - // - // gGL.color4fv(bg_color.mV); - // gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); - // - // if ( mLabelSegments.size()) - // { - // LLUI::pushMatrix(); - // { - // gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); - // LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; - // LLVector3 label_offset = height_vec - label_height; - // LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); - // gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); - // } - // LLUI::popMatrix(); - // } - //} - //LLUI::popMatrix(); F32 y_offset = (F32)mOffsetY; -- cgit v1.2.3 From 05600db8968d05e816cd637e99d821961802cbc0 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 18 Apr 2012 17:27:28 -0700 Subject: converted to unix line endings --- indra/newview/llhudobject.cpp | 10 +++++----- indra/newview/llhudobject.h | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp index 06b0c3c6c8..0960846510 100644 --- a/indra/newview/llhudobject.cpp +++ b/indra/newview/llhudobject.cpp @@ -232,11 +232,11 @@ LLHUDEffect *LLHUDObject::addHUDEffect(const U8 type) case LL_HUD_EFFECT_LOOKAT: hud_objectp = new LLHUDEffectLookAt(type); break; -#ifdef XXX_STINSON_CHUI_REWORK - case LL_HUD_EFFECT_VOICE_VISUALIZER: - hud_objectp = new LLVoiceVisualizer(type); - break; -#endif // XXX_STINSON_CHUI_REWORK +#ifdef XXX_STINSON_CHUI_REWORK + case LL_HUD_EFFECT_VOICE_VISUALIZER: + hud_objectp = new LLVoiceVisualizer(type); + break; +#endif // XXX_STINSON_CHUI_REWORK case LL_HUD_EFFECT_POINTAT: hud_objectp = new LLHUDEffectPointAt(type); break; diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h index 6f8be41177..21cf5fe17c 100644 --- a/indra/newview/llhudobject.h +++ b/indra/newview/llhudobject.h @@ -94,9 +94,9 @@ public: LL_HUD_EFFECT_EDIT, LL_HUD_EFFECT_LOOKAT, LL_HUD_EFFECT_POINTAT, -#ifdef XXX_STINSON_CHUI_REWORK - LL_HUD_EFFECT_VOICE_VISUALIZER, // Ventrella -#endif // XXX_STINSON_CHUI_REWORK +#ifdef XXX_STINSON_CHUI_REWORK + LL_HUD_EFFECT_VOICE_VISUALIZER, // Ventrella +#endif // XXX_STINSON_CHUI_REWORK LL_HUD_NAME_TAG, LL_HUD_EFFECT_BLOB }; -- cgit v1.2.3 From 23f7db3ceeadd9729f437ee12996e86d3a0bcff0 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 20 Apr 2012 13:52:49 -0700 Subject: allow nested modifier tags (e.g. Lazy, Atomic) in param block entries --- indra/llxuixml/llinitparam.h | 273 ++++++++++++++++++++++++-------------- indra/llxuixml/llxuiparser.cpp | 33 ++--- indra/newview/llpreviewscript.cpp | 6 +- 3 files changed, 193 insertions(+), 119 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index afb6868c4b..5222d4c713 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -36,6 +36,71 @@ #include "llerror.h" +namespace LLTypeTags +{ + template <typename INNER_TYPE, int _SORT_ORDER> + struct TypeTagBase + { + typedef void is_tag_t; + typedef INNER_TYPE inner_t; + static const int SORT_ORDER=_SORT_ORDER; + }; + + template <int VAL1, int VAL2> + struct GreaterThan + { + static const bool value = VAL1 > VAL2; + }; + + template<typename ITEM, typename REST, bool NEEDS_SWAP = GreaterThan<ITEM::SORT_ORDER, REST::SORT_ORDER>::value > + struct Swap + { + typedef typename ITEM::Cons<REST>::value_t value_t; + }; + + template<typename ITEM, typename REST> + struct Swap<ITEM, REST, true> + { + typedef typename REST::Cons<Swap<ITEM, typename REST::inner_t>::value_t>::value_t value_t; + }; + + template<typename T, typename SORTABLE = void> + struct IsSortable + { + static const bool value = false; + }; + + template<typename T> + struct IsSortable<T, typename T::is_tag_t> + { + static const bool value = true; + }; + + template<typename ITEM, typename REST, bool IS_REST_SORTABLE = IsSortable<REST>::value> + struct InsertInto + { + typedef typename ITEM::Cons<REST>::value_t value_t; + }; + + template<typename ITEM, typename REST> + struct InsertInto <ITEM, REST, true> + { + typedef typename Swap<ITEM, REST>::value_t value_t; + }; + + template<typename T, bool SORTABLE = IsSortable<T>::value> + struct Sorted + { + typedef T value_t; + }; + + template<typename T> + struct Sorted <T, true> + { + typedef typename InsertInto<T, typename Sorted<typename T::inner_t>::value_t>::value_t value_t; + }; +} + namespace LLInitParam { // used to indicate no matching value to a given name when parsing @@ -100,7 +165,7 @@ namespace LLInitParam // by holding on to a copy (scalar params) // or deriving from it (blocks) // has specializations for custom value behavior - // and "tagged" values like Lazy and Atomic + // and "tag" values like Lazy and Atomic template<typename T, typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t> class ParamValue { @@ -134,7 +199,7 @@ namespace LLInitParam template<typename T> class ParamValue<T, IS_A_BLOCK> - : public T + : public T { typedef ParamValue<T, IS_A_BLOCK> self_t; public: @@ -175,7 +240,7 @@ namespace LLInitParam // leverages empty base class optimization template <typename T> class TypeValues - : public ParamValue<T> + : public ParamValue<typename LLTypeTags::Sorted<T>::value_t> { private: struct Inaccessable{}; @@ -183,10 +248,11 @@ namespace LLInitParam typedef std::map<std::string, T> value_name_map_t; typedef Inaccessable name_t; typedef TypeValues<T> type_value_t; - typedef typename ParamValue<T>::value_t value_t; + typedef typename ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; + typedef typename param_value_t::value_t value_t; - TypeValues(const value_t& val) - : ParamValue<T>(val) + TypeValues(const typename param_value_t::value_t& val) + : param_value_t(val) {} void setValueName(const std::string& key) {} @@ -214,12 +280,12 @@ namespace LLInitParam operator const value_t&() const { - return ParamValue<T>::getValue(); + return param_value_t::getValue(); } const value_t& operator()() const { - return ParamValue<T>::getValue(); + return param_value_t::getValue(); } static value_name_map_t* getValueNames() {return NULL;} @@ -229,17 +295,18 @@ namespace LLInitParam // and caching of last used name template <typename T, typename DERIVED_TYPE = TypeValues<T>, bool IS_SPECIALIZED = true > class TypeValuesHelper - : public ParamValue<T> + : public ParamValue<typename LLTypeTags::Sorted<T>::value_t> { typedef TypeValuesHelper<T, DERIVED_TYPE, IS_SPECIALIZED> self_t; public: typedef typename std::map<std::string, T> value_name_map_t; typedef std::string name_t; typedef self_t type_value_t; - typedef typename ParamValue<T>::value_t value_t; + typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; + typedef typename param_value_t::value_t value_t; - TypeValuesHelper(const value_t& val) - : ParamValue<T>(val) + TypeValuesHelper(const typename param_value_t::value_t& val) + : param_value_t(val) {} //TODO: cache key by index to save on param block size @@ -328,7 +395,7 @@ namespace LLInitParam void assignNamedValue(const std::string& name) { - if (getValueFromName(name, ParamValue<T>::getValue())) + if (getValueFromName(name, param_value_t::getValue())) { setValueName(name); } @@ -336,12 +403,12 @@ namespace LLInitParam operator const value_t&() const { - return ParamValue<T>::getValue(); + return param_value_t::getValue(); } const value_t& operator()() const { - return ParamValue<T>::getValue(); + return param_value_t::getValue(); } protected: @@ -571,7 +638,7 @@ namespace LLInitParam { public: LazyValue() - : mPtr(NULL) + : mPtr(NULL) {} ~LazyValue() @@ -585,26 +652,28 @@ namespace LLInitParam } LazyValue(const LazyValue& other) + : mPtr(NULL) { - if (other.mPtr) - { - mPtr = new T(*other.mPtr); - } - else - { - mPtr = NULL; - } + *this = other; } LazyValue& operator = (const LazyValue& other) { - if (other.mPtr) + if (!other.mPtr) { - mPtr = new T(*other.mPtr); + delete mPtr; + mPtr = NULL; } else { - mPtr = NULL; + if (!mPtr) + { + mPtr = new T(*other.mPtr); + } + else + { + *mPtr = *(other.mPtr); + } } return *this; } @@ -622,8 +691,14 @@ namespace LLInitParam void set(const T& other) { - delete mPtr; - mPtr = new T(other); + if (!mPtr) + { + mPtr = new T(other); + } + else + { + *mPtr = other; + } } const T& get() const @@ -667,12 +742,28 @@ namespace LLInitParam typedef LLInitParam::NOT_BLOCK NOT_A_BLOCK; template<typename T> - class Atomic - {}; + struct Atomic : public LLTypeTags::TypeTagBase<T, 1> + { + template <typename S> struct Cons { typedef Atomic<ParamValue<S> > value_t; }; + template <typename T> struct Cons<Atomic<T> > { typedef Atomic<T> value_t; }; + }; template<typename T, typename BLOCK_T = typename IsBlock<T>::value_t > - class Lazy - {}; + struct Lazy : public LLTypeTags::TypeTagBase<T, 0> + { + template <typename S> struct Cons + { + typedef Lazy<ParamValue<S, BLOCK_T>, BLOCK_T> value_t; + }; + template <typename T> struct Cons<Lazy<T, IS_A_BLOCK> > + { + typedef Lazy<T, IS_A_BLOCK> value_t; + }; + template <typename T> struct Cons<Lazy<T, NOT_A_BLOCK> > + { + typedef Lazy<T, BLOCK_T> value_t; + }; + }; // "Multiple" constraint types, put here in root class to avoid ambiguity during use struct AnyAmount @@ -837,14 +928,14 @@ namespace LLInitParam template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T>, bool HAS_MULTIPLE_VALUES = false, - typename VALUE_IS_BLOCK = typename IsBlock<ParamValue<T> >::value_t> + typename VALUE_IS_BLOCK = typename IsBlock<ParamValue<typename LLTypeTags::Sorted<T>::value_t> >::value_t> class TypedParam : public Param, public NAME_VALUE_LOOKUP::type_value_t { protected: typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t; - typedef ParamValue<T> param_value_t; + typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; typedef typename param_value_t::default_value_t default_value_t; typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; public: @@ -1002,7 +1093,7 @@ namespace LLInitParam public NAME_VALUE_LOOKUP::type_value_t { protected: - typedef ParamValue<T> param_value_t; + typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; typedef typename param_value_t::default_value_t default_value_t; typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> self_t; typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; @@ -1185,11 +1276,11 @@ namespace LLInitParam : public Param { protected: - typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t; - typedef ParamValue<VALUE_TYPE> param_value_t; + typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t; + typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t> param_value_t; typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t; - typedef container_t default_value_t; - typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; + typedef container_t default_value_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; public: typedef typename param_value_t::value_t value_t; @@ -1385,7 +1476,7 @@ namespace LLInitParam { protected: typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> self_t; - typedef ParamValue<VALUE_TYPE> param_value_t; + typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t> param_value_t; typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t; typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; typedef container_t default_value_t; @@ -1956,7 +2047,25 @@ namespace LLInitParam template<typename T, typename BLOCK_IDENTIFIER> struct IsBlock<ParamValue<BaseBlock::Atomic<T>, typename IsBlock<BaseBlock::Atomic<T> >::value_t >, BLOCK_IDENTIFIER> { - typedef typename IsBlock<ParamValue<T> >::value_t value_t; + typedef typename IsBlock<T>::value_t value_t; + }; + + template<typename T> + struct InnerMostType + { + typedef T value_t; + }; + + template<typename T> + struct InnerMostType<ParamValue<T, NOT_BLOCK> > + { + typedef typename InnerMostType<T>::value_t value_t; + }; + + template<typename T> + struct InnerMostType<ParamValue<T, IS_A_BLOCK> > + { + typedef typename InnerMostType<T>::value_t value_t; }; template<typename T, typename BLOCK_T> @@ -1965,8 +2074,8 @@ namespace LLInitParam typedef ParamValue <BaseBlock::Atomic<T>, BLOCK_T> self_t; public: - typedef T value_t; - typedef T default_value_t; + typedef typename InnerMostType<T>::value_t value_t; + typedef T default_value_t; ParamValue() : mValue(), @@ -1980,27 +2089,17 @@ namespace LLInitParam void setValue(const value_t& val) { - mValue = val; - } - - const T& getValue() const - { - return mValue; - } - - T& getValue() - { - return mValue; + mValue.setValue(val); } - operator const value_t&() const + const value_t& getValue() const { - return mValue; + return mValue.getValue(); } - const value_t& operator()() const + value_t& getValue() { - return mValue; + return mValue.getValue(); } bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) @@ -2030,7 +2129,7 @@ namespace LLInitParam if (overwrite) { resetToDefault(); - return mValue.mergeBlock(block_data, source, overwrite); + return mValue.mergeBlock(block_data, source.getValue(), overwrite); } return false; } @@ -2042,7 +2141,7 @@ namespace LLInitParam static BlockDescriptor& getBlockDescriptor() { - return T::getBlockDescriptor(); + return value_t::getBlockDescriptor(); } @@ -2064,9 +2163,9 @@ namespace LLInitParam typedef ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T> self_t; public: - typedef T value_t; - typedef LazyValue<T> default_value_t; - + typedef typename InnerMostType<T>::value_t value_t; + typedef LazyValue<T> default_value_t; + ParamValue() : mValue(), mValidated(false) @@ -2089,22 +2188,12 @@ namespace LLInitParam const value_t& getValue() const { - return mValue.get(); + return mValue.get().getValue(); } - T& getValue() + value_t& getValue() { - return mValue.get(); - } - - operator const value_t&() const - { - return mValue.get(); - } - - const value_t& operator()() const - { - return mValue.get(); + return mValue.get().getValue(); } bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) @@ -2117,7 +2206,7 @@ namespace LLInitParam if (mValue.empty()) return; const BaseBlock* base_block = (diff_block && !diff_block->mValue.empty()) - ? &(diff_block->mValue.get()) + ? &(diff_block->mValue.get().getValue()) : NULL; mValue.get().serializeBlock(p, name_stack, base_block); } @@ -2129,7 +2218,7 @@ namespace LLInitParam bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) { - return source.mValue.empty() || mValue.get().mergeBlock(block_data, source, overwrite); + return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite); } bool validateBlock(bool emit_errors = true) const @@ -2139,10 +2228,9 @@ namespace LLInitParam static BlockDescriptor& getBlockDescriptor() { - return T::getBlockDescriptor(); + return value_t::getBlockDescriptor(); } - mutable bool mValidated; // lazy validation flag private: @@ -2155,8 +2243,8 @@ namespace LLInitParam typedef ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> self_t; public: - typedef T value_t; - typedef LazyValue<T> default_value_t; + typedef typename InnerMostType<T>::value_t value_t; + typedef LazyValue<T> default_value_t; ParamValue() : mValue(), @@ -2180,22 +2268,12 @@ namespace LLInitParam const value_t& getValue() const { - return mValue.get(); + return mValue.get().getValue(); } - T& getValue() + value_t& getValue() { - return mValue.get(); - } - - operator const value_t&() const - { - return mValue.get(); - } - - const value_t& operator()() const - { - return mValue.get(); + return mValue.get().getValue(); } mutable bool mValidated; // lazy validation flag @@ -2226,9 +2304,6 @@ namespace LLInitParam const value_t& getValue() const { return mValue; } LLSD& getValue() { return mValue; } - operator const value_t&() const { return mValue; } - const value_t& operator()() const { return mValue; } - // block param interface bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index 58ed24b08b..808e391575 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -43,7 +43,6 @@ #include "lluicolor.h" #include "v3math.h" - using namespace BOOST_SPIRIT_CLASSIC_NS; const S32 MAX_STRING_ATTRIBUTE_SIZE = 40; @@ -80,7 +79,6 @@ struct Occurs : public LLInitParam::Block<Occurs> {} }; - typedef enum { USE_REQUIRED, @@ -102,9 +100,18 @@ namespace LLInitParam struct Element; struct Group; -struct Choice; struct Sequence; -struct Any; + +struct All : public LLInitParam::Block<All, Occurs> +{ + Multiple< Lazy<Element, IS_A_BLOCK> > elements; + + All() + : elements("element") + { + maxOccurs = 1; + } +}; struct Attribute : public LLInitParam::Block<Attribute> { @@ -128,24 +135,13 @@ struct Any : public LLInitParam::Block<Any, Occurs> {} }; -struct All : public LLInitParam::Block<All, Occurs> -{ - Multiple< Lazy<Element, IS_A_BLOCK> > elements; - - All() - : elements("element") - { - maxOccurs = 1; - } -}; - struct Choice : public LLInitParam::ChoiceBlock<Choice, Occurs> { Alternative< Lazy<Element, IS_A_BLOCK> > element; Alternative< Lazy<Group, IS_A_BLOCK> > group; Alternative< Lazy<Choice, IS_A_BLOCK> > choice; Alternative< Lazy<Sequence, IS_A_BLOCK> > sequence; - Alternative< Lazy<Any, IS_A_BLOCK> > any; + Alternative< Lazy<Any> > any; Choice() : element("element"), @@ -161,9 +157,9 @@ struct Sequence : public LLInitParam::ChoiceBlock<Sequence, Occurs> { Alternative< Lazy<Element, IS_A_BLOCK> > element; Alternative< Lazy<Group, IS_A_BLOCK> > group; - Alternative< Lazy<Choice, IS_A_BLOCK> > choice; + Alternative< Lazy<Choice> > choice; Alternative< Lazy<Sequence, IS_A_BLOCK> > sequence; - Alternative< Lazy<Any, IS_A_BLOCK> > any; + Alternative< Lazy<Any> > any; }; struct GroupContents : public LLInitParam::ChoiceBlock<GroupContents, Occurs> @@ -314,7 +310,6 @@ public: setNameSpace(ns); }; } - }; // diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 88727bf59b..29eb5ce69e 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -305,7 +305,11 @@ BOOL LLFloaterScriptSearch::handleKeyHere(KEY key, MASK mask) { if (mEditorCore) { - return mEditorCore->handleKeyHere(key, mask); + BOOL handled = mEditorCore->handleKeyHere(key, mask); + if (!handled) + { + LLFloater::handleKeyHere(key, mask); + } } return FALSE; -- cgit v1.2.3 From c8bc9cca06ba33a81d4f7bb5d624519e09071d9c Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 20 Apr 2012 19:12:24 -0700 Subject: fix for gcc builds --- indra/llxuixml/llinitparam.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 5222d4c713..f7e5e41cae 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -55,13 +55,13 @@ namespace LLTypeTags template<typename ITEM, typename REST, bool NEEDS_SWAP = GreaterThan<ITEM::SORT_ORDER, REST::SORT_ORDER>::value > struct Swap { - typedef typename ITEM::Cons<REST>::value_t value_t; + typedef typename ITEM::template Cons<REST>::value_t value_t; }; template<typename ITEM, typename REST> struct Swap<ITEM, REST, true> { - typedef typename REST::Cons<Swap<ITEM, typename REST::inner_t>::value_t>::value_t value_t; + typedef typename REST::template Cons<Swap<ITEM, typename REST::inner_t>::value_t>::value_t value_t; }; template<typename T, typename SORTABLE = void> @@ -79,7 +79,7 @@ namespace LLTypeTags template<typename ITEM, typename REST, bool IS_REST_SORTABLE = IsSortable<REST>::value> struct InsertInto { - typedef typename ITEM::Cons<REST>::value_t value_t; + typedef typename ITEM::template Cons<REST>::value_t value_t; }; template<typename ITEM, typename REST> @@ -248,7 +248,7 @@ namespace LLInitParam typedef std::map<std::string, T> value_name_map_t; typedef Inaccessable name_t; typedef TypeValues<T> type_value_t; - typedef typename ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; + typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; typedef typename param_value_t::value_t value_t; TypeValues(const typename param_value_t::value_t& val) @@ -745,7 +745,7 @@ namespace LLInitParam struct Atomic : public LLTypeTags::TypeTagBase<T, 1> { template <typename S> struct Cons { typedef Atomic<ParamValue<S> > value_t; }; - template <typename T> struct Cons<Atomic<T> > { typedef Atomic<T> value_t; }; + template <typename S> struct Cons<Atomic<S> > { typedef Atomic<S> value_t; }; }; template<typename T, typename BLOCK_T = typename IsBlock<T>::value_t > -- cgit v1.2.3 From f11f7c78537f096a637f5f1790e4f2a089718a2e Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 20 Apr 2012 19:21:59 -0700 Subject: CHUI-92 FIX Notification count is not shown on notification chiclet --- indra/newview/llchiclet.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index dd0d47cccd..4236c3f359 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -926,9 +926,9 @@ protected: mChiclet(chiclet) { // connect counter handlers to the signals - connectToChannel("IM Notifications"); connectToChannel("Group Notifications"); connectToChannel("Offer"); + connectToChannel("Notifications"); } static bool filterNotification(LLNotificationPtr notify); -- cgit v1.2.3 From 20de8559e56df169ec7978e50061c3d587142ad5 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 20 Apr 2012 19:31:46 -0700 Subject: more gcc fixes --- indra/llxuixml/llinitparam.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index f7e5e41cae..a956719fa3 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -755,13 +755,13 @@ namespace LLInitParam { typedef Lazy<ParamValue<S, BLOCK_T>, BLOCK_T> value_t; }; - template <typename T> struct Cons<Lazy<T, IS_A_BLOCK> > + template <typename S> struct Cons<Lazy<S, IS_A_BLOCK> > { - typedef Lazy<T, IS_A_BLOCK> value_t; + typedef Lazy<S, IS_A_BLOCK> value_t; }; - template <typename T> struct Cons<Lazy<T, NOT_A_BLOCK> > + template <typename S> struct Cons<Lazy<S, NOT_A_BLOCK> > { - typedef Lazy<T, BLOCK_T> value_t; + typedef Lazy<S, BLOCK_T> value_t; }; }; -- cgit v1.2.3 From dde1342fffcf0d90ef22e50405a0c4634ef22a74 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 23 Apr 2012 17:09:18 +0300 Subject: CHUI-93 FIXED Increased People floater minimum width to avoid scroller on the tab container. --- indra/newview/skins/default/xui/en/floater_people.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_people.xml b/indra/newview/skins/default/xui/en/floater_people.xml index 029e4464ea..45afe6b70b 100644 --- a/indra/newview/skins/default/xui/en/floater_people.xml +++ b/indra/newview/skins/default/xui/en/floater_people.xml @@ -7,7 +7,7 @@ height="570" help_topic="sidebar_people" min_height="440" - min_width="333" + min_width="390" layout="topleft" name="floater_people" save_rect="true" -- cgit v1.2.3 From 9b77ffb71ba112d27296b7ce8ab571285b9bba06 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 24 Apr 2012 16:51:59 -0700 Subject: CHUI-94 FIX Clicking OK on a notification does not remove the notification from the notifications listing --- indra/llxuixml/llinitparam.h | 145 +++++++++++++++++++++++++++++++++++++++- indra/llxuixml/llxuiparser.cpp | 4 +- indra/newview/llsyswellwindow.h | 2 +- 3 files changed, 147 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index a956719fa3..be63e5cb39 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -207,7 +207,7 @@ namespace LLInitParam typedef T value_t; ParamValue() - : T(), + : T(), mValidated(false) {} @@ -741,6 +741,13 @@ namespace LLInitParam typedef LLInitParam::IS_A_BLOCK IS_A_BLOCK; typedef LLInitParam::NOT_BLOCK NOT_A_BLOCK; + template<typename T> + struct Sequential : public LLTypeTags::TypeTagBase<T, 2> + { + template <typename S> struct Cons { typedef Sequential<ParamValue<S> > value_t; }; + template <typename S> struct Cons<Sequential<S> > { typedef Sequential<S> value_t; }; + }; + template<typename T> struct Atomic : public LLTypeTags::TypeTagBase<T, 1> { @@ -2050,6 +2057,13 @@ namespace LLInitParam typedef typename IsBlock<T>::value_t value_t; }; + template<typename T, typename BLOCK_IDENTIFIER> + struct IsBlock<ParamValue<BaseBlock::Sequential<T>, typename IsBlock<BaseBlock::Sequential<T> >::value_t >, BLOCK_IDENTIFIER> + { + typedef typename IsBlock<T>::value_t value_t; + }; + + template<typename T> struct InnerMostType { @@ -2157,6 +2171,135 @@ namespace LLInitParam T mValue; }; + template<typename T> + class ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK> + { + typedef ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK> self_t; + + public: + typedef typename InnerMostType<T>::value_t value_t; + typedef T default_value_t; + + ParamValue() + : mValue(), + mValidated(false) + { + mCurParam = getBlockDescriptor().mAllParams.begin(); + } + + ParamValue(const default_value_t& value) + : mValue(value), + mValidated(false) + { + mCurParam = getBlockDescriptor().mAllParams.begin(); + } + + void setValue(const value_t& val) + { + mValue.setValue(val); + } + + const value_t& getValue() const + { + return mValue.getValue(); + } + + value_t& getValue() + { + return mValue.getValue(); + } + + bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) + { + if (new_name) + { + mCurParam = getBlockDescriptor().mAllParams.begin(); + } + if (name_stack_range.first == name_stack_range.second + && mCurParam != getBlockDescriptor().mAllParams.end()) + { + // deserialize to mCurParam + LLParamDescriptor& pd = *(*mCurParam); + ParamDescriptor::deserialize_func_t deserialize_func = pd.mDeserializeFunc; + LLParam* paramp = mValue.getParamFromHandle(pd.mParamHandle); + + if (deserialize_func + && paramp + && deserialize_func(paramp, p, name_stack_range, new_name)) + { + ++mCurParam; + return true; + } + else + { + return false; + } + } + else + { + return mValue.deserializeBlock(p, name_stack_range, new_name); + } + } + + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const + { + const BaseBlock* base_block = diff_block + ? &(diff_block->mValue) + : NULL; + mValue.serializeBlock(p, name_stack, base_block); + } + + bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const + { + return mValue.inspectBlock(p, name_stack, min_count, max_count); + } + + bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) + { + return mValue.mergeBlock(block_data, source.getValue(), overwrite); + } + + bool validateBlock(bool emit_errors = true) const + { + return mValue.validateBlock(emit_errors); + } + + static BlockDescriptor& getBlockDescriptor() + { + return value_t::getBlockDescriptor(); + } + + mutable bool mValidated; // lazy validation flag + + private: + + BlockDescriptor::all_params_list_t::iterator mCurParam; + T mValue; + }; + + template<typename T> + class ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK> + : public T + { + typedef ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK> self_t; + + public: + typedef typename InnerMostType<T>::value_t value_t; + typedef T default_value_t; + + ParamValue() + : T(), + mValidated(false) + {} + + ParamValue(const default_value_t& value) + : T(value.getValue()), + mValidated(false) + {} + + mutable bool mValidated; // lazy validation flag + }; + template<typename T, typename BLOCK_T> class ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T> { diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index 808e391575..9cd88a1620 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -115,8 +115,8 @@ struct All : public LLInitParam::Block<All, Occurs> struct Attribute : public LLInitParam::Block<Attribute> { - Mandatory<std::string> name; - Mandatory<std::string> type; + Mandatory<std::string> name, + type; Mandatory<EUse> use; Attribute() diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index caf30cfd67..f497f546aa 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -123,7 +123,7 @@ protected: struct WellNotificationChannel : public LLNotificationChannel { WellNotificationChannel(LLNotificationWellWindow*); - void onAdd(LLNotificationPtr notify) + void onDelete(LLNotificationPtr notify) { mWellWindow->removeItemByID(notify->getID()); } -- cgit v1.2.3 From 5955e6260e6e263fb089f7cc91c0be482cccdfb8 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 24 Apr 2012 17:10:43 -0700 Subject: CHUI-106 FIX Notifications like Friends online are shown in local chat history - no toast given if chat history is open --- indra/llui/llnotificationtemplate.h | 2 +- indra/newview/skins/default/xui/en/notifications.xml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index 8080acbf87..f7d08ae1f4 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -206,7 +206,7 @@ struct LLNotificationTemplate : name("name"), persist("persist", false), log_to_im("log_to_im", false), - log_to_chat("log_to_chat", false), + log_to_chat("log_to_chat", true), functor("functor"), icon("icon"), label("label"), diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index da83ffbab4..73ec6ffdb3 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -5164,7 +5164,7 @@ The string [STRING_NAME] is missing from strings.xml icon="notifytip.tga" name="IMSystemMessageTip" log_to_im="true" - log_to_chat="true" + log_to_chat="false" type="notifytip"> [MESSAGE] </notification> @@ -5209,7 +5209,7 @@ Topic: [SUBJECT], Message: [MESSAGE] <notification icon="notifytip.tga" name="FriendOnline" - log_to_chat="true" + log_to_chat="false" type="notifytip"> <tag>friendship</tag> <nolink>[NAME]</nolink> is Online @@ -5218,7 +5218,7 @@ Topic: [SUBJECT], Message: [MESSAGE] <notification icon="notifytip.tga" name="FriendOffline" - log_to_chat="true" + log_to_chat="false" type="notifytip"> <tag>friendship</tag> <nolink>[NAME]</nolink> is Offline @@ -5466,7 +5466,7 @@ You don't have permission to copy this. icon="notifytip.tga" name="InventoryAccepted" log_to_im="true" - log_to_chat="true" + log_to_chat="false" type="notifytip"> [NAME] received your inventory offer. </notification> @@ -5475,7 +5475,7 @@ You don't have permission to copy this. icon="notifytip.tga" name="InventoryDeclined" log_to_im="true" - log_to_chat="true" + log_to_chat="false" type="notifytip"> [NAME] declined your inventory offer. </notification> -- cgit v1.2.3 From 734153b6399828cff9da44707a1720ad1b7a0c6f Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 24 Apr 2012 18:38:49 -0700 Subject: CHUI-96 FIX Cannot dismiss modal dialogs related to merchant outbox --- indra/newview/llfloateroutbox.cpp | 8 ++++++++ indra/newview/llnotificationhandler.h | 1 + 2 files changed, 9 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index 2a2b231b53..c55970ad69 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -58,6 +58,14 @@ bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotifi return false; } +void LLNotificationsUI::LLOutboxNotification::onDelete(LLNotificationPtr p) +{ + LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler*>(LLNotifications::instance().getChannel("AlertModal").get()); + if (sys_handler) + { + sys_handler->onDelete(p); + } +} ///---------------------------------------------------------------------------- /// LLOutboxAddedObserver helper class diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 21f3961d18..1725d632e8 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -276,6 +276,7 @@ public: {} /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onDelete(LLNotificationPtr p); bool processNotification(const LLNotificationPtr& p); }; -- cgit v1.2.3 From d5e4a69ffa8cb3cc8209f25bbfa1bc2ed49e3394 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 24 Apr 2012 18:57:13 -0700 Subject: fix for gcc builds --- indra/llxuixml/llinitparam.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index be63e5cb39..aa4bc73843 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -2219,9 +2219,9 @@ namespace LLInitParam && mCurParam != getBlockDescriptor().mAllParams.end()) { // deserialize to mCurParam - LLParamDescriptor& pd = *(*mCurParam); + ParamDescriptor& pd = *(*mCurParam); ParamDescriptor::deserialize_func_t deserialize_func = pd.mDeserializeFunc; - LLParam* paramp = mValue.getParamFromHandle(pd.mParamHandle); + Param* paramp = mValue.getParamFromHandle(pd.mParamHandle); if (deserialize_func && paramp -- cgit v1.2.3 From 6781eb101b135763a92153a3eab1245be95172bf Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 25 Apr 2012 10:28:20 -0700 Subject: more gcc build fixes --- indra/llxuixml/llinitparam.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index aa4bc73843..ce8a921cfe 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -2225,7 +2225,7 @@ namespace LLInitParam if (deserialize_func && paramp - && deserialize_func(paramp, p, name_stack_range, new_name)) + && deserialize_func(*paramp, p, name_stack_range, new_name)) { ++mCurParam; return true; -- cgit v1.2.3 From db316f830df45e1b0229ebcbdb5feedc5eb23913 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 26 Apr 2012 10:44:45 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose removed hacks for object inventory folderview --- indra/newview/llfolderview.cpp | 23 ++++------------- indra/newview/llfolderview.h | 8 ------ indra/newview/llfolderviewitem.cpp | 5 ++-- indra/newview/llpanelobjectinventory.cpp | 43 +++++++++++++------------------- 4 files changed, 25 insertions(+), 54 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index e0d7d67f7d..d54f04475f 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -176,6 +176,7 @@ LLFolderView::Params::Params() show_load_status("show_load_status", true), use_ellipses("use_ellipses", false) { + folder_indentation = -4; } @@ -224,10 +225,7 @@ LLFolderView::LLFolderView(const Params& p) mAutoOpenCandidate = NULL; mAutoOpenTimer.stop(); mKeyboardSelection = FALSE; - const LLFolderViewItem::Params& item_params = - LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); - S32 indentation = item_params.folder_indentation(); - mIndentation = -indentation; // children start at indentation 0 + mIndentation = p.folder_indentation; gIdleCallbacks.addFunction(idle, this); //clear label @@ -235,7 +233,6 @@ LLFolderView::LLFolderView(const Params& p) // just make sure the label ("Inventory Folder") never shows up mLabel = LLStringUtil::null; - //mRenamer->setWriteableBgColor(LLColor4::white); // Escape is handled by reverting the rename, not commiting it (default behavior) LLLineEditor::Params params; params.name("ren"); @@ -1921,20 +1918,10 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, // when drop is not handled by child, it should be handled // by the folder which is the hierarchy root. - if (!handled) + if (!handled + && getListener()->getUUID().notNull()) { - if (getListener()->getUUID().notNull()) - { - handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - } - else - { - if (!mFolders.empty()) - { - // dispatch to last folder as a hack to support "Contents" folder in object inventory - handled = mFolders.back()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); - } - } + handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); } if (handled) diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 1d018b5e6a..9a6bf05cd1 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -187,14 +187,6 @@ public: // public rename functionality - can only start the process void startRenamingSelectedItem( void ); - // These functions were used when there was only one folderview, - // and relied on that concept. This functionality is now handled - // by the listeners and the lldraganddroptool. - //LLFolderViewItem* getMovingItem() { return mMovingItem; } - //void setMovingItem( LLFolderViewItem* item ) { mMovingItem = item; } - //void dragItemIntoFolder( LLFolderViewItem* moving_item, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept ); - //void dragFolderIntoFolder( LLFolderViewFolder* moving_folder, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept ); - // LLView functionality ///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent ); /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 8d6114c887..ab1794ff15 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -417,9 +417,8 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) const Params& p = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); S32 indentation = p.folder_indentation(); // Only indent deeper items in hierarchy - mIndentation = (getParentFolder() - && getParentFolder()->getParentFolder() ) - ? mParentFolder->getIndentation() + indentation + mIndentation = (getParentFolder()) + ? getParentFolder()->getIndentation() + indentation : 0; if (mLabelWidthDirty) { diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 98ea680504..1efd1c3d9c 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -738,15 +738,7 @@ const std::string& LLTaskCategoryBridge::getDisplayName() const if (cat) { - // Localize "Contents" folder. - if (cat->getParentUUID().isNull() && cat->getName() == "Contents") - { - mDisplayName.assign(LLTrans::getString("ViewerObjectContents")); - } - else - { - mDisplayName.assign(cat->getName()); - } + mDisplayName.assign(cat->getName()); } return mDisplayName; @@ -1552,6 +1544,7 @@ void LLPanelObjectInventory::reset() p.parent_panel = this; p.tool_tip= LLTrans::getString("PanelContentsTooltip"); p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL); + p.folder_indentation = -14; // subtract space normally reserved for folder expanders mFolders = LLUICtrlFactory::create<LLFolderView>(p); // this ensures that we never say "searching..." or "no items found" mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); @@ -1630,10 +1623,11 @@ void LLPanelObjectInventory::updateInventory() LLInventoryObject* inventory_root = objectp->getInventoryRoot(); LLInventoryObject::object_list_t contents; objectp->getInventoryContents(contents); - if (inventory_root) + mHaveInventory = TRUE; + + if (inventory_root && !contents.empty()) { createFolderViews(inventory_root, contents); - mHaveInventory = TRUE; mIsInventoryEmpty = FALSE; mFolders->setEnabled(TRUE); } @@ -1641,7 +1635,6 @@ void LLPanelObjectInventory::updateInventory() { // TODO: create an empty inventory mIsInventoryEmpty = TRUE; - mHaveInventory = TRUE; } } else @@ -1693,19 +1686,19 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root bridge = LLTaskInvFVBridge::createObjectBridge(this, inventory_root); if(bridge) { - LLFolderViewFolder* new_folder = NULL; - LLFolderViewFolder::Params p; - p.name = inventory_root->getName(); - p.icon = LLUI::getUIImage("Inv_FolderClosed"); - p.icon_open = LLUI::getUIImage("Inv_FolderOpen"); - p.root = mFolders; - p.listener = bridge; - p.tool_tip = p.name; - new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); - new_folder->addToFolder(mFolders, mFolders); - new_folder->toggleOpen(); - - createViewsForCategory(&contents, inventory_root, new_folder); + //LLFolderViewFolder* new_folder = NULL; + //LLFolderViewFolder::Params p; + //p.name = inventory_root->getName(); + //p.icon = LLUI::getUIImage("Inv_FolderClosed"); + //p.icon_open = LLUI::getUIImage("Inv_FolderOpen"); + //p.root = mFolders; + //p.listener = bridge; + //p.tool_tip = p.name; + //new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); + //new_folder->addToFolder(mFolders, mFolders); + //new_folder->toggleOpen(); + + createViewsForCategory(&contents, inventory_root, mFolders); } } -- cgit v1.2.3 From 28d5727cecdad638202106fd1289bee25c0f97bd Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 26 Apr 2012 15:30:08 -0700 Subject: post-merge build fixes --- indra/llxuixml/llinitparam.h | 4 +- indra/newview/llfolderviewitem.cpp | 2 +- indra/newview/llimhandler.cpp | 56 +++++++++---------- indra/newview/llnotificationgrouphandler.cpp | 1 + indra/newview/llnotificationhandler.h | 2 +- indra/newview/llnotificationofferhandler.cpp | 2 +- indra/newview/llnotificationtiphandler.cpp | 81 +++++++++++++--------------- indra/newview/llviewerwindow.cpp | 12 ++--- indra/newview/llviewerwindow.h | 3 ++ 9 files changed, 81 insertions(+), 82 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 2c854d8287..29f4a09cb7 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -1405,7 +1405,7 @@ namespace LLInitParam return *this; } - self_t& add(const typename named_value_lookup_t::name_t& name) + self_t& add(const typename named_value_t::name_t& name) { value_t value; @@ -1612,7 +1612,7 @@ namespace LLInitParam return *this; } - self_t& add(const typename named_value_lookup_t::name_t& name) + self_t& add(const typename named_value_t::name_t& name) { value_t value; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index c2dec4ab27..43d3675d17 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -357,7 +357,7 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection, LLFolderView* root = getRoot(); if (getParentFolder()) { - getParentFolder()->requestArrange(); + getParentFolder()->requestArrange(); } if(set_selection) { diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index c7034aea3a..047472a282 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -71,34 +71,34 @@ bool LLIMHandler::processNotification(const LLNotificationPtr& notification) initChannel(); } - LLSD substitutions = notification->getSubstitutions(); - - // According to comments in LLIMMgr::addMessage(), if we get message - // from ourselves, the sender id is set to null. This fixes EXT-875. - LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); - if (avatar_id.isNull()) - avatar_id = gAgentID; - - LLToastIMPanel::Params im_p; - im_p.notification = notification; - im_p.avatar_id = avatar_id; - im_p.from = substitutions["FROM"].asString(); - im_p.time = substitutions["TIME"].asString(); - im_p.message = substitutions["MESSAGE"].asString(); - im_p.session_id = substitutions["SESSION_ID"].asUUID(); - - LLToastIMPanel* im_box = new LLToastIMPanel(im_p); - - LLToast::Params p; - p.notif_id = notification->getID(); - p.session_id = im_p.session_id; - p.notification = notification; - p.panel = im_box; - p.can_be_stored = false; - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); - if(channel) - channel->addToast(p); - } + LLSD substitutions = notification->getSubstitutions(); + + // According to comments in LLIMMgr::addMessage(), if we get message + // from ourselves, the sender id is set to null. This fixes EXT-875. + LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); + if (avatar_id.isNull()) + avatar_id = gAgentID; + + LLToastIMPanel::Params im_p; + im_p.notification = notification; + im_p.avatar_id = avatar_id; + im_p.from = substitutions["FROM"].asString(); + im_p.time = substitutions["TIME"].asString(); + im_p.message = substitutions["MESSAGE"].asString(); + im_p.session_id = substitutions["SESSION_ID"].asUUID(); + + LLToastIMPanel* im_box = new LLToastIMPanel(im_p); + + LLToast::Params p; + p.notif_id = notification->getID(); + p.session_id = im_p.session_id; + p.notification = notification; + p.panel = im_box; + p.can_be_stored = false; + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); + if(channel) + channel->addToast(p); + return false; } diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 50db4737ce..6946b78cbf 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -43,6 +43,7 @@ LLGroupHandler::LLGroupHandler() // Getting a Channel for our notifications LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); if(channel) + { channel->addOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1)); mChannel = channel->getHandle(); } diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 805e29e2a4..83d228e799 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -95,7 +95,7 @@ public: // base interface functions /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } /*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel) mChannel->killToastByNotificationID(p->getID());} + /*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->killToastByNotificationID(p->getID());} virtual bool processNotification(const LLNotificationPtr& notify)=0; diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 52cc518968..2112b0d35e 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -48,7 +48,7 @@ LLOfferHandler::LLOfferHandler() if(channel) { channel->setControlHovering(true); - channel->setOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1)); + channel->addOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1)); mChannel = channel->getHandle(); } } diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index f07109335d..3588721849 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -82,61 +82,56 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) // archive message in nearby chat if (notification->canLogToChat()) - { - LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); - - // don't show toast if Nearby Chat is opened - LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); - if (!nearby_chat_bar->isMinimized() && nearby_chat_bar->getVisible() && nearby_chat->getVisible()) - { - return false; - } - } + { + LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); - std::string session_name = notification->getPayload()["SESSION_NAME"]; - const std::string name = notification->getSubstitutions()["NAME"]; - if (session_name.empty()) + // don't show toast if Nearby Chat is opened + LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); + LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); + if (!nearby_chat_bar->isMinimized() && nearby_chat_bar->getVisible() && nearby_chat->getVisible()) { - session_name = name; + return false; } - LLUUID from_id = notification->getPayload()["from_id"]; + } + + std::string session_name = notification->getPayload()["SESSION_NAME"]; + const std::string name = notification->getSubstitutions()["NAME"]; + if (session_name.empty()) + { + session_name = name; + } + LLUUID from_id = notification->getPayload()["from_id"]; if (notification->canLogToIM()) - { - LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, - notification->getMessage(), from_id, from_id); - } + { + LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, + notification->getMessage(), from_id, from_id); + } if (notification->canLogToIM() && notification->hasFormElements()) - { - LLHandlerUtil::spawnIMSession(name, from_id); - } + { + LLHandlerUtil::spawnIMSession(name, from_id); + } if (notification->canLogToIM() && LLHandlerUtil::isIMFloaterOpened(notification)) - { - return false; - } + { + return false; + } - LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); + LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); - p.panel = notify_box; - p.is_tip = true; - p.can_be_stored = false; + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); + p.panel = notify_box; + p.is_tip = true; + p.can_be_stored = false; - removeExclusiveNotifications(notification); + removeExclusiveNotifications(notification); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); - if(channel) - channel->addToast(p); - } - else if (notify["sigtype"].asString() == "delete") - { - mChannel->killToastByNotificationID(notification->getID()); - } + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); + if(channel) + channel->addToast(p); return false; } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 117078bcd1..32f693b009 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1542,14 +1542,14 @@ LLViewerWindow::LLViewerWindow(const Params& p) // pass its value right now. Instead, pass it a nullary function that // will, when we later need it, return the value of gKeyboard. // boost::lambda::var() constructs such a functor on the fly. - mWindowListener(new LLWindowListener(this, boost::lambda::var(gKeyboard))), - mViewerWindowListener(new LLViewerWindowListener(this)), + mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard))); + mViewerWindowListener.reset(new LLViewerWindowListener(this)); - LLNotificationChannelPtr vw_alerts_channel(new LLNotificationChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"))); - LLNotificationChannelPtr vw_alerts_modal_channel(new LLNotificationChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"))); + mAlertsChannel.reset(new LLNotificationChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"))); + mModalAlertsChannel.reset(new LLNotificationChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"))); - vw_alerts_channel->connectChanged(&LLViewerWindow::onAlert); - vw_alerts_modal_channel->connectChanged(&LLViewerWindow::onAlert); + mAlertsChannel->connectChanged(&LLViewerWindow::onAlert); + mModalAlertsChannel->connectChanged(&LLViewerWindow::onAlert); LLNotifications::instance().setIgnoreAllNotifications(gSavedSettings.getBOOL("IgnoreAllNotifications")); llinfos << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << llendl; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 6efcaeaf18..ee6a7793f8 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -418,6 +418,9 @@ private: bool mActive; bool mUIVisible; + boost::shared_ptr<class LLNotificationChannel> mAlertsChannel, + mModalAlertsChannel; + LLRect mWindowRectRaw; // whole window, including UI LLRect mWindowRectScaled; // whole window, scaled by UI size LLRect mWorldViewRectRaw; // area of screen for 3D world -- cgit v1.2.3 From 2babcb4af56e6b7fb443f1b78002dc9e61e891c7 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Thu, 23 Feb 2012 21:02:46 +0200 Subject: Linux build fix. Moved type casts from protected base classes to derived LLCoord. --- indra/llmath/llcoord.h | 19 +++++++++++++------ indra/llui/llfloater.cpp | 4 ++-- indra/llwindow/llwindow.cpp | 8 ++++---- 3 files changed, 19 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llcoord.h b/indra/llmath/llcoord.h index 1f617e649e..a66f3c7424 100644 --- a/indra/llmath/llcoord.h +++ b/indra/llmath/llcoord.h @@ -26,6 +26,15 @@ #ifndef LL_LLCOORD_H #define LL_LLCOORD_H +template<typename> class LLCoord; +struct LL_COORD_TYPE_GL; +struct LL_COORD_TYPE_WINDOW; +struct LL_COORD_TYPE_SCREEN; + +typedef LLCoord<LL_COORD_TYPE_GL> LLCoordGL; +typedef LLCoord<LL_COORD_TYPE_WINDOW> LLCoordWindow; +typedef LLCoord<LL_COORD_TYPE_SCREEN> LLCoordScreen; + struct LLCoordCommon { LLCoordCommon(S32 x, S32 y) : mX(x), mY(y) {} @@ -62,6 +71,8 @@ public: bool operator==(const self_t& other) const { return mX == other.mX && mY == other.mY; } bool operator!=(const self_t& other) const { return !(*this == other); } + static const self_t& getTypedCoords(const COORD_FRAME& self) { return static_cast<const self_t&>(self); } + static self_t& getTypedCoords(COORD_FRAME& self) { return static_cast<self_t&>(self); } }; struct LL_COORD_TYPE_GL @@ -70,13 +81,13 @@ struct LL_COORD_TYPE_GL LLCoordCommon convertToCommon() const { - const LLCoord<LL_COORD_TYPE_GL>& self = static_cast<const LLCoord<LL_COORD_TYPE_GL>&>(*this); + const LLCoordGL& self = LLCoordGL::getTypedCoords(*this); return LLCoordCommon(self.mX, self.mY); } void convertFromCommon(const LLCoordCommon& from) { - LLCoord<LL_COORD_TYPE_GL>& self = static_cast<LLCoord<LL_COORD_TYPE_GL>&>(*this); + LLCoordGL& self = LLCoordGL::getTypedCoords(*this); self.mX = from.mX; self.mY = from.mY; } @@ -98,8 +109,4 @@ struct LL_COORD_TYPE_SCREEN void convertFromCommon(const LLCoordCommon& from); }; -typedef LLCoord<LL_COORD_TYPE_GL> LLCoordGL; -typedef LLCoord<LL_COORD_TYPE_WINDOW> LLCoordWindow; -typedef LLCoord<LL_COORD_TYPE_SCREEN> LLCoordScreen; - #endif diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 22b20969fc..51611d547c 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -3306,7 +3306,7 @@ bool LLCoordFloater::operator==(const LLCoordFloater& other) const LLCoordCommon LL_COORD_FLOATER::convertToCommon() const { - const LLCoordFloater& self = static_cast<const LLCoordFloater&>(*this); + const LLCoordFloater& self = static_cast<const LLCoordFloater&>(LLCoordFloater::getTypedCoords(*this)); LLRect snap_rect = gFloaterView->getSnapRect(); LLFloater* floaterp = mFloater.get(); @@ -3348,7 +3348,7 @@ LLCoordCommon LL_COORD_FLOATER::convertToCommon() const void LL_COORD_FLOATER::convertFromCommon(const LLCoordCommon& from) { - LLCoordFloater& self = static_cast<LLCoordFloater&>(*this); + LLCoordFloater& self = static_cast<LLCoordFloater&>(LLCoordFloater::getTypedCoords(*this)); LLRect snap_rect = gFloaterView->getSnapRect(); LLFloater* floaterp = mFloater.get(); S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0; diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 6834b34387..4e91271d83 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -440,7 +440,7 @@ BOOL LLWindowManager::isWindowValid(LLWindow *window) //coordinate conversion utility funcs that forward to llwindow LLCoordCommon LL_COORD_TYPE_WINDOW::convertToCommon() const { - const LLCoordWindow& self = static_cast<const LLCoordWindow&>(*this); + const LLCoordWindow& self = LLCoordWindow::getTypedCoords(*this); LLWindow* windowp = &(*LLWindow::beginInstances()); LLCoordGL out; @@ -450,7 +450,7 @@ LLCoordCommon LL_COORD_TYPE_WINDOW::convertToCommon() const void LL_COORD_TYPE_WINDOW::convertFromCommon(const LLCoordCommon& from) { - LLCoordWindow& self = static_cast<LLCoordWindow&>(*this); + LLCoordWindow& self = LLCoordWindow::getTypedCoords(*this); LLWindow* windowp = &(*LLWindow::beginInstances()); LLCoordGL from_gl(from); @@ -459,7 +459,7 @@ void LL_COORD_TYPE_WINDOW::convertFromCommon(const LLCoordCommon& from) LLCoordCommon LL_COORD_TYPE_SCREEN::convertToCommon() const { - const LLCoordScreen& self = static_cast<const LLCoordScreen&>(*this); + const LLCoordScreen& self = LLCoordScreen::getTypedCoords(*this); LLWindow* windowp = &(*LLWindow::beginInstances()); LLCoordGL out; @@ -469,7 +469,7 @@ LLCoordCommon LL_COORD_TYPE_SCREEN::convertToCommon() const void LL_COORD_TYPE_SCREEN::convertFromCommon(const LLCoordCommon& from) { - LLCoordScreen& self = static_cast<LLCoordScreen&>(*this); + LLCoordScreen& self = LLCoordScreen::getTypedCoords(*this); LLWindow* windowp = &(*LLWindow::beginInstances()); LLCoordGL from_gl(from); -- cgit v1.2.3 From cf86247b8c5e199447b7cd3dc645a42a6a645265 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Thu, 26 Apr 2012 23:52:57 +0300 Subject: CHUI-78 WIP Reordered and added missing items for People floater gear menus. --- indra/newview/llpanelpeoplemenus.cpp | 1 + .../skins/default/xui/en/menu_people_groups.xml | 23 +++++---- .../skins/default/xui/en/menu_people_nearby.xml | 56 +++++++++++++--------- 3 files changed, 45 insertions(+), 35 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index f12c4de2f7..0d66b8f10b 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -67,6 +67,7 @@ LLContextMenu* NearbyMenu::createMenu() registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, id)); registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, id)); registrar.add("Avatar.BlockUnblock", boost::bind(&LLAvatarActions::toggleBlock, id)); + registrar.add("Avatar.InviteToGroup", boost::bind(&LLAvatarActions::inviteToGroup, id)); enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2)); enable_registrar.add("Avatar.CheckItem", boost::bind(&NearbyMenu::checkContextMenuItem, this, _2)); diff --git a/indra/newview/skins/default/xui/en/menu_people_groups.xml b/indra/newview/skins/default/xui/en/menu_people_groups.xml index 3a450258fa..1e0364b84e 100644 --- a/indra/newview/skins/default/xui/en/menu_people_groups.xml +++ b/indra/newview/skins/default/xui/en/menu_people_groups.xml @@ -2,6 +2,16 @@ <toggleable_menu name="menu_group_plus" left="0" bottom="0" visible="false" mouse_opaque="false" opaque="true" color="MenuDefaultBgColor"> + <menu_item_call + label="Activate" + name="Activate"> + <menu_item_call.on_click + function="People.Groups.Action" + parameter="activate" /> + <menu_item_call.on_enable + function="People.Groups.Enable" + parameter="activate" /> + </menu_item_call> <menu_item_call label="View Info" name="View Info"> @@ -23,7 +33,7 @@ parameter="chat" /> </menu_item_call> <menu_item_call - label="Call" + label="Voice call" name="Call"> <menu_item_call.on_click function="People.Groups.Action" @@ -33,17 +43,6 @@ parameter="call" /> </menu_item_call> <menu_item_separator /> - <menu_item_call - label="Activate" - name="Activate"> - <menu_item_call.on_click - function="People.Groups.Action" - parameter="activate" /> - <menu_item_call.on_enable - function="People.Groups.Enable" - parameter="activate" /> - </menu_item_call> - <menu_item_separator /> <menu_item_call label="Leave" name="Leave"> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index d2e35e4cc0..b7c9ab1fe3 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -9,13 +9,40 @@ <menu_item_call.on_click function="Avatar.Profile" /> </menu_item_call> + <menu_item_call + label="IM" + layout="topleft" + name="IM"> + <menu_item_call.on_click + function="Avatar.IM" /> + </menu_item_call> + <menu_item_call + label="Offer Teleport" + name="teleport"> + <menu_item_call.on_click + function="Avatar.OfferTeleport"/> + <menu_item_call.on_enable + function="Avatar.EnableItem" + parameter="can_offer_teleport"/> + </menu_item_call> + <menu_item_call + label="Voice call" + layout="topleft" + name="Call"> + <menu_item_call.on_click + function="Avatar.Call" /> + <menu_item_call.on_enable + function="Avatar.EnableItem" + parameter="can_call" /> + </menu_item_call> + <menu_item_separator /> <menu_item_call label="Add Friend" layout="topleft" name="Add Friend"> <menu_item_call.on_click function="Avatar.AddFriend" /> - <menu_item_call.on_enable + <menu_item_call.on_visible function="Avatar.EnableItem" parameter="can_add" /> </menu_item_call> @@ -30,22 +57,13 @@ parameter="can_delete" /> </menu_item_call> <menu_item_call - label="IM" + label="Invite to group..." layout="topleft" - name="IM"> + name="Invite"> <menu_item_call.on_click - function="Avatar.IM" /> - </menu_item_call> - <menu_item_call - label="Call" - layout="topleft" - name="Call"> - <menu_item_call.on_click - function="Avatar.Call" /> - <menu_item_call.on_enable - function="Avatar.EnableItem" - parameter="can_call" /> + function="Avatar.InviteToGroup" /> </menu_item_call> + <menu_item_separator /> <menu_item_call label="Map" layout="topleft" @@ -83,13 +101,5 @@ function="Avatar.EnableItem" parameter="can_block" /> </menu_item_check> - <menu_item_call - label="Offer Teleport" - name="teleport"> - <menu_item_call.on_click - function="Avatar.OfferTeleport"/> - <menu_item_call.on_enable - function="Avatar.EnableItem" - parameter="can_offer_teleport"/> - </menu_item_call> + </context_menu> -- cgit v1.2.3 From f948ba82a985c2fec5ed1e65a55bd68f6e811197 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 4 May 2012 22:08:13 +0300 Subject: CHUI-103 WIP Added support for showing/hiding timestamp and names, replacing own name with (You) --- indra/newview/llchathistory.cpp | 30 ++++++++++++++++++-------- indra/newview/skins/default/xui/en/strings.xml | 1 + 2 files changed, 22 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 5bdfb5adbc..143d4ff4fe 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -778,15 +778,19 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (use_plain_text_chat_history) { LLStyle::Params timestamp_style(style_params); - if (!message_from_log) + + if (args["show_time"].asBoolean()) { - LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor"); - timestamp_style.color(timestamp_color); - timestamp_style.readonly_color(timestamp_color); + if (!message_from_log) + { + LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor"); + timestamp_style.color(timestamp_color); + timestamp_style.readonly_color(timestamp_color); + } + mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, timestamp_style); } - mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, timestamp_style); - if (utf8str_trim(chat.mFromName).size() != 0) + if (args["show_names_in_p2p_chat"].asBoolean() && utf8str_trim(chat.mFromName).size() != 0) { // Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text. if ( chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull()) @@ -806,13 +810,21 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL mEditor->appendText(chat.mFromName + delimiter, false, link_params); } - else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log) + else if (chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log) { LLStyle::Params link_params(style_params); link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); - // Add link to avatar's inspector and delimiter to message. - mEditor->appendText(std::string(link_params.link_href) + delimiter, false, link_params); + if (gAgentID == chat.mFromID) + { std::string localized_name; + bool is_localized = LLTrans::findString(localized_name, "AgentNameSubst"); + mEditor->appendText((is_localized? localized_name:"(You)") + delimiter, false, link_params); + } + else + { + // Add link to avatar's inspector and delimiter to message. + mEditor->appendText(std::string(link_params.link_href) + delimiter, false, link_params); + } } else { diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 9752652679..0beb8ed0ab 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -405,6 +405,7 @@ Please try logging in again in a minute.</string> <string name="TrackYourCamera">Track your camera</string> <string name="ControlYourCamera">Control your camera</string> <string name="NotConnected">Not Connected</string> + <string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name --> <!-- Sim Access labels --> <string name="SIM_ACCESS_PG">General</string> -- cgit v1.2.3 From 79928c65329146920558d9bc286f643ccf8dca7f Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 7 May 2012 20:05:07 +0300 Subject: CHUI-103 Repair drawing messages with prepend new line --- indra/newview/llchathistory.cpp | 21 ++++++++++++++------- indra/newview/llchathistory.h | 4 ++++ 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 143d4ff4fe..30b2839547 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -775,10 +775,13 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL style_params.readonly_color(LLColor4::grey); } + mPrependNewLineState = (mEditor->getText().size() != 0)? 1 : 0; + if (use_plain_text_chat_history) { LLStyle::Params timestamp_style(style_params); + // timestams showing if (args["show_time"].asBoolean()) { if (!message_from_log) @@ -787,9 +790,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL timestamp_style.color(timestamp_color); timestamp_style.readonly_color(timestamp_color); } - mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, timestamp_style); + mEditor->appendText("[" + chat.mTimeStr + "] ", isNeedPrependNewline(), timestamp_style); } + // names showing if (args["show_names_in_p2p_chat"].asBoolean() && utf8str_trim(chat.mFromName).size() != 0) { // Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text. @@ -807,8 +811,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL link_params.is_link = true; link_params.link_href = url; - mEditor->appendText(chat.mFromName + delimiter, - false, link_params); + mEditor->appendText(chat.mFromName + delimiter, isNeedPrependNewline(), link_params); } else if (chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log) { @@ -818,22 +821,26 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (gAgentID == chat.mFromID) { std::string localized_name; bool is_localized = LLTrans::findString(localized_name, "AgentNameSubst"); - mEditor->appendText((is_localized? localized_name:"(You)") + delimiter, false, link_params); + mEditor->appendText((is_localized? localized_name:"(You)") + delimiter, + isNeedPrependNewline(), link_params); } else { // Add link to avatar's inspector and delimiter to message. - mEditor->appendText(std::string(link_params.link_href) + delimiter, false, link_params); + mEditor->appendText(std::string(link_params.link_href) + delimiter, + isNeedPrependNewline(), link_params); } } else { - mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, false, style_params); + mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, + isNeedPrependNewline(), style_params); } } } else { + mPrependNewLineState = 0; LLView* view = NULL; LLInlineViewSegment::Params p; p.force_newline = true; @@ -956,7 +963,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL message = chat.mFromName + message; } - mEditor->appendText(message, FALSE, style_params); + mEditor->appendText(message, isNeedPrependNewline(), style_params); } mEditor->blockUndo(); diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 28344e6a10..4cd9c75e1c 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -138,6 +138,10 @@ class LLChatHistory : public LLUICtrl S32 mTopHeaderPad; S32 mBottomHeaderPad; + S32 mPrependNewLineState; + + bool isNeedPrependNewline() {return (mPrependNewLineState-- > 0);} + class LLLayoutPanel* mMoreChatPanel; LLTextBox* mMoreChatText; LLTextEditor* mEditor; -- cgit v1.2.3 From 7b8251fd2f169136fc45e4c17104da676f75727b Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 7 May 2012 21:54:09 +0300 Subject: CHUI-103 WIP Added settings for switching text view mode --- indra/newview/app_settings/settings.xml | 23 +++++++++++++++++++++++ indra/newview/llchathistory.cpp | 24 +++++++++++++++--------- indra/newview/llchathistory.h | 4 ---- indra/newview/llimfloater.cpp | 3 +++ 4 files changed, 41 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ee8c15752b..e6d0ed7dfa 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2,6 +2,29 @@ <llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> <map> + <key>IMShowTime</key> + <map> + <key>Comment</key> + <string>Enable(disable) timestamp showing in the chat.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>IMShowNamesForP2PConv</key> + <map> + <key>Comment</key> + <string>Enable(disable) showing of a names in the chat.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>CrashHostUrl</key> <map> <key>Comment</key> diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 30b2839547..b70e98f22b 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -775,7 +775,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL style_params.readonly_color(LLColor4::grey); } - mPrependNewLineState = (mEditor->getText().size() != 0)? 1 : 0; + bool prependNewLineState = mEditor->getText().size() != 0; if (use_plain_text_chat_history) { @@ -790,11 +790,12 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL timestamp_style.color(timestamp_color); timestamp_style.readonly_color(timestamp_color); } - mEditor->appendText("[" + chat.mTimeStr + "] ", isNeedPrependNewline(), timestamp_style); + mEditor->appendText("[" + chat.mTimeStr + "] ", prependNewLineState, timestamp_style); + prependNewLineState = false; } // names showing - if (args["show_names_in_p2p_chat"].asBoolean() && utf8str_trim(chat.mFromName).size() != 0) + if (args["show_names_for_p2p_conv"].asBoolean() && utf8str_trim(chat.mFromName).size() != 0) { // Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text. if ( chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull()) @@ -811,7 +812,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL link_params.is_link = true; link_params.link_href = url; - mEditor->appendText(chat.mFromName + delimiter, isNeedPrependNewline(), link_params); + mEditor->appendText(chat.mFromName + delimiter, prependNewLineState, link_params); + prependNewLineState = false; } else if (chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log) { @@ -822,25 +824,28 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL { std::string localized_name; bool is_localized = LLTrans::findString(localized_name, "AgentNameSubst"); mEditor->appendText((is_localized? localized_name:"(You)") + delimiter, - isNeedPrependNewline(), link_params); + prependNewLineState, link_params); + prependNewLineState = false; } else { // Add link to avatar's inspector and delimiter to message. mEditor->appendText(std::string(link_params.link_href) + delimiter, - isNeedPrependNewline(), link_params); + prependNewLineState, link_params); + prependNewLineState = false; } } else { mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, - isNeedPrependNewline(), style_params); + prependNewLineState, style_params); + prependNewLineState = false; } } } else { - mPrependNewLineState = 0; + prependNewLineState = 0; LLView* view = NULL; LLInlineViewSegment::Params p; p.force_newline = true; @@ -963,7 +968,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL message = chat.mFromName + message; } - mEditor->appendText(message, isNeedPrependNewline(), style_params); + mEditor->appendText(message, prependNewLineState, style_params); + prependNewLineState = false; } mEditor->blockUndo(); diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 4cd9c75e1c..28344e6a10 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -138,10 +138,6 @@ class LLChatHistory : public LLUICtrl S32 mTopHeaderPad; S32 mBottomHeaderPad; - S32 mPrependNewLineState; - - bool isNeedPrependNewline() {return (mPrependNewLineState-- > 0);} - class LLLayoutPanel* mMoreChatPanel; LLTextBox* mMoreChatText; LLTextEditor* mEditor; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index f67464078b..f743b5e2bf 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -630,6 +630,9 @@ void LLIMFloater::updateMessages() { LLSD chat_args; chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history; + chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); + chat_args["show_names_for_p2p_conv"] = + gSavedSettings.getBOOL("IMShowNamesForP2PConv"); std::ostringstream message; std::list<LLSD>::const_reverse_iterator iter = messages.rbegin(); -- cgit v1.2.3 From fac210075f4c68db372ae0535e332ffe9765a5d1 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Mon, 7 May 2012 22:40:56 +0300 Subject: CHUI-105 WIP Added tear-off and return behavior for IM floater. XUI changed for Converstions multifloater and IM floater. --- indra/llui/llfloater.cpp | 4 +- indra/newview/llimfloater.cpp | 46 ++++++ indra/newview/llimfloater.h | 2 + indra/newview/llimfloatercontainer.cpp | 24 ++++ indra/newview/llimfloatercontainer.h | 1 + .../skins/default/xui/en/floater_im_container.xml | 111 ++++++++++----- .../skins/default/xui/en/floater_im_session.xml | 158 +++++++++++++++++---- 7 files changed, 281 insertions(+), 65 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 51611d547c..b087205a5c 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1371,7 +1371,7 @@ void LLFloater::setHost(LLMultiFloater* host) mButtonScale = 1.f; //mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE; } - updateTitleButtons(); + if (host) { mHostHandle = host->getHandle(); @@ -1381,6 +1381,8 @@ void LLFloater::setHost(LLMultiFloater* host) { mHostHandle.markDead(); } + + updateTitleButtons(); } void LLFloater::moveResizeHandlesToFront() diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index f743b5e2bf..df3521ecb0 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -28,6 +28,7 @@ #include "llimfloater.h" +#include "lldraghandle.h" #include "llnotificationsutil.h" #include "llagent.h" @@ -251,6 +252,12 @@ BOOL LLIMFloater::postBuild() slide_right->setVisible(!mControlPanel->getParent()->getVisible()); slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); + LLButton* return_btn = getChild<LLButton>("return_btn"); + return_btn->setCommitCallback(boost::bind(&LLFloater::onClickTearOff, this)); + + LLButton* tear_off_btn = getChild<LLButton>("tear_off_btn"); + tear_off_btn->setCommitCallback(boost::bind(&LLFloater::onClickTearOff, this)); + mInputEditor = getChild<LLLineEditor>("chat_editor"); mInputEditor->setMaxTextLength(1023); // enable line history support for instant message bar @@ -1194,3 +1201,42 @@ void LLIMFloater::onClickCloseBtn() LLFloater::onClickCloseBtn(); } + +// virtual +void LLIMFloater::updateTitleButtons() +{ + if (!mDragHandle) + { + return; + } + + LLMultiFloater* host_floater = getHost(); + + bool is_hosted = host_floater != NULL; + if (is_hosted) ///< floater is hosted + { + for (S32 i = 0; i < BUTTON_COUNT; i++) + { + if (!mButtons[i]) + { + continue; + } + + // Hide the standard header buttons in a docked IM floater. + mButtons[i]->setVisible(false); + } + } + else ///< floater is torn off + { + LLFloater::updateTitleButtons(); + } + + // toggle floater's drag handle and title visibility + mDragHandle->setVisible(!is_hosted); + + LLButton* return_btn = getChild<LLButton>("return_btn"); + return_btn->setVisible(!is_hosted); + + LLButton* tear_off_btn = getChild<LLButton>("tear_off_btn"); + tear_off_btn->setVisible(is_hosted); +} diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index f7cd35b5eb..95aa214ff6 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -120,6 +120,8 @@ protected: /* virtual */ void onClickCloseBtn(); + /*virtual*/ void updateTitleButtons(); + private: // process focus events to set a currently active session /* virtual */ void onFocusLost(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index c8e48b0d42..9b5055fb98 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -56,6 +56,9 @@ BOOL LLIMFloaterContainer::postBuild() mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLIMFloaterContainer::onNewMessageReceived, this, _1)); // Do not call base postBuild to not connect to mCloseSignal to not close all floaters via Close button // mTabContainer will be initialized in LLMultiFloater::addChild() + + setTabContainer(getChild<LLTabContainer>("im_box_tab_container")); + return TRUE; } @@ -74,6 +77,7 @@ void LLIMFloaterContainer::onOpen(const LLSD& key) */ } +// virtual void LLIMFloaterContainer::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point) @@ -89,6 +93,12 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); + LLView* floater_contents = floaterp->getChild<LLView>("contents_view"); + + // we don't show the header when the floater is hosted, + // so reshape floater contents to occupy the header space + floater_contents->setShape(floaterp->getRect()); + LLUUID session_id = floaterp->getKey(); LLIconCtrl* icon = 0; @@ -116,6 +126,20 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, mTabContainer->setTabImage(floaterp, icon); } +// virtual +void LLIMFloaterContainer::removeFloater(LLFloater* floaterp) +{ + LLMultiFloater::removeFloater(floaterp); + + LLRect contents_rect = floaterp->getRect(); + + // reduce the floater contents height by header height + contents_rect.mTop -= floaterp->getHeaderHeight(); + + LLView* floater_contents = floaterp->getChild<LLView>("contents_view"); + floater_contents->setShape(contents_rect); +} + void LLIMFloaterContainer::onCloseFloater(LLUUID& id) { mSessions.erase(id); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 892ecef48d..93b91fe3cf 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -50,6 +50,7 @@ public: /*virtual*/ void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); + /*virtual*/ void removeFloater(LLFloater* floaterp); static LLFloater* getCurrentVoiceFloater(); diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e123de46c2..d19b36971f 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -3,47 +3,86 @@ can_close="false" can_minimize="true" can_resize="true" - height="390" + height="430" layout="topleft" + min_width="510" name="floater_im_box" help_topic="floater_im_box" save_rect="true" save_visibility="true" single_instance="true" title="CONVERSATIONS" - width="396"> - <tab_container - follows="left|right|top|bottom" - height="390" - layout="topleft" - left="1" - name="im_box_tab_container" - tab_position="bottom" - tab_width="64" - tab_max_width = "134" - tab_height="16" - use_custom_icon_ctrl="true" - tab_icon_ctrl_pad="2" - halign="left" - use_ellipses="true" - top="0" - width="394"> - <first_tab - tab_bottom_image_flash="Toolbar_Left_Flash"/> - <middle_tab - tab_bottom_image_flash="Toolbar_Middle_Flash"/> - <last_tab - tab_bottom_image_flash="Toolbar_Right_Flash"/> - </tab_container> - <icon - color="DefaultShadowLight" - enabled="false" - follows="left|right|bottom" - height="17" - image_name="tabarea.tga" - layout="bottomleft" - left="1" - name="im_box_tab_container_icon" - bottom="10" - width="394" /> + width="680"> + <panel + border="true" + follows="top|bottom|left" + layout="topleft" + name="conversations_list" + opaque="true" + top="0" + left="5" + height="425" + width="263"> + <menu_button + follows="top|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left="5" + name="sort_btn" + top="5" + width="31" /> + <button + follows="top|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_pad="4" + name="add_btn" + tool_tip="Add button on the left panel" + width="31"> + </button> + <button + follows="right|top" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TabIcon_Open_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left="228" + name="slide_left_btn" + width="31" /> + <button + follows="right|top" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TabIcon_Close_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_delta="0" + name="slide_right_btn" + width="31" /> + </panel> + <panel_container + follows="all" + layout="topleft" + name="im_box_tab_container" + opaque="true" + top="0" + left_pad="15" + height="430" + width="389" + min_width="290"> + </panel_container> </multi_floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index ca73883e53..3c3f4ad0e2 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - legacy_header_height="18" background_visible="true" default_tab_group="1" height="355" @@ -15,28 +14,147 @@ can_resize="true" min_width="250" min_height="190"> + <view + follows="all" + layout="topleft" + name="contents_view" + top="0" + left="0" + height="355" + width="394"> + <panel + follows="all" + layout="topleft" + name="toolbar_panel" + top="0" + left="0" + height="35" + width="394"> + <menu_button + follows="top|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left="5" + name="view_options_btn" + top="5" + width="31" /> + <button + follows="top|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_pad="4" + name="add_btn" + width="31"> + <commit_callback + function="Chats.add" /> + </button> + <button + follows="top|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="VoicePTT_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_pad="4" + name="call" + width="31"> + <commit_callback + function="Chats.add" /> + </button> + <button + follows="right|top" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Icon_Close_Foreground" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left="283" + name="close_btn" + width="31" /> + <button + follows="right|top" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TabIcon_Open_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_pad="5" + name="slide_left_btn" + width="31" /> + <button + follows="right|top" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TabIcon_Close_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_delta="0" + name="slide_right_btn" + width="31" /> + <button + follows="right|top" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="tearoffbox.tga" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_pad="5" + name="tear_off_btn" + width="31" /> + <button + follows="right|top" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Icon_Dock_Foreground" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_delta="0" + name="return_btn" + width="31" /> + </panel> <layout_stack animate="true" default_tab_group="2" follows="all" - height="320" + height="310" width="394" layout="topleft" orientation="horizontal" name="im_panels" tab_group="1" - top="20" + top_pad="0" left="0"> <layout_panel name="im_control_panel_holder" min_width="115" width="150" - height="320" + height="310" auto_resize="false"> <panel name="panel_im_control_panel" layout="topleft" - height="320" + height="310" width="150" follows="all"/> </layout_panel> @@ -46,39 +164,22 @@ tab_group="2" top="0" height="200" - width="254" + width="254" user_resize="true"> - <button - height="20" - follows="left|top" - top="0" - left="2" - image_overlay="TabIcon_Open_Off" - layout="topleft" - width="25" - name="slide_left_btn" /> - <button - height="20" - follows="left|top" - top="0" - left="2" - image_overlay="TabIcon_Close_Off" - width="25" - name="slide_right_btn" /> <chat_history - font="SansSerifSmall" - follows="left|right|top|bottom" - height="150" + font="SansSerifSmall" + follows="all" + height="170" name="chat_history" parse_highlights="true" parse_urls="true" - left="1" + left="1" width="249"> </chat_history> <line_editor bottom="0" follows="left|right|bottom" - font="SansSerifSmall" + font="SansSerifSmall" height="20" label="To" layout="bottomleft" @@ -88,4 +189,5 @@ </line_editor> </layout_panel> </layout_stack> + </view> </floater> -- cgit v1.2.3 From 905e56f8823e7513b35b9de4e5c6f8b0b6cca539 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 8 May 2012 23:30:34 +0300 Subject: CHUI-103 FIXED Implemented switching text view modes from pop-up menu --- indra/newview/app_settings/settings.xml | 1 - indra/newview/llimfloater.cpp | 54 ++++++++++++++++++++-- indra/newview/llimfloater.h | 6 ++- indra/newview/llnearbychat.cpp | 3 ++ .../skins/default/xui/en/floater_im_session.xml | 1 + .../default/xui/en/menu_im_session_showmodes.xml | 50 ++++++++++++++++++++ 6 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e6d0ed7dfa..d1fc8bdb7e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -24,7 +24,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>CrashHostUrl</key> <map> <key>Comment</key> diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index df3521ecb0..d02db458b4 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -94,7 +94,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) case IM_SESSION_GROUP_START: mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); break; - case IM_SESSION_INVITE: + case IM_SESSION_INVITE: if (gAgent.isInGroup(mSessionID)) { mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); @@ -104,7 +104,8 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); } break; - default: break; + default: + break; } } setOverlapsScreenChannel(true); @@ -112,6 +113,52 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); setDocked(true); + mCommitCallbackRegistrar.add("IMSession.Menu.Action", + boost::bind(&LLIMFloater::onIMSessionMenuItemClicked, this, _2)); + mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", + boost::bind(&LLIMFloater::onIMCompactExpandedMenuItemCheck, this, _2)); + mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.CheckItem", + boost::bind(&LLIMFloater::onIMShowModesMenuItemCheck, this, _2)); + mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", + boost::bind(&LLIMFloater::onIMShowModesMenuItemEnable, this, _2)); +} + +bool LLIMFloater::onIMCompactExpandedMenuItemCheck(const LLSD& userdata) +{ + std::string item = userdata.asString(); + bool is_plain_text_mode = gSavedSettings.getBOOL("PlainTextChatHistory"); + + return is_plain_text_mode? item == "compact_view" : item == "expanded_view"; +} + +bool LLIMFloater::onIMShowModesMenuItemCheck(const LLSD& userdata) +{ + return gSavedSettings.getBOOL(userdata.asString()); +} + +bool LLIMFloater::onIMShowModesMenuItemEnable(const LLSD& userdata) +{ + std::string item = userdata.asString(); + bool plain_text = gSavedSettings.getBOOL("PlainTextChatHistory"); + bool is_not_names = (item != "IMShowNamesForP2PConv"); + bool is_p2p_chat = (mDialog == IM_SESSION_P2P_INVITE || mDialog == IM_NOTHING_SPECIAL); + return (plain_text && (is_not_names || is_p2p_chat)); +} + +void LLIMFloater::onIMSessionMenuItemClicked(const LLSD& userdata) +{ + std::string item = userdata.asString(); + + if (item == "compact_view" || item == "expanded_view") + { + gSavedSettings.setBOOL("PlainTextChatHistory", item == "compact_view"); + } + else + { bool prev_value = gSavedSettings.getBOOL(item); + gSavedSettings.setBOOL(item, !prev_value); + } + + reloadMessages(); } void LLIMFloater::onFocusLost() @@ -635,11 +682,12 @@ void LLIMFloater::updateMessages() if (messages.size()) { + bool is_p2p_chat = (mDialog == IM_SESSION_P2P_INVITE || mDialog == IM_NOTHING_SPECIAL); LLSD chat_args; chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history; chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); chat_args["show_names_for_p2p_conv"] = - gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + (!is_p2p_chat) || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); std::ostringstream message; std::list<LLSD>::const_reverse_iterator iter = messages.rbegin(); diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 95aa214ff6..ff4eaed0b9 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -87,7 +87,6 @@ public: // called when docked floater's position has been set by chiclet void setPositioned(bool b) { mPositioned = b; }; - void onVisibilityChange(const LLSD& new_visibility); void processIMTyping(const LLIMInfo* im_info, BOOL typing); void processAgentListUpdates(const LLSD& body); @@ -148,6 +147,11 @@ private: static void* createPanelGroupControl(void* userdata); static void* createPanelAdHocControl(void* userdata); + bool onIMCompactExpandedMenuItemCheck(const LLSD& userdata); + bool onIMShowModesMenuItemCheck(const LLSD& userdata); + bool onIMShowModesMenuItemEnable(const LLSD& userdata); + void onIMSessionMenuItemClicked(const LLSD& userdata); + // Add the "User is typing..." indicator. void addTypingIndicator(const LLIMInfo* im_info); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a7303ad035..3a43750408 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -120,6 +120,9 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) tmp_chat.mFromName = chat.mFromName; LLSD chat_args = args; chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history; + chat_args["show_time"] = true; + chat_args["show_names_for_p2p_conv"] = true; + mChatHistory->appendMessage(chat, chat_args); } diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 3c3f4ad0e2..d90947a80a 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -31,6 +31,7 @@ height="35" width="394"> <menu_button + menu_filename="menu_im_session_showmodes.xml" follows="top|left" height="25" image_hover_unselected="Toolbar_Middle_Over" diff --git a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml new file mode 100644 index 0000000000..483f24afd0 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_modes" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_check + label="Compact view" + name="compact_view"> + <menu_item_check.on_click + function="IMSession.Menu.Action" + parameter="compact_view"/> + <menu_item_check.on_check + function="IMSession.Menu.CompactExpandedModes.CheckItem" + parameter="compact_view"/> + </menu_item_check> + <menu_item_check + label="Expanded view" + name="expanded_view"> + <menu_item_check.on_click + function="IMSession.Menu.Action" + parameter="expanded_view"/> + <menu_item_check.on_check + function="IMSession.Menu.CompactExpandedModes.CheckItem" + parameter="expanded_view"/> + </menu_item_check> + <menu_item_separator layout="topleft" /> + <menu_item_check name="IMShowTime" label="Show time"> + <menu_item_check.on_click + function="IMSession.Menu.Action" + parameter="IMShowTime" /> + <menu_item_check.on_check + function="IMSession.Menu.ShowModes.CheckItem" + parameter="IMShowTime" /> + <menu_item_check.on_enable + function="IMSession.Menu.ShowModes.Enable" + parameter="IMShowTime" /> + </menu_item_check> + <menu_item_check name="IMShowNamesForP2PConv" label="Show names in one-to-one conversations"> + <menu_item_check.on_click + function="IMSession.Menu.Action" + parameter="IMShowNamesForP2PConv" /> + <menu_item_check.on_check + function="IMSession.Menu.ShowModes.CheckItem" + parameter="IMShowNamesForP2PConv" /> + <menu_item_check.on_enable + function="IMSession.Menu.ShowModes.Enable" + parameter="IMShowNamesForP2PConv" /> + + </menu_item_check> +</toggleable_menu> -- cgit v1.2.3 From dfe6ce4be9b2b61a689e6cce41a9da91bd9a8b73 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 9 May 2012 21:41:46 +0300 Subject: Removed a recursive include declaration --- indra/newview/llspeakers.h | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index b9358cf37c..1c6f51e131 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -29,7 +29,6 @@ #include "llevent.h" #include "lleventtimer.h" -#include "llspeakers.h" #include "llvoicechannel.h" class LLSpeakerMgr; -- cgit v1.2.3 From 7eaeb88bc37a747ff82fd37df84592f54c88cdbf Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Thu, 10 May 2012 20:40:15 +0300 Subject: CHUI-105 WIP Added expand/collapse behavior for Conversations floater messages pane. --- indra/newview/llimfloater.cpp | 70 ++++++++++++++-------- indra/newview/llimfloater.h | 5 ++ indra/newview/llimfloatercontainer.cpp | 26 ++++++++ indra/newview/llimfloatercontainer.h | 4 ++ .../skins/default/xui/en/floater_im_container.xml | 44 +++++--------- .../skins/default/xui/en/floater_im_session.xml | 41 +++++-------- 6 files changed, 111 insertions(+), 79 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index d02db458b4..b2a5c4a64d 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -67,6 +67,8 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mDialog(IM_NOTHING_SPECIAL), mChatHistory(NULL), mInputEditor(NULL), + mExpandCollapseBtn(NULL), + mTearOffBtn(NULL), mSavedTitle(), mTypingStart(), mShouldSendTypingState(false), @@ -180,6 +182,17 @@ void LLIMFloater::onFocusReceived() } } +/*virtual*/ +void LLIMFloater::onOpen(const LLSD& key) +{ + LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); + if (host_floater) + { + // Show the messages pane when opening a floater hosted in the Conversations + host_floater->toggleMessagesPane(true); + } +} + // virtual void LLIMFloater::onClose(bool app_quitting) { @@ -291,19 +304,14 @@ BOOL LLIMFloater::postBuild() mControlPanel->setSessionId(mSessionID); mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel")); - LLButton* slide_left = getChild<LLButton>("slide_left_btn"); - slide_left->setVisible(mControlPanel->getParent()->getVisible()); - slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); - - LLButton* slide_right = getChild<LLButton>("slide_right_btn"); - slide_right->setVisible(!mControlPanel->getParent()->getVisible()); - slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); + getChild<LLButton>("close_btn")->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); - LLButton* return_btn = getChild<LLButton>("return_btn"); - return_btn->setCommitCallback(boost::bind(&LLFloater::onClickTearOff, this)); + mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); + mExpandCollapseBtn->setImageOverlay(getString(mControlPanel->getParent()->getVisible() ? "collapse_icon" : "expand_icon")); + mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); - LLButton* tear_off_btn = getChild<LLButton>("tear_off_btn"); - tear_off_btn->setCommitCallback(boost::bind(&LLFloater::onClickTearOff, this)); + mTearOffBtn = getChild<LLButton>("tear_off_btn"); + mTearOffBtn->setCommitCallback(boost::bind(&LLFloater::onClickTearOff, this)); mInputEditor = getChild<LLLineEditor>("chat_editor"); mInputEditor->setMaxTextLength(1023); @@ -427,12 +435,23 @@ void* LLIMFloater::createPanelAdHocControl(void* userdata) void LLIMFloater::onSlide() { - mControlPanel->getParent()->setVisible(!mControlPanel->getParent()->getVisible()); + LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); + if (host_floater) + { + // Hide the messages pane if a floater is hosted in the Conversations + host_floater->toggleMessagesPane(false); + } + else ///< floater is torn off + { + bool expand = !mControlPanel->getParent()->getVisible(); - gSavedSettings.setBOOL("IMShowControlPanel", mControlPanel->getParent()->getVisible()); + // Expand/collapse the IM control panel + mControlPanel->getParent()->setVisible(expand); - getChild<LLButton>("slide_left_btn")->setVisible(mControlPanel->getParent()->getVisible()); - getChild<LLButton>("slide_right_btn")->setVisible(!mControlPanel->getParent()->getVisible()); + gSavedSettings.setBOOL("IMShowControlPanel", expand); + + mExpandCollapseBtn->setImageOverlay(getString(expand ? "collapse_icon" : "expand_icon")); + } } //static @@ -1253,14 +1272,16 @@ void LLIMFloater::onClickCloseBtn() // virtual void LLIMFloater::updateTitleButtons() { - if (!mDragHandle) + // This gets called before LLIMFloater::postBuild() while some LLIMFloater members are NULL + if ( !mDragHandle + || !mControlPanel + || !mExpandCollapseBtn + || !mTearOffBtn) { return; } - LLMultiFloater* host_floater = getHost(); - - bool is_hosted = host_floater != NULL; + bool is_hosted = getHost() != NULL; if (is_hosted) ///< floater is hosted { for (S32 i = 0; i < BUTTON_COUNT; i++) @@ -1273,18 +1294,19 @@ void LLIMFloater::updateTitleButtons() // Hide the standard header buttons in a docked IM floater. mButtons[i]->setVisible(false); } + + mExpandCollapseBtn->setImageOverlay(getString("collapse_icon")); } else ///< floater is torn off { LLFloater::updateTitleButtons(); + + bool is_expanded = mControlPanel->getParent()->getVisible(); + mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); } // toggle floater's drag handle and title visibility mDragHandle->setVisible(!is_hosted); - - LLButton* return_btn = getChild<LLButton>("return_btn"); - return_btn->setVisible(!is_hosted); - LLButton* tear_off_btn = getChild<LLButton>("tear_off_btn"); - tear_off_btn->setVisible(is_hosted); + mTearOffBtn->setImageOverlay(getString(is_hosted ? "tear_off_icon" : "return_icon")); } diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index ff4eaed0b9..4f161449f7 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -33,6 +33,7 @@ #include "lltransientdockablefloater.h" class LLAvatarName; +class LLButton; class LLLineEditor; class LLPanelChatControlPanel; class LLChatHistory; @@ -59,6 +60,7 @@ public: /*virtual*/ void draw(); // LLFloater overrides + /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); @@ -182,6 +184,9 @@ private: bool mSessionInitialized; LLSD mQueuedMsgsForInit; + + LLButton* mExpandCollapseBtn; + LLButton* mTearOffBtn; }; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 9b5055fb98..c8b8cb208d 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -40,6 +40,7 @@ // LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) : LLMultiFloater(seed) + ,mMessagesPaneWidth(0) { mAutoResize = FALSE; LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); @@ -185,4 +186,29 @@ void LLIMFloaterContainer::setMinimized(BOOL b) } } +void LLIMFloaterContainer::toggleMessagesPane(bool expand) +{ + LLView* messages_pane = getChild<LLView>("im_box_tab_container"); + bool is_expanded = messages_pane->getVisible(); + if (is_expanded == expand) + { + return; + } + + // Store the messages pane width before collapsing it. + if (!expand) + { + LLView* conversations_pane = getChild<LLView>("conversations_pane"); + S32 horizontal_pad = messages_pane->getRect().mLeft - conversations_pane->getRect().mRight; + mMessagesPaneWidth = messages_pane->getRect().getWidth() + horizontal_pad; + } + + // Show/hide the messages pane. + messages_pane->setVisible(expand); + + S32 floater_width = getRect().getWidth(); + floater_width += (expand ? mMessagesPaneWidth : -mMessagesPaneWidth); + reshape(floater_width, getRect().getHeight()); +} + // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 93b91fe3cf..045f053b1c 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -60,12 +60,16 @@ public: virtual void setMinimized(BOOL b); + void toggleMessagesPane(bool expand); + private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; avatarID_panel_map_t mSessions; boost::signals2::connection mNewMessageConnection; void onNewMessageReceived(const LLSD& data); + + S32 mMessagesPaneWidth; }; #endif // LL_LLIMFLOATERCONTAINER_H diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index d19b36971f..8a0181bae4 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <multi_floater - can_close="false" + can_close="true" can_minimize="true" can_resize="true" height="430" @@ -17,7 +17,7 @@ border="true" follows="top|bottom|left" layout="topleft" - name="conversations_list" + name="conversations_pane" opaque="true" top="0" left="5" @@ -29,7 +29,7 @@ image_hover_unselected="Toolbar_Middle_Over" image_overlay="OptionsMenu_Off" image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" + image_unselected="Toolbar_Middle_Off" layout="topleft" left="5" name="sort_btn" @@ -39,7 +39,7 @@ follows="top|left" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" + image_overlay="AddItem_Off" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" @@ -55,34 +55,20 @@ image_hover_unselected="Toolbar_Middle_Over" image_overlay="TabIcon_Open_Off" image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" + image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" left="228" - name="slide_left_btn" + name="expand_collapse_btn" width="31" /> - <button - follows="right|top" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="TabIcon_Close_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - top="5" - left_delta="0" - name="slide_right_btn" - width="31" /> - </panel> + </panel> <panel_container - follows="all" - layout="topleft" - name="im_box_tab_container" - opaque="true" - top="0" - left_pad="15" - height="430" - width="389" - min_width="290"> - </panel_container> + follows="all" + height="430" + layout="topleft" + left_pad="15" + min_width="290" + name="im_box_tab_container" + top="0" + width="389"/> </multi_floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index d90947a80a..954f646bae 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -12,8 +12,21 @@ visible="false" width="394" can_resize="true" + can_tear_off="false" min_width="250" min_height="190"> + <floater.string + name="collapse_icon" + value="TabIcon_Open_Off"/> + <floater.string + name="expand_icon" + value="TabIcon_Close_Off"/> + <floater.string + name="tear_off_icon" + value="tearoffbox.tga"/> + <floater.string + name="return_icon" + value="Icon_Dock_Foreground"/> <view follows="all" layout="topleft" @@ -23,7 +36,7 @@ height="355" width="394"> <panel - follows="all" + follows="left|top|right" layout="topleft" name="toolbar_panel" top="0" @@ -95,19 +108,7 @@ layout="topleft" top="5" left_pad="5" - name="slide_left_btn" - width="31" /> - <button - follows="right|top" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="TabIcon_Close_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - top="5" - left_delta="0" - name="slide_right_btn" + name="expand_collapse_btn" width="31" /> <button follows="right|top" @@ -121,18 +122,6 @@ left_pad="5" name="tear_off_btn" width="31" /> - <button - follows="right|top" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Icon_Dock_Foreground" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - top="5" - left_delta="0" - name="return_btn" - width="31" /> </panel> <layout_stack animate="true" -- cgit v1.2.3 From df58153514f6b361c65efc5dd6d31d39f68603c0 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 14 May 2012 15:44:57 +0300 Subject: CHUI-113 WIP all voice controls is moved from a IM-control panel to the IM floater; IMControlPanel is removed; simplified voice button's listener behavior --- indra/newview/llchathistory.cpp | 14 +- indra/newview/llimfloater.cpp | 192 +++++++++++++----- indra/newview/llimfloater.h | 30 ++- indra/newview/llpanelimcontrolpanel.cpp | 221 +-------------------- indra/newview/llpanelimcontrolpanel.h | 31 +-- .../skins/default/xui/en/floater_im_session.xml | 16 +- 6 files changed, 202 insertions(+), 302 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index b70e98f22b..3214c95600 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -700,9 +700,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL return; } + bool from_me = chat.mFromID == gAgent.getID(); mEditor->setPlainText(use_plain_text_chat_history); - if (!mEditor->scrolledToEnd() && chat.mFromID != gAgent.getID() && !chat.mFromName.empty()) + if (!mEditor->scrolledToEnd() && !from_me && !chat.mFromName.empty()) { mUnreadChatSources.insert(chat.mFromName); mMoreChatPanel->setVisible(TRUE); @@ -777,6 +778,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL bool prependNewLineState = mEditor->getText().size() != 0; + // show timestamps and names in the compact mode if (use_plain_text_chat_history) { LLStyle::Params timestamp_style(style_params); @@ -820,7 +822,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL LLStyle::Params link_params(style_params); link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); - if (gAgentID == chat.mFromID) + if (from_me) { std::string localized_name; bool is_localized = LLTrans::findString(localized_name, "AgentNameSubst"); mEditor->appendText((is_localized? localized_name:"(You)") + delimiter, @@ -843,9 +845,9 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } } } - else + else // showing timestamp and name in the expanded mode { - prependNewLineState = 0; + prependNewLineState = false; LLView* view = NULL; LLInlineViewSegment::Params p; p.force_newline = true; @@ -953,7 +955,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL //MESSAGE TEXT PROCESSING //*HACK getting rid of redundant sender names in system notifications sent using sender name (see EXT-5010) - if (use_plain_text_chat_history && gAgentID != chat.mFromID && chat.mFromID.notNull()) + if (use_plain_text_chat_history && !from_me && chat.mFromID.notNull()) { std::string slurl_about = SLURL_APP_AGENT + chat.mFromID.asString() + SLURL_ABOUT; if (message.length() > slurl_about.length() && @@ -975,7 +977,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL mEditor->blockUndo(); // automatically scroll to end when receiving chat from myself - if (chat.mFromID == gAgentID) + if (from_me) { mEditor->setCursorAndScrollToEnd(); } diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index b2a5c4a64d..248e50eefa 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -51,14 +51,12 @@ #include "llchathistory.h" #include "llnotifications.h" #include "llviewerwindow.h" -#include "llvoicechannel.h" #include "lltransientfloatermgr.h" #include "llinventorymodel.h" #include "llrootview.h" #include "llspeakers.h" #include "llviewerchat.h" - LLIMFloater::LLIMFloater(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id), mControlPanel(NULL), @@ -85,11 +83,8 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mSessionInitialized = im_session->mSessionInitialized; mDialog = im_session->mType; - switch(mDialog){ - case IM_NOTHING_SPECIAL: - case IM_SESSION_P2P_INVITE: - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this); - break; + switch (mDialog) + { case IM_SESSION_CONFERENCE_START: mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); break; @@ -106,6 +101,8 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); } break; + case IM_NOTHING_SPECIAL: + case IM_SESSION_P2P_INVITE: default: break; } @@ -143,7 +140,8 @@ bool LLIMFloater::onIMShowModesMenuItemEnable(const LLSD& userdata) std::string item = userdata.asString(); bool plain_text = gSavedSettings.getBOOL("PlainTextChatHistory"); bool is_not_names = (item != "IMShowNamesForP2PConv"); - bool is_p2p_chat = (mDialog == IM_SESSION_P2P_INVITE || mDialog == IM_NOTHING_SPECIAL); + LLIMModel::LLIMSession* im_session = LLIMModel::instance().findIMSession(mSessionID); + bool is_p2p_chat = im_session && im_session->isP2PSessionType(); return (plain_text && (is_not_names || is_p2p_chat)); } @@ -289,6 +287,12 @@ void LLIMFloater::sendMsg() LLIMFloater::~LLIMFloater() { + mVoiceChannelStateChangeConnection.disconnect(); + if(LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->removeObserver(this); + } + LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); } @@ -301,15 +305,27 @@ BOOL LLIMFloater::postBuild() mOtherParticipantUUID = other_party_id; } - mControlPanel->setSessionId(mSessionID); - mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel")); + boundVoiceChannel(); getChild<LLButton>("close_btn")->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); - mExpandCollapseBtn->setImageOverlay(getString(mControlPanel->getParent()->getVisible() ? "collapse_icon" : "expand_icon")); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); + if (mControlPanel) + { + mControlPanel->setSessionId(mSessionID); + mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel")); + + mExpandCollapseBtn->setImageOverlay( + getString(mControlPanel->getParent()->getVisible() ? "collapse_icon" : "expand_icon")); + } + else + { + mExpandCollapseBtn->setEnabled(false); + getChild<LLLayoutPanel>("im_control_panel_holder")->setVisible(false); + } + mTearOffBtn = getChild<LLButton>("tear_off_btn"); mTearOffBtn->setCommitCallback(boost::bind(&LLFloater::onClickTearOff, this)); @@ -358,6 +374,10 @@ BOOL LLIMFloater::postBuild() std::string session_name(LLIMModel::instance().getName(mSessionID)); updateSessionName(session_name, session_name); } + + childSetAction("voice_call_btn", boost::bind(&LLIMFloater::onCallButtonClicked, this)); + + LLVoiceClient::getInstance()->addObserver(this); //*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla" //see LLFloaterIMPanel for how it is done (IB) @@ -372,6 +392,89 @@ BOOL LLIMFloater::postBuild() } } +void LLIMFloater::boundVoiceChannel() +{ + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + if(voice_channel) + { + mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback( + boost::bind(&LLIMFloater::onVoiceChannelStateChanged, this, _1, _2)); + + //call (either p2p, group or ad-hoc) can be already in started state + updateCallState(voice_channel->getState()); + } +} + +void LLIMFloater::updateCallState(LLVoiceChannel::EState state) +{ + bool is_call_started = state >= LLVoiceChannel::STATE_CALL_STARTED; + getChild<LLButton>("voice_call_btn")->setImageOverlay( + is_call_started? getString("call_btn_stop") : getString("call_btn_start")); + enableDisableCallBtn(); + +} + +void LLIMFloater::enableDisableCallBtn() +{ + bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() + && LLVoiceClient::getInstance()->isVoiceWorking(); + + LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionID); + + if (!session) + { + getChildView("voice_call_btn")->setEnabled(false); + return; + } + + bool session_initialized = session->mSessionInitialized; + bool callback_enabled = session->mCallBackEnabled; + + BOOL enable_connect = session_initialized + && voice_enabled + && callback_enabled; + getChildView("voice_call_btn")->setEnabled(enable_connect); +} + + +void LLIMFloater::onCallButtonClicked() +{ + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + if (voice_channel) + { + bool is_call_active = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED; + if (is_call_active) + { + gIMMgr->endCall(mSessionID); + } + else + { + gIMMgr->startCall(mSessionID); + } + } +} + +/*void LLIMFloater::onOpenVoiceControlsClicked() +{ + LLFloaterReg::showInstance("voice_controls"); +}*/ + +void LLIMFloater::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) + { + return; + } + + enableDisableCallBtn(); +} + +void LLIMFloater::onVoiceChannelStateChanged( + const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) +{ + updateCallState(new_state); +} + void LLIMFloater::updateSessionName(const std::string& ui_title, const std::string& ui_label) { @@ -404,17 +507,6 @@ void LLIMFloater::draw() LLTransientDockableFloater::draw(); } - -// static -void* LLIMFloater::createPanelIMControl(void* userdata) -{ - LLIMFloater *self = (LLIMFloater*)userdata; - self->mControlPanel = new LLPanelIMControlPanel(); - self->mControlPanel->setXMLFilename("panel_im_control_panel.xml"); - return self->mControlPanel; -} - - // static void* LLIMFloater::createPanelGroupControl(void* userdata) { @@ -443,14 +535,17 @@ void LLIMFloater::onSlide() } else ///< floater is torn off { - bool expand = !mControlPanel->getParent()->getVisible(); + if (mControlPanel) + { + bool expand = !mControlPanel->getParent()->getVisible(); - // Expand/collapse the IM control panel - mControlPanel->getParent()->setVisible(expand); + // Expand/collapse the IM control panel + mControlPanel->getParent()->setVisible(expand); - gSavedSettings.setBOOL("IMShowControlPanel", expand); + gSavedSettings.setBOOL("IMShowControlPanel", expand); - mExpandCollapseBtn->setImageOverlay(getString(expand ? "collapse_icon" : "expand_icon")); + mExpandCollapseBtn->setImageOverlay(getString(expand ? "collapse_icon" : "expand_icon")); + } } } @@ -659,15 +754,13 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) { mSessionID = im_session_id; setKey(im_session_id); - mControlPanel->setSessionId(im_session_id); + if (mControlPanel) + { + mControlPanel->setSessionId(im_session_id); + } + boundVoiceChannel(); } - // updating "Call" button from group control panel here to enable it without placing into draw() (EXT-4796) - if(gAgent.isInGroup(im_session_id)) - { - mControlPanel->updateCallButton(); - } - //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) @@ -910,13 +1003,6 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body) } } -void LLIMFloater::updateChatHistoryStyle() -{ - mChatHistory->clear(); - mLastMessageIndex = -1; - updateMessages(); -} - void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue) { LLFontGL* font = LLViewerChat::getChatFont(); @@ -927,11 +1013,10 @@ void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue) LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); if (floater) { - floater->updateChatHistoryStyle(); + floater->reloadMessages(); floater->mInputEditor->setFont(font); } } - } void LLIMFloater::processSessionUpdate(const LLSD& session_update) @@ -1152,7 +1237,6 @@ void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info) speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE); } } - } } @@ -1274,7 +1358,7 @@ void LLIMFloater::updateTitleButtons() { // This gets called before LLIMFloater::postBuild() while some LLIMFloater members are NULL if ( !mDragHandle - || !mControlPanel + //|| !mControlPanel || !mExpandCollapseBtn || !mTearOffBtn) { @@ -1301,8 +1385,22 @@ void LLIMFloater::updateTitleButtons() { LLFloater::updateTitleButtons(); - bool is_expanded = mControlPanel->getParent()->getVisible(); - mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); + if (mControlPanel) + { + bool is_expanded = mControlPanel->getParent()->getVisible(); + mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); + } + } + + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); + if (session) + { + mExpandCollapseBtn->setEnabled(is_hosted || !session->isP2PSessionType()); + } + else + { + llwarns << "Empty session." << llendl; + return; } // toggle floater's drag handle and title visibility diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 4f161449f7..40b3fff8f4 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -31,6 +31,8 @@ #include "lllogchat.h" #include "lltooldraganddrop.h" #include "lltransientdockablefloater.h" +#include "llvoicechannel.h" +#include "llvoiceclient.h" class LLAvatarName; class LLButton; @@ -44,14 +46,16 @@ class LLInventoryCategory; * Individual IM window that appears at the bottom of the screen, * optionally "docked" to the bottom tray. */ -class LLIMFloater : public LLTransientDockableFloater +class LLIMFloater + : public LLTransientDockableFloater + , public LLVoiceClientStatusObserver { LOG_CLASS(LLIMFloater); public: LLIMFloater(const LLUUID& session_id); virtual ~LLIMFloater(); - + // LLView overrides /*virtual*/ BOOL postBuild(); /*virtual*/ void setVisible(BOOL visible); @@ -90,11 +94,20 @@ public: // called when docked floater's position has been set by chiclet void setPositioned(bool b) { mPositioned = b; }; void onVisibilityChange(const LLSD& new_visibility); + + // Implements LLVoiceClientStatusObserver::onChange() to enable the call + // button when voice is available + void onChange(EStatusType status, const std::string &channelURI, + bool proximal); + + virtual void onVoiceChannelStateChanged( + const LLVoiceChannel::EState& old_state, + const LLVoiceChannel::EState& new_state); + void processIMTyping(const LLIMInfo* im_info, BOOL typing); void processAgentListUpdates(const LLSD& body); void processSessionUpdate(const LLSD& session_update); - void updateChatHistoryStyle(); static void processChatHistoryStyleUpdate(const LLSD& newvalue); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, @@ -153,6 +166,13 @@ private: bool onIMShowModesMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemEnable(const LLSD& userdata); void onIMSessionMenuItemClicked(const LLSD& userdata); + void onCallButtonClicked(); + + void boundVoiceChannel(); + void enableDisableCallBtn(); + + // refresh a visual state of the Call button + void updateCallState(LLVoiceChannel::EState state); // Add the "User is typing..." indicator. void addTypingIndicator(const LLIMInfo* im_info); @@ -185,9 +205,11 @@ private: bool mSessionInitialized; LLSD mQueuedMsgsForInit; + // connection to voice channel state change signal + boost::signals2::connection mVoiceChannelStateChangeConnection; + LLButton* mExpandCollapseBtn; LLButton* mTearOffBtn; }; - #endif // LL_IMFLOATER_H diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index eda0749cdb..f0fc15b4d8 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -1,31 +1,30 @@ -/** +/** * @file llpanelavatar.cpp * @brief LLPanelAvatar and related class implementations * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" - #include "llfloaterreg.h" #include "llpanelimcontrolpanel.h" @@ -39,92 +38,15 @@ #include "llavatarlist.h" #include "llparticipantlist.h" #include "llimview.h" -#include "llvoicechannel.h" #include "llspeakers.h" #include "lltrans.h" -void LLPanelChatControlPanel::onCallButtonClicked() -{ - gIMMgr->startCall(mSessionId); -} - -void LLPanelChatControlPanel::onEndCallButtonClicked() -{ - gIMMgr->endCall(mSessionId); -} - -void LLPanelChatControlPanel::onOpenVoiceControlsClicked() -{ - LLFloaterReg::showInstance("voice_controls"); -} - -void LLPanelChatControlPanel::onChange(EStatusType status, const std::string &channelURI, bool proximal) -{ - if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) - { - return; - } - - updateCallButton(); -} - -void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) -{ - updateButtons(new_state); -} - -void LLPanelChatControlPanel::updateCallButton() -{ - // hide/show call button - bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); - - LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId); - - if (!session) - { - getChildView("call_btn")->setEnabled(false); - return; - } - - bool session_initialized = session->mSessionInitialized; - bool callback_enabled = session->mCallBackEnabled; - - BOOL enable_connect = session_initialized - && voice_enabled - && callback_enabled; - getChildView("call_btn")->setEnabled(enable_connect); -} - -void LLPanelChatControlPanel::updateButtons(LLVoiceChannel::EState state) -{ - bool is_call_started = state >= LLVoiceChannel::STATE_CALL_STARTED; - getChildView("end_call_btn_panel")->setVisible( is_call_started); - getChildView("voice_ctrls_btn_panel")->setVisible( is_call_started && findChild<LLView>("voice_ctrls_btn_panel")); - getChildView("call_btn_panel")->setVisible( ! is_call_started); - - getChildView("volume_ctrl_panel")->setVisible(state == LLVoiceChannel::STATE_CONNECTED); - - updateCallButton(); - -} - LLPanelChatControlPanel::~LLPanelChatControlPanel() { - mVoiceChannelStateChangeConnection.disconnect(); - if(LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->removeObserver(this); - } } BOOL LLPanelChatControlPanel::postBuild() { - childSetAction("call_btn", boost::bind(&LLPanelChatControlPanel::onCallButtonClicked, this)); - childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this)); - childSetAction("voice_ctrls_btn", boost::bind(&LLPanelChatControlPanel::onOpenVoiceControlsClicked, this)); - - LLVoiceClient::getInstance()->addObserver(this); - return TRUE; } @@ -132,14 +54,6 @@ void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id) { //Method is called twice for AdHoc and Group chat. Second time when server init reply received mSessionId = session_id; - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionId); - if(voice_channel) - { - mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback(boost::bind(&LLPanelChatControlPanel::onVoiceChannelStateChanged, this, _1, _2)); - - //call (either p2p, group or ad-hoc) can be already in started state - updateButtons(voice_channel->getState()); - } } LLPanelIMControlPanel::LLPanelIMControlPanel() @@ -148,29 +62,27 @@ LLPanelIMControlPanel::LLPanelIMControlPanel() LLPanelIMControlPanel::~LLPanelIMControlPanel() { - LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); +// LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); } BOOL LLPanelIMControlPanel::postBuild() { - childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this)); +/* childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this)); childSetAction("add_friend_btn", boost::bind(&LLPanelIMControlPanel::onAddFriendButtonClicked, this)); childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this)); childSetAction("teleport_btn", boost::bind(&LLPanelIMControlPanel::onTeleportButtonClicked, this)); childSetAction("pay_btn", boost::bind(&LLPanelIMControlPanel::onPayButtonClicked, this)); - childSetAction("mute_btn", boost::bind(&LLPanelIMControlPanel::onClickMuteVolume, this)); childSetAction("block_btn", boost::bind(&LLPanelIMControlPanel::onClickBlock, this)); childSetAction("unblock_btn", boost::bind(&LLPanelIMControlPanel::onClickUnblock, this)); - - getChild<LLUICtrl>("volume_slider")->setCommitCallback(boost::bind(&LLPanelIMControlPanel::onVolumeChange, this, _2)); getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId())); setFocusReceivedCallback(boost::bind(&LLPanelIMControlPanel::onFocusReceived, this)); - +*/ return LLPanelChatControlPanel::postBuild(); + } void LLPanelIMControlPanel::draw() @@ -180,56 +92,14 @@ void LLPanelIMControlPanel::draw() getChild<LLUICtrl>("block_btn_panel")->setVisible(!is_muted); getChild<LLUICtrl>("unblock_btn_panel")->setVisible(is_muted); - if (getChildView("volume_ctrl_panel")->getVisible()) - { - - bool is_muted_voice = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat); - - LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); - mute_btn->setValue( is_muted_voice ); - - LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); - volume_slider->setEnabled( !is_muted_voice ); - - F32 volume; - - if (is_muted_voice) - { - // it's clearer to display their volume as zero - volume = 0.f; - } - else - { - // actual volume - volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); - } - volume_slider->setValue( (F64)volume ); - } LLPanelChatControlPanel::draw(); } -void LLPanelIMControlPanel::onClickMuteVolume() -{ - // By convention, we only display and toggle voice mutes, not all mutes - LLMuteList* mute_list = LLMuteList::getInstance(); - bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat); - - LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT); - if (!is_muted) - { - mute_list->add(mute, LLMute::flagVoiceChat); - } - else - { - mute_list->remove(mute, LLMute::flagVoiceChat); - } -} - void LLPanelIMControlPanel::onClickBlock() { LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT); - + LLMuteList::getInstance()->add(mute); } @@ -240,12 +110,6 @@ void LLPanelIMControlPanel::onClickUnblock() LLMuteList::getInstance()->remove(mute); } -void LLPanelIMControlPanel::onVolumeChange(const LLSD& data) -{ - F32 volume = (F32)data.asReal(); - LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); -} - void LLPanelIMControlPanel::onTeleportButtonClicked() { LLAvatarActions::offerTeleport(mAvatarID); @@ -281,62 +145,6 @@ void LLPanelIMControlPanel::onFocusReceived() } } -void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id) -{ - LLPanelChatControlPanel::setSessionId(session_id); - - LLIMModel& im_model = LLIMModel::instance(); - - LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); - mAvatarID = im_model.getOtherParticipantID(session_id); - LLAvatarTracker::instance().addParticularFriendObserver(mAvatarID, this); - - // Disable "Add friend" button for friends. - getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(mAvatarID)); - - // Disable "Teleport" button if friend is offline - if(LLAvatarActions::isFriend(mAvatarID)) - { - getChildView("teleport_btn")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(mAvatarID)); - } - - getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(mAvatarID); - - // Disable most profile buttons if the participant is - // not really an SL avatar (e.g., an Avaline caller). - LLIMModel::LLIMSession* im_session = - im_model.findIMSession(session_id); - if( im_session && !im_session->mOtherParticipantIsAvatar ) - { - getChildView("view_profile_btn")->setEnabled(FALSE); - getChildView("add_friend_btn")->setEnabled(FALSE); - - getChildView("share_btn")->setEnabled(FALSE); - getChildView("teleport_btn")->setEnabled(FALSE); - getChildView("pay_btn")->setEnabled(FALSE); - - getChild<LLTextBox>("avatar_name")->setValue(im_session->mName); - getChild<LLTextBox>("avatar_name")->setToolTip(im_session->mName); - } - else - { - // If the participant is an avatar, fetch the currect name - gCacheName->get(mAvatarID, false, - boost::bind(&LLPanelIMControlPanel::onNameCache, this, _1, _2, _3)); - } -} - -//virtual -void LLPanelIMControlPanel::changed(U32 mask) -{ - getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(mAvatarID)); - - // Disable "Teleport" button if friend is offline - if(LLAvatarActions::isFriend(mAvatarID)) - { - getChildView("teleport_btn")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(mAvatarID)); - } -} void LLPanelIMControlPanel::onNameCache(const LLUUID& id, const std::string& full_name, bool is_group) { @@ -398,19 +206,13 @@ void LLPanelGroupControlPanel::onSortMenuItemClicked(const LLSD& userdata) } -void LLPanelGroupControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) -{ - LLPanelChatControlPanel::onVoiceChannelStateChanged(old_state, new_state); - mParticipantList->setSpeakingIndicatorsVisible(new_state >= LLVoiceChannel::STATE_CALL_STARTED); -} - void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id) { LLPanelChatControlPanel::setSessionId(session_id); mGroupID = session_id; - // for group and Ad-hoc chat we need to include agent into list + // for group and Ad-hoc chat we need to include agent into list if(!mParticipantList) { LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id); @@ -428,4 +230,3 @@ BOOL LLPanelAdHocControlPanel::postBuild() //We don't need LLPanelGroupControlPanel::postBuild() to be executed as there is no group_info_btn at AdHoc chat return LLPanelChatControlPanel::postBuild(); } - diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h index bba847b5d4..3466da33a1 100644 --- a/indra/newview/llpanelimcontrolpanel.h +++ b/indra/newview/llpanelimcontrolpanel.h @@ -28,14 +28,12 @@ #define LL_LLPANELIMCONTROLPANEL_H #include "llpanel.h" -#include "llvoicechannel.h" #include "llcallingcard.h" class LLParticipantList; -class LLPanelChatControlPanel +class LLPanelChatControlPanel : public LLPanel - , public LLVoiceClientStatusObserver { public: LLPanelChatControlPanel() : @@ -44,21 +42,6 @@ public: virtual BOOL postBuild(); - void onCallButtonClicked(); - void onEndCallButtonClicked(); - void onOpenVoiceControlsClicked(); - - // Implements LLVoiceClientStatusObserver::onChange() to enable the call - // button when voice is available - /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); - - virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); - - void updateButtons(LLVoiceChannel::EState state); - - // Enables/disables call button depending on voice availability - void updateCallButton(); - virtual void setSessionId(const LLUUID& session_id); const LLUUID& getSessionId() { return mSessionId; } @@ -70,7 +53,7 @@ private: }; -class LLPanelIMControlPanel : public LLPanelChatControlPanel, LLFriendObserver +class LLPanelIMControlPanel : public LLPanelChatControlPanel { public: LLPanelIMControlPanel(); @@ -78,10 +61,7 @@ public: BOOL postBuild(); - void setSessionId(const LLUUID& session_id); - - // LLFriendObserver trigger - virtual void changed(U32 mask); + //void setSessionId(const LLUUID& session_id); protected: void onNameCache(const LLUUID& id, const std::string& full_name, bool is_group); @@ -93,13 +73,9 @@ private: void onTeleportButtonClicked(); void onPayButtonClicked(); void onFocusReceived(); - - void onClickMuteVolume(); void onClickBlock(); void onClickUnblock(); /*virtual*/ void draw(); - void onVolumeChange(const LLSD& data); - LLUUID mAvatarID; }; @@ -123,7 +99,6 @@ protected: private: void onGroupInfoButtonClicked(); void onSortMenuItemClicked(const LLSD& userdata); - /*virtual*/ void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); }; class LLPanelAdHocControlPanel : public LLPanelGroupControlPanel diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 954f646bae..a332bb5b12 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -15,6 +15,8 @@ can_tear_off="false" min_width="250" min_height="190"> + <floater.string name="call_btn_start">VoicePTT_Off</floater.string> + <floater.string name="call_btn_stop">VoicePTT_On</floater.string> <floater.string name="collapse_icon" value="TabIcon_Open_Off"/> @@ -47,10 +49,10 @@ menu_filename="menu_im_session_showmodes.xml" follows="top|left" height="25" - image_hover_unselected="Toolbar_Middle_Over" + image_hover_unselected="Toolbar_Left_Over" image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" + image_selected="Toolbar_Left_Selected" + image_unselected="Toolbar_Left_Off" layout="topleft" left="5" name="view_options_btn" @@ -74,14 +76,14 @@ <button follows="top|left" height="25" - image_hover_unselected="Toolbar_Middle_Over" + image_hover_unselected="Toolbar_Right_Over" image_overlay="VoicePTT_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" + image_selected="Toolbar_Right_Selected" + image_unselected="Toolbar_Right_Off" layout="topleft" top="5" left_pad="4" - name="call" + name="voice_call_btn" width="31"> <commit_callback function="Chats.add" /> -- cgit v1.2.3 From 6cd68b321147136b2ad79fdbfeafdd2ffc39f1a3 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 14 May 2012 16:03:39 +0300 Subject: Formatting fixes --- indra/newview/llimfloater.cpp | 299 ++++++++++++++++++++++-------------------- indra/newview/llimfloater.h | 35 +++-- 2 files changed, 171 insertions(+), 163 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 248e50eefa..cb489627fb 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -115,11 +115,11 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mCommitCallbackRegistrar.add("IMSession.Menu.Action", boost::bind(&LLIMFloater::onIMSessionMenuItemClicked, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", - boost::bind(&LLIMFloater::onIMCompactExpandedMenuItemCheck, this, _2)); + boost::bind(&LLIMFloater::onIMCompactExpandedMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.CheckItem", - boost::bind(&LLIMFloater::onIMShowModesMenuItemCheck, this, _2)); + boost::bind(&LLIMFloater::onIMShowModesMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", - boost::bind(&LLIMFloater::onIMShowModesMenuItemEnable, this, _2)); + boost::bind(&LLIMFloater::onIMShowModesMenuItemEnable, this, _2)); } bool LLIMFloater::onIMCompactExpandedMenuItemCheck(const LLSD& userdata) @@ -154,7 +154,8 @@ void LLIMFloater::onIMSessionMenuItemClicked(const LLSD& userdata) gSavedSettings.setBOOL("PlainTextChatHistory", item == "compact_view"); } else - { bool prev_value = gSavedSettings.getBOOL(item); + { + bool prev_value = gSavedSettings.getBOOL(item); gSavedSettings.setBOOL(item, !prev_value); } @@ -164,7 +165,7 @@ void LLIMFloater::onIMSessionMenuItemClicked(const LLSD& userdata) void LLIMFloater::onFocusLost() { LLIMModel::getInstance()->resetActiveSessionID(); - + LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, false); } @@ -205,8 +206,8 @@ void LLIMFloater::onClose(bool app_quitting) } /* static */ -void LLIMFloater::newIMCallback(const LLSD& data){ - +void LLIMFloater::newIMCallback(const LLSD& data) +{ if (data["num_unread"].asInteger() > 0 || data["from_id"].asUUID().isNull()) { LLUUID session_id = data["session_id"].asUUID(); @@ -214,7 +215,7 @@ void LLIMFloater::newIMCallback(const LLSD& data){ LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); if (floater == NULL) return; - // update if visible, otherwise will be updated when opened + // update if visible, otherwise will be updated when opened if (floater->getVisible()) { floater->updateMessages(); @@ -229,7 +230,7 @@ void LLIMFloater::onVisibilityChange(const LLSD& new_visibility) LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); if (visible && voice_channel && - voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED) + voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED) { LLFloaterReg::showInstance("voice_call", mSessionID); } @@ -248,9 +249,9 @@ void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata ) void LLIMFloater::sendMsg() { - if (!gAgent.isGodlike() - && (mDialog == IM_NOTHING_SPECIAL) - && mOtherParticipantUUID.isNull()) + if (!gAgent.isGodlike() + && (mDialog == IM_NOTHING_SPECIAL) + && mOtherParticipantUUID.isNull()) { llinfos << "Cannot send IM to everyone unless you're a god." << llendl; return; @@ -259,16 +260,15 @@ void LLIMFloater::sendMsg() if (mInputEditor) { LLWString text = mInputEditor->getConvertedText(); - if(!text.empty()) + if (!text.empty()) { // Truncate and convert to UTF8 for transport std::string utf8_text = wstring_to_utf8str(text); utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); - + if (mSessionInitialized) { - LLIMModel::sendMessage(utf8_text, mSessionID, - mOtherParticipantUUID,mDialog); + LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog); } else { @@ -283,8 +283,6 @@ void LLIMFloater::sendMsg() } } - - LLIMFloater::~LLIMFloater() { mVoiceChannelStateChangeConnection.disconnect(); @@ -299,7 +297,8 @@ LLIMFloater::~LLIMFloater() //virtual BOOL LLIMFloater::postBuild() { - const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID); + const LLUUID& other_party_id = + LLIMModel::getInstance()->getOtherParticipantID(mSessionID); if (other_party_id.notNull()) { mOtherParticipantUUID = other_party_id; @@ -335,8 +334,8 @@ BOOL LLIMFloater::postBuild() mInputEditor->setEnableLineHistory(TRUE); LLFontGL* font = LLViewerChat::getChatFont(); - mInputEditor->setFont(font); - + mInputEditor->setFont(font); + mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) ); mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) ); mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this ); @@ -346,7 +345,7 @@ BOOL LLIMFloater::postBuild() mInputEditor->setPassDelete( TRUE ); childSetCommitCallback("chat_editor", onSendMsg, this); - + mChatHistory = getChild<LLChatHistory>("chat_history"); setDocked(true); @@ -355,19 +354,19 @@ BOOL LLIMFloater::postBuild() // Disable input editor if session cannot accept text LLIMModel::LLIMSession* im_session = - LLIMModel::instance().findIMSession(mSessionID); - if( im_session && !im_session->mTextIMPossible ) + LLIMModel::instance().findIMSession(mSessionID); + if ( im_session && !im_session->mTextIMPossible ) { mInputEditor->setEnabled(FALSE); mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label")); } - if ( im_session && im_session->isP2PSessionType()) + if (im_session && im_session->isP2PSessionType()) { // look up display name for window title LLAvatarNameCache::get(im_session->mOtherParticipantID, - boost::bind(&LLIMFloater::onAvatarNameCache, - this, _1, _2)); + boost::bind(&LLIMFloater::onAvatarNameCache, + this, _1, _2)); } else { @@ -382,7 +381,7 @@ BOOL LLIMFloater::postBuild() //*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla" //see LLFloaterIMPanel for how it is done (IB) - if(isChatMultiTab()) + if (isChatMultiTab()) { return LLFloater::postBuild(); } @@ -476,14 +475,14 @@ void LLIMFloater::onVoiceChannelStateChanged( } void LLIMFloater::updateSessionName(const std::string& ui_title, - const std::string& ui_label) + const std::string& ui_label) { mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + ui_label); - setTitle(ui_title); + setTitle(ui_title); } void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id, - const LLAvatarName& av_name) + const LLAvatarName& av_name) { // Use display name only for labels, as the extended name will be in the // floater title @@ -498,7 +497,7 @@ void LLIMFloater::draw() if ( mMeTyping ) { // Time out if user hasn't typed for a while. - if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS ) + if (mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS) { setTyping(false); } @@ -510,7 +509,7 @@ void LLIMFloater::draw() // static void* LLIMFloater::createPanelGroupControl(void* userdata) { - LLIMFloater *self = (LLIMFloater*)userdata; + LLIMFloater *self = (LLIMFloater*) userdata; self->mControlPanel = new LLPanelGroupControlPanel(self->mSessionID); self->mControlPanel->setXMLFilename("panel_group_control_panel.xml"); return self->mControlPanel; @@ -519,7 +518,7 @@ void* LLIMFloater::createPanelGroupControl(void* userdata) // static void* LLIMFloater::createPanelAdHocControl(void* userdata) { - LLIMFloater *self = (LLIMFloater*)userdata; + LLIMFloater *self = (LLIMFloater*) userdata; self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID); self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml"); return self->mControlPanel; @@ -554,14 +553,15 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) { closeHiddenIMToasts(); - if (!gIMMgr->hasSession(session_id)) return NULL; + if (!gIMMgr->hasSession(session_id)) + return NULL; - if(!isChatMultiTab()) + if (!isChatMultiTab()) { //hide all LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); - iter != inst_list.end(); ++iter) + iter != inst_list.end(); ++iter) { LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); if (floater && floater->isDocked()) @@ -574,9 +574,10 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) bool exist = findInstance(session_id); LLIMFloater* floater = getInstance(session_id); - if (!floater) return NULL; + if (!floater) + return NULL; - if(isChatMultiTab()) + if (isChatMultiTab()) { LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); @@ -586,7 +587,7 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) // LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; // TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END; - + if (floater_container) { floater_container->addFloater(floater, TRUE, i_pt); @@ -629,16 +630,16 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock) { // update notification channel state LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> - (LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); - - if(!isChatMultiTab()) + (LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + + if (!isChatMultiTab()) { LLTransientDockableFloater::setDocked(docked, pop_on_undock); } // update notification channel state - if(channel) + if (channel) { channel->updateShowToastsState(); channel->redrawToasts(); @@ -648,12 +649,12 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock) void LLIMFloater::setVisible(BOOL visible) { LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> - (LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + (LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); LLTransientDockableFloater::setVisible(visible); // update notification channel state - if(channel) + if (channel) { channel->updateShowToastsState(); channel->redrawToasts(); @@ -674,10 +675,10 @@ void LLIMFloater::setVisible(BOOL visible) } } - if(!visible) + if (!visible) { LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(mSessionID); - if(chiclet) + if (chiclet) { chiclet->setToggleState(false); } @@ -686,13 +687,14 @@ void LLIMFloater::setVisible(BOOL visible) BOOL LLIMFloater::getVisible() { - if(isChatMultiTab()) + if (isChatMultiTab()) { - LLIMFloaterContainer* im_container = LLIMFloaterContainer::getInstance(); - + LLIMFloaterContainer* im_container = + LLIMFloaterContainer::getInstance(); + // Treat inactive floater as invisible. bool is_active = im_container->getActiveFloater() == this; - + //torn off floater is always inactive if (!is_active && getHost() != im_container) { @@ -700,7 +702,8 @@ BOOL LLIMFloater::getVisible() } // getVisible() returns TRUE when Tabbed IM window is minimized. - return is_active && !im_container->isMinimized() && im_container->getVisible(); + return is_active && !im_container->isMinimized() + && im_container->getVisible(); } else { @@ -711,9 +714,10 @@ BOOL LLIMFloater::getVisible() //static bool LLIMFloater::toggle(const LLUUID& session_id) { - if(!isChatMultiTab()) + if (!isChatMultiTab()) { - LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); + LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>( + "impanel", session_id); if (floater && floater->getVisible() && floater->hasFocus()) { // clicking on chiclet to close floater just hides it to maintain existing @@ -721,7 +725,7 @@ bool LLIMFloater::toggle(const LLUUID& session_id) floater->setVisible(false); return false; } - else if(floater && (!floater->isDocked() || floater->getVisible() && !floater->hasFocus())) + else if (floater && (!floater->isDocked() || floater->getVisible() && !floater->hasFocus())) { floater->setVisible(TRUE); floater->setFocus(TRUE); @@ -763,16 +767,15 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) - //need to send delayed messaged collected while waiting for session initialization - if (!mQueuedMsgsForInit.size()) return; + if (!mQueuedMsgsForInit.size()) + return; LLSD::array_iterator iter; - for ( iter = mQueuedMsgsForInit.beginArray(); - iter != mQueuedMsgsForInit.endArray(); - ++iter) + for (iter = mQueuedMsgsForInit.beginArray(); + iter != mQueuedMsgsForInit.endArray(); ++iter) { LLIMModel::sendMessage(iter->asString(), mSessionID, - mOtherParticipantUUID, mDialog); + mOtherParticipantUUID, mDialog); } } @@ -785,11 +788,11 @@ void LLIMFloater::updateMessages() // we shouldn't reset unread message counters if IM floater doesn't have focus if (hasFocus()) { - LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1); + LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex + 1); } else { - LLIMModel::instance().getMessagesSilently(mSessionID, messages, mLastMessageIndex+1); + LLIMModel::instance().getMessagesSilently(mSessionID, messages, mLastMessageIndex + 1); } if (messages.size()) @@ -798,8 +801,7 @@ void LLIMFloater::updateMessages() LLSD chat_args; chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history; chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); - chat_args["show_names_for_p2p_conv"] = - (!is_p2p_chat) || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + chat_args["show_names_for_p2p_conv"] = (!is_p2p_chat) || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); std::ostringstream message; std::list<LLSD>::const_reverse_iterator iter = messages.rbegin(); @@ -830,8 +832,8 @@ void LLIMFloater::updateMessages() { // remove embedded notification from channel LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> - (LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + (LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); if (getVisible()) { // toast will be automatically closed since it is not storable toast @@ -849,7 +851,7 @@ void LLIMFloater::updateMessages() { chat.mText = message; } - + mChatHistory->appendMessage(chat, chat_args); mLastMessageIndex = msg["index"].asInteger(); @@ -857,16 +859,16 @@ void LLIMFloater::updateMessages() if (chat.mNotifId.notNull() && LLNotificationsUtil::find(chat.mNotifId) != NULL) { if (++iter == iter_end) - { - break; - } - else - { - mLastMessageIndex++; - } - } - } - } + { + break; + } + else + { + mLastMessageIndex++; + } + } + } + } } void LLIMFloater::reloadMessages() @@ -877,15 +879,15 @@ void LLIMFloater::reloadMessages() } // static -void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ) +void LLIMFloater::onInputEditorFocusReceived(LLFocusableElement* caller, void* userdata) { - LLIMFloater* self= (LLIMFloater*) userdata; + LLIMFloater* self = (LLIMFloater*) userdata; // Allow enabling the LLIMFloater input editor only if session can accept text LLIMModel::LLIMSession* im_session = - LLIMModel::instance().findIMSession(self->mSessionID); + LLIMModel::instance().findIMSession(self->mSessionID); //TODO: While disabled lllineeditor can receive focus we need to check if it is enabled (EK) - if( im_session && im_session->mTextIMPossible && self->mInputEditor->getEnabled()) + if (im_session && im_session->mTextIMPossible && self->mInputEditor->getEnabled()) { //in disconnected state IM input editor should be disabled self->mInputEditor->setEnabled(!gDisconnected); @@ -902,7 +904,7 @@ void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userd // static void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata) { - LLIMFloater* self = (LLIMFloater*)userdata; + LLIMFloater* self = (LLIMFloater*) userdata; std::string text = self->mInputEditor->getText(); if (!text.empty()) { @@ -917,13 +919,13 @@ void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata) void LLIMFloater::setTyping(bool typing) { - if ( typing ) + if (typing) { // Started or proceeded typing, reset the typing timeout timer mTypingTimeoutTimer.reset(); } - if ( mMeTyping != typing ) + if (mMeTyping != typing) { // Typing state is changed mMeTyping = typing; @@ -935,21 +937,23 @@ void LLIMFloater::setTyping(bool typing) // Don't want to send typing indicators to multiple people, potentially too // much network traffic. Only send in person-to-person IMs. - if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL ) + if (mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL) { - if ( mMeTyping ) + if (mMeTyping) { - if ( mTypingTimer.getElapsedTimeF32() > 1.f ) + if (mTypingTimer.getElapsedTimeF32() > 1.f) { // Still typing, send 'start typing' notification - LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, TRUE); + LLIMModel::instance().sendTypingState(mSessionID, + mOtherParticipantUUID, TRUE); mShouldSendTypingState = false; } } else { // Send 'stop typing' notification immediately - LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, FALSE); + LLIMModel::instance().sendTypingState(mSessionID, + mOtherParticipantUUID, FALSE); mShouldSendTypingState = false; } } @@ -962,7 +966,7 @@ void LLIMFloater::setTyping(bool typing) void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) { - if ( typing ) + if (typing) { // other user started typing addTypingIndicator(im_info); @@ -976,9 +980,10 @@ void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) void LLIMFloater::processAgentListUpdates(const LLSD& body) { - if ( !body.isMap() ) return; + if (!body.isMap()) + return; - if ( body.has("agent_updates") && body["agent_updates"].isMap() ) + if (body.has("agent_updates") && body["agent_updates"].isMap()) { LLSD agent_data = body["agent_updates"].get(gAgentID.asString()); if (agent_data.isMap() && agent_data.has("info")) @@ -987,7 +992,7 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body) if (agent_info.has("mutes")) { - BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean(); + BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean(); mInputEditor->setEnabled(!moderator_muted_text); std::string label; if (moderator_muted_text) @@ -1008,7 +1013,7 @@ void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue) LLFontGL* font = LLViewerChat::getChatFont(); LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); - iter != inst_list.end(); ++iter) + iter != inst_list.end(); ++iter) { LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); if (floater) @@ -1022,15 +1027,16 @@ void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue) void LLIMFloater::processSessionUpdate(const LLSD& session_update) { // *TODO : verify following code when moderated mode will be implemented - if ( false && session_update.has("moderated_mode") && - session_update["moderated_mode"].has("voice") ) + if (false && session_update.has("moderated_mode") && + session_update["moderated_mode"].has("voice")) { BOOL voice_moderated = session_update["moderated_mode"]["voice"]; const std::string session_label = LLIMModel::instance().getName(mSessionID); if (voice_moderated) { - setTitle(session_label + std::string(" ") + LLTrans::getString("IM_moderated_chat_label")); + setTitle(session_label + std::string(" ") + + LLTrans::getString("IM_moderated_chat_label")); } else { @@ -1044,15 +1050,14 @@ void LLIMFloater::processSessionUpdate(const LLSD& session_update) } BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, EDragAndDropType cargo_type, - void *cargo_data, EAcceptance *accept, - std::string& tooltip_msg) + BOOL drop, EDragAndDropType cargo_type, + void *cargo_data, EAcceptance *accept, + std::string& tooltip_msg) { - if (mDialog == IM_NOTHING_SPECIAL) { LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, - cargo_type, cargo_data, accept); + cargo_type, cargo_data, accept); } // handle case for dropping calling cards (and folders of calling cards) onto invitation panel for invites @@ -1062,14 +1067,14 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, if (cargo_type == DAD_CALLINGCARD) { - if (dropCallingCard((LLInventoryItem*)cargo_data, drop)) + if (dropCallingCard((LLInventoryItem*) cargo_data, drop)) { *accept = ACCEPT_YES_MULTI; } } else if (cargo_type == DAD_CATEGORY) { - if (dropCategory((LLInventoryCategory*)cargo_data, drop)) + if (dropCategory((LLInventoryCategory*) cargo_data, drop)) { *accept = ACCEPT_YES_MULTI; } @@ -1081,9 +1086,9 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop) { BOOL rv = isInviteAllowed(); - if(rv && item && item->getCreatorUUID().notNull()) + if (rv && item && item->getCreatorUUID().notNull()) { - if(drop) + if (drop) { uuid_vec_t ids; ids.push_back(item->getCreatorUUID()); @@ -1101,26 +1106,26 @@ BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop) BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop) { BOOL rv = isInviteAllowed(); - if(rv && category) + if (rv && category) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; LLUniqueBuddyCollector buddies; gInventory.collectDescendentsIf(category->getUUID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - buddies); + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + buddies); S32 count = items.count(); - if(count == 0) + if (count == 0) { rv = FALSE; } - else if(drop) + else if (drop) { uuid_vec_t ids; ids.reserve(count); - for(S32 i = 0; i < count; ++i) + for (S32 i = 0; i < count; ++i) { ids.push_back(items.get(i)->getCreatorUUID()); } @@ -1132,12 +1137,11 @@ BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop) BOOL LLIMFloater::isInviteAllowed() const { - - return ( (IM_SESSION_CONFERENCE_START == mDialog) - || (IM_SESSION_INVITE == mDialog) ); + return ((IM_SESSION_CONFERENCE_START == mDialog) + || (IM_SESSION_INVITE == mDialog)); } -class LLSessionInviteResponder : public LLHTTPClient::Responder +class LLSessionInviteResponder: public LLHTTPClient::Responder { public: LLSessionInviteResponder(const LLUUID& session_id) @@ -1165,7 +1169,7 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) S32 count = ids.size(); - if( isInviteAllowed() && (count > 0) ) + if (isInviteAllowed() && (count > 0)) { llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl; @@ -1182,10 +1186,9 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) data["method"] = "invite"; data["session-id"] = mSessionID; LLHTTPClient::post( - url, - data, - new LLSessionInviteResponder( - mSessionID)); + url, + data, + new LLSessionInviteResponder(mSessionID)); } else { @@ -1202,17 +1205,17 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info) { // We may have lost a "stop-typing" packet, don't add it twice - if ( im_info && !mOtherTyping ) + if (im_info && !mOtherTyping) { mOtherTyping = true; // Save and set new title mSavedTitle = getTitle(); - setTitle (mTypingStart); + setTitle(mTypingStart); // Update speaker LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if ( speaker_mgr ) + if (speaker_mgr) { speaker_mgr->setSpeakerTyping(im_info->mFromID, TRUE); } @@ -1221,18 +1224,18 @@ void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info) void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info) { - if ( mOtherTyping ) + if (mOtherTyping) { mOtherTyping = false; // Revert the title to saved one setTitle(mSavedTitle); - if ( im_info ) + if (im_info) { // Update speaker LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if ( speaker_mgr ) + if (speaker_mgr) { speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE); } @@ -1253,7 +1256,8 @@ void LLIMFloater::closeHiddenIMToasts() } }; - LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getNotificationScreenChannel(); + LLNotificationsUI::LLScreenChannel* channel = + LLNotificationsUI::LLChannelManager::getNotificationScreenChannel(); if (channel != NULL) { channel->closeHiddenToasts(IMToastMatcher()); @@ -1295,28 +1299,34 @@ void LLIMFloater::initIMFloater() void LLIMFloater::sRemoveTypingIndicator(const LLSD& data) { LLUUID session_id = data["session_id"]; - if (session_id.isNull()) return; + if (session_id.isNull()) + return; LLUUID from_id = data["from_id"]; - if (gAgentID == from_id || LLUUID::null == from_id) return; + if (gAgentID == from_id || LLUUID::null == from_id) + return; LLIMFloater* floater = LLIMFloater::findInstance(session_id); - if (!floater) return; + if (!floater) + return; - if (IM_NOTHING_SPECIAL != floater->mDialog) return; + if (IM_NOTHING_SPECIAL != floater->mDialog) + return; floater->removeTypingIndicator(); } -void LLIMFloater::onIMChicletCreated( const LLUUID& session_id ) +void LLIMFloater::onIMChicletCreated(const LLUUID& session_id) { if (isChatMultiTab()) { LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); - if (!im_box) return; + if (!im_box) + return; - if (LLIMFloater::findInstance(session_id)) return; + if (LLIMFloater::findInstance(session_id)) + return; LLIMFloater* new_tab = LLIMFloater::getInstance(session_id); @@ -1325,11 +1335,11 @@ void LLIMFloater::onIMChicletCreated( const LLUUID& session_id ) } -void LLIMFloater::onClickCloseBtn() +void LLIMFloater::onClickCloseBtn() { LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - mSessionID); + mSessionID); if (session == NULL) { @@ -1342,7 +1352,8 @@ void LLIMFloater::onClickCloseBtn() LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - if (is_call_with_chat && voice_channel != NULL && voice_channel->isActive()) + if (is_call_with_chat && voice_channel != NULL + && voice_channel->isActive()) { LLSD payload; payload["session_id"] = mSessionID; diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 40b3fff8f4..60b392952f 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -84,7 +84,7 @@ public: // get new messages from LLIMModel void updateMessages(); void reloadMessages(); - static void onSendMsg( LLUICtrl*, void*); + static void onSendMsg(LLUICtrl*, void*); void sendMsg(); // callback for LLIMModel on new messages @@ -111,9 +111,9 @@ public: static void processChatHistoryStyleUpdate(const LLSD& newvalue); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, EDragAndDropType cargo_type, - void *cargo_data, EAcceptance *accept, - std::string& tooltip_msg); + BOOL drop, EDragAndDropType cargo_type, + void *cargo_data, EAcceptance *accept, + std::string& tooltip_msg); /** * Returns true if chat is displayed in multi tabbed floater @@ -131,10 +131,8 @@ public: virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } protected: - /* virtual */ - void onClickCloseBtn(); - - /*virtual*/ void updateTitleButtons(); + /* virtual */ void onClickCloseBtn(); + /* virtual */ void updateTitleButtons(); private: // process focus events to set a currently active session @@ -143,24 +141,23 @@ private: // Update the window title, input field help text, etc. void updateSessionName(const std::string& ui_title, const std::string& ui_label); - + // For display name lookups for IM window titles void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); - + BOOL dropCallingCard(LLInventoryItem* item, BOOL drop); BOOL dropCategory(LLInventoryCategory* category, BOOL drop); BOOL isInviteAllowed() const; BOOL inviteToSession(const uuid_vec_t& agent_ids); - - static void onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ); - static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); - static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); - void setTyping(bool typing); - void onSlide(); - static void* createPanelIMControl(void* userdata); - static void* createPanelGroupControl(void* userdata); - static void* createPanelAdHocControl(void* userdata); + + static void onInputEditorFocusReceived( LLFocusableElement* caller,void* userdata ); + static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); + static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); + void setTyping(bool typing); + void onSlide(); + static void* createPanelGroupControl(void* userdata); + static void* createPanelAdHocControl(void* userdata); bool onIMCompactExpandedMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemCheck(const LLSD& userdata); -- cgit v1.2.3 From c866b094ee000172f7cd820692f228f3f0afddc8 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 14 May 2012 21:19:18 +0300 Subject: CHUI-113 WIP clean-up (obsolete code was removed) --- indra/newview/llpanelimcontrolpanel.cpp | 102 ------------- indra/newview/llpanelimcontrolpanel.h | 28 ---- .../default/xui/en/panel_im_control_panel.xml | 166 --------------------- 3 files changed, 296 deletions(-) delete mode 100644 indra/newview/skins/default/xui/en/panel_im_control_panel.xml (limited to 'indra') diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index f0fc15b4d8..cba0d6c064 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -56,108 +56,6 @@ void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id) mSessionId = session_id; } -LLPanelIMControlPanel::LLPanelIMControlPanel() -{ -} - -LLPanelIMControlPanel::~LLPanelIMControlPanel() -{ -// LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); -} - -BOOL LLPanelIMControlPanel::postBuild() -{ -/* childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this)); - childSetAction("add_friend_btn", boost::bind(&LLPanelIMControlPanel::onAddFriendButtonClicked, this)); - - childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this)); - childSetAction("teleport_btn", boost::bind(&LLPanelIMControlPanel::onTeleportButtonClicked, this)); - childSetAction("pay_btn", boost::bind(&LLPanelIMControlPanel::onPayButtonClicked, this)); - - childSetAction("block_btn", boost::bind(&LLPanelIMControlPanel::onClickBlock, this)); - childSetAction("unblock_btn", boost::bind(&LLPanelIMControlPanel::onClickUnblock, this)); - - getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId())); - - setFocusReceivedCallback(boost::bind(&LLPanelIMControlPanel::onFocusReceived, this)); -*/ - return LLPanelChatControlPanel::postBuild(); - -} - -void LLPanelIMControlPanel::draw() -{ - bool is_muted = LLMuteList::getInstance()->isMuted(mAvatarID); - - getChild<LLUICtrl>("block_btn_panel")->setVisible(!is_muted); - getChild<LLUICtrl>("unblock_btn_panel")->setVisible(is_muted); - - - LLPanelChatControlPanel::draw(); -} - -void LLPanelIMControlPanel::onClickBlock() -{ - LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT); - - LLMuteList::getInstance()->add(mute); -} - -void LLPanelIMControlPanel::onClickUnblock() -{ - LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT); - - LLMuteList::getInstance()->remove(mute); -} - -void LLPanelIMControlPanel::onTeleportButtonClicked() -{ - LLAvatarActions::offerTeleport(mAvatarID); -} -void LLPanelIMControlPanel::onPayButtonClicked() -{ - LLAvatarActions::pay(mAvatarID); -} - -void LLPanelIMControlPanel::onViewProfileButtonClicked() -{ - LLAvatarActions::showProfile(mAvatarID); -} - -void LLPanelIMControlPanel::onAddFriendButtonClicked() -{ - LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon"); - std::string full_name = avatar_icon->getFullName(); - LLAvatarActions::requestFriendshipDialog(mAvatarID, full_name); -} - -void LLPanelIMControlPanel::onShareButtonClicked() -{ - LLAvatarActions::share(mAvatarID); -} - -void LLPanelIMControlPanel::onFocusReceived() -{ - // Disable all the buttons (Call, Teleport, etc) if disconnected. - if (gDisconnected) - { - setAllChildrenEnabled(FALSE); - } -} - - -void LLPanelIMControlPanel::onNameCache(const LLUUID& id, const std::string& full_name, bool is_group) -{ - if ( id == mAvatarID ) - { - std::string avatar_name = full_name; - getChild<LLTextBox>("avatar_name")->setValue(avatar_name); - getChild<LLTextBox>("avatar_name")->setToolTip(avatar_name); - - bool is_linden = LLStringUtil::endsWith(full_name, " Linden"); - getChild<LLUICtrl>("mute_btn")->setEnabled( !is_linden); - } -} LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id): mParticipantList(NULL) diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h index 3466da33a1..0ec992bb1e 100644 --- a/indra/newview/llpanelimcontrolpanel.h +++ b/indra/newview/llpanelimcontrolpanel.h @@ -52,34 +52,6 @@ private: boost::signals2::connection mVoiceChannelStateChangeConnection; }; - -class LLPanelIMControlPanel : public LLPanelChatControlPanel -{ -public: - LLPanelIMControlPanel(); - ~LLPanelIMControlPanel(); - - BOOL postBuild(); - - //void setSessionId(const LLUUID& session_id); - -protected: - void onNameCache(const LLUUID& id, const std::string& full_name, bool is_group); - -private: - void onViewProfileButtonClicked(); - void onAddFriendButtonClicked(); - void onShareButtonClicked(); - void onTeleportButtonClicked(); - void onPayButtonClicked(); - void onFocusReceived(); - void onClickBlock(); - void onClickUnblock(); - /*virtual*/ void draw(); - LLUUID mAvatarID; -}; - - class LLPanelGroupControlPanel : public LLPanelChatControlPanel { public: diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml deleted file mode 100644 index 8fcd6ccbaf..0000000000 --- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml +++ /dev/null @@ -1,166 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - border="false" - height="300" - name="panel_im_control_panel" - width="150"> - <avatar_icon - follows="left|top" - height="105" - left_delta="20" - name="avatar_icon" - top="-5" - width="114"/> - <layout_stack - mouse_opaque="false" - border_size="0" - clip="false" - follows="all" - height="183" - layout="topleft" - left="5" - name="button_stack" - orientation="vertical" - top_pad="5" - width="145"> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="20" - layout="topleft" - left="2" - min_height="20" - width="140" - name="view_profile_btn_panel" - top="0" > - <button - follows="left|top|right" - height="23" - label="Profile" - name="view_profile_btn" - top="0" - width="140" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="25" - layout="topleft" - min_height="25" - width="140" - name="add_friend_btn_panel"> - <button - follows="left|top|right" - height="23" - label="Add Friend" - name="add_friend_btn" - top="5" - width="140" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="25" - layout="topleft" - min_height="25" - width="140" - name="teleport_btn_panel"> - <button - auto_resize="false" - follows="left|top|right" - height="23" - label="Teleport" - name="teleport_btn" - tool_tip = "Offer to teleport this person" - width="140" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="25" - layout="topleft" - min_height="25" - width="140" - name="share_btn_panel"> - <button - auto_resize="true" - follows="left|top|right" - height="23" - label="Share" - name="share_btn" - width="140" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="25" - layout="topleft" - min_height="25" - width="140" - name="pay_btn_panel"> - <button - auto_resize="true" - follows="left|top|right" - height="23" - label="Pay" - name="pay_btn" - width="140" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="25" - layout="topleft" - min_height="25" - width="140" - name="call_btn_panel"> - <button - follows="left|top|right" - height="23" - label="Call" - name="call_btn" - width="140" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="25" - layout="topleft" - min_height="25" - width="140" - name="end_call_btn_panel" - visible="false"> - <button - follows="left|top|right" - height="23" - label="End Call" - name="end_call_btn" - width="140" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="25" - layout="topleft" - min_height="25" - width="140" - name="voice_ctrls_btn_panel" - visible="false"> - <button - follows="left|top|right" - height="23" - label="Voice Controls" - name="voice_ctrls_btn" - width="140" /> - </layout_panel> - <layout_panel - mouse_opaque="false" - auto_resize="true" - follows="top|left" - height="0" - layout="topleft" - min_height="0" - width="140" - name="spacer"/> - </layout_stack> -</panel> -- cgit v1.2.3 From 0568fb00ab1bc6ddaed5fdd7cac88e81aa8c26e2 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 15 May 2012 19:31:55 +0300 Subject: CHUI-102 WIP Implemented new context menu for ad-hoc and group conferences --- indra/newview/llpanelpeoplemenus.cpp | 7 +++++-- indra/newview/llparticipantlist.cpp | 14 ++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index 0d66b8f10b..c84790d839 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -51,6 +51,7 @@ LLContextMenu* NearbyMenu::createMenu() // set up the callbacks for all of the avatar menu items LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + LLContextMenu* menu; if ( mUUIDs.size() == 1 ) { @@ -73,7 +74,7 @@ LLContextMenu* NearbyMenu::createMenu() enable_registrar.add("Avatar.CheckItem", boost::bind(&NearbyMenu::checkContextMenuItem, this, _2)); // create the context menu from the XUI - return createFromFile("menu_people_nearby.xml"); + menu = createFromFile("menu_people_nearby.xml"); } else { @@ -89,8 +90,10 @@ LLContextMenu* NearbyMenu::createMenu() enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2)); // create the context menu from the XUI - return createFromFile("menu_people_nearby_multiselect.xml"); + menu = createFromFile("menu_people_nearby_multiselect.xml"); } + + return menu; } bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 975a6c67d8..59d26edff2 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -32,6 +32,7 @@ #include "llagent.h" #include "llimview.h" +#include "llpanelpeoplemenus.h" #include "llnotificationsutil.h" #include "llparticipantlist.h" #include "llspeakers.h" @@ -197,10 +198,10 @@ private: uuid_set_t mAvalineCallers; }; -LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, +LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu/* = true*/, - bool exclude_agent /*= true*/, + bool exclude_agent /*= true*/, bool can_toggle_icons /*= true*/) : mSpeakerMgr(data_source), mAvatarList(avatar_list), @@ -233,8 +234,9 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, if (use_context_menu) { - mParticipantListMenu = new LLParticipantListMenu(*this); - mAvatarList->setContextMenu(mParticipantListMenu); + //mParticipantListMenu = new LLParticipantListMenu(*this); + //mAvatarList->setContextMenu(mParticipantListMenu); + mAvatarList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); } else { @@ -670,7 +672,7 @@ bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents:: return mParent.onSpeakerMuteEvent(event, userdata); } -LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() +/*LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() { // set up the callbacks for all of the avatar menu items LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -708,7 +710,7 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() main_menu->arrangeAndClear(); return main_menu; -} +}*/ void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y) { -- cgit v1.2.3 From 0ed7966bd5471e4152ade9ac63e81406b4d0a679 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 15 May 2012 20:42:14 +0300 Subject: CHUI-105 WIP Remove obsolete controls from the group's control pane --- indra/newview/llpanelimcontrolpanel.cpp | 7 +--- indra/newview/llpanelimcontrolpanel.h | 1 - .../default/xui/en/panel_group_control_panel.xml | 49 ---------------------- 3 files changed, 1 insertion(+), 56 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index cba0d6c064..bc4097cd93 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -64,7 +64,6 @@ mParticipantList(NULL) BOOL LLPanelGroupControlPanel::postBuild() { - childSetAction("group_info_btn", boost::bind(&LLPanelGroupControlPanel::onGroupInfoButtonClicked, this)); return LLPanelChatControlPanel::postBuild(); } @@ -84,10 +83,6 @@ void LLPanelGroupControlPanel::draw() LLPanelChatControlPanel::draw(); } -void LLPanelGroupControlPanel::onGroupInfoButtonClicked() -{ - LLGroupActions::show(mGroupID); -} void LLPanelGroupControlPanel::onSortMenuItemClicked(const LLSD& userdata) { @@ -114,7 +109,7 @@ void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id) if(!mParticipantList) { LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id); - mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true,false); + mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false); } } diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h index 0ec992bb1e..02915ec4bb 100644 --- a/indra/newview/llpanelimcontrolpanel.h +++ b/indra/newview/llpanelimcontrolpanel.h @@ -69,7 +69,6 @@ protected: LLParticipantList* mParticipantList; private: - void onGroupInfoButtonClicked(); void onSortMenuItemClicked(const LLSD& userdata); }; diff --git a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml index ad10e53a4e..a5295ebe01 100644 --- a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml +++ b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml @@ -40,55 +40,6 @@ show_speaking_indicator="false" width="145" /> </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="28" - layout="topleft" - min_height="28" - width="130" - name="group_info_btn_panel"> - <button - follows="left|right|bottom" - height="23" - label="Group Profile" - name="group_info_btn" - use_ellipses="true" - top="5" - width="130" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="28" - layout="topleft" - min_height="28" - width="130" - name="call_btn_panel"> - <button - follows="all" - height="23" - label="Call Group" - name="call_btn" - use_ellipses="true" - width="130" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="28" - layout="topleft" - min_height="28" - width="130" - name="end_call_btn_panel" - visible="false"> - <button - follows="all" - height="23" - label="Leave Call" - name="end_call_btn" - use_ellipses="true" /> - </layout_panel> <layout_panel auto_resize="false" follows="top|left|right" -- cgit v1.2.3 From e2824864590ded669eac3c53efbfc60d04107ee4 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 15 May 2012 22:19:20 +0300 Subject: CHUI-105 WIP Hide an additional close button for undocked state of an IM floater --- indra/newview/llimfloater.cpp | 10 ++++++++++ indra/newview/llimfloater.h | 3 +++ 2 files changed, 13 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index cb489627fb..1ca3545aae 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -391,6 +391,12 @@ BOOL LLIMFloater::postBuild() } } +void LLIMFloater::onTearOffClicked(LLIMFloater* self) +{ + onClickTearOff(self); + updateTitleButtons(); +} + void LLIMFloater::boundVoiceChannel() { LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); @@ -1377,6 +1383,7 @@ void LLIMFloater::updateTitleButtons() } bool is_hosted = getHost() != NULL; + if (is_hosted) ///< floater is hosted { for (S32 i = 0; i < BUTTON_COUNT; i++) @@ -1391,6 +1398,7 @@ void LLIMFloater::updateTitleButtons() } mExpandCollapseBtn->setImageOverlay(getString("collapse_icon")); + } else ///< floater is torn off { @@ -1403,6 +1411,8 @@ void LLIMFloater::updateTitleButtons() } } + getChild<LLButton>("close_btn")->setVisible(is_hosted); + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); if (session) { diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 60b392952f..03f52fb316 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -93,6 +93,7 @@ public: // called when docked floater's position has been set by chiclet void setPositioned(bool b) { mPositioned = b; }; + void onVisibilityChange(const LLSD& new_visibility); // Implements LLVoiceClientStatusObserver::onChange() to enable the call @@ -139,6 +140,8 @@ private: /* virtual */ void onFocusLost(); /* virtual */ void onFocusReceived(); + void onTearOffClicked(LLIMFloater *self); + // Update the window title, input field help text, etc. void updateSessionName(const std::string& ui_title, const std::string& ui_label); -- cgit v1.2.3 From f59aa880395d4b744c89b0a375b21ee2bf429625 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Thu, 17 May 2012 02:51:18 +0300 Subject: CHUI-105 WIP Implemented collapsed/expanded state transitions for messages and conversation panes. The states and dimensions of Conversations floater panes are saved in per account settings. --- indra/llui/lllayoutstack.h | 2 + indra/llui/llmultifloater.cpp | 36 +++-- indra/llui/llmultifloater.h | 3 + .../newview/app_settings/settings_per_account.xml | 55 +++++++ indra/newview/llimfloater.cpp | 4 +- indra/newview/llimfloatercontainer.cpp | 133 ++++++++++++++--- indra/newview/llimfloatercontainer.h | 18 ++- .../skins/default/xui/en/floater_im_container.xml | 158 ++++++++++++++------- 8 files changed, 320 insertions(+), 89 deletions(-) (limited to 'indra') diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index d32caec5f9..58643868e8 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -177,6 +177,8 @@ public: F32 getVisibleAmount() const; S32 getVisibleDim() const; + bool isCollapsed() const { return mCollapsed;} + void setOrientation(LLLayoutStack::ELayoutOrientation orientation); void storeOriginalDim(); diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index f3a48835b1..540ac74aee 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -468,23 +468,12 @@ BOOL LLMultiFloater::postBuild() void LLMultiFloater::updateResizeLimits() { - static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0); - const LLFloater::Params& default_params = LLFloater::getDefaultParams(); - S32 floater_header_size = default_params.header_height; - S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size; // initialize minimum size constraint to the original xml values. S32 new_min_width = mOrigMinWidth; S32 new_min_height = mOrigMinHeight; - // possibly increase minimum size constraint due to children's minimums. - for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) - { - LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx); - if (floaterp) - { - new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2); - new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height); - } - } + + computeResizeLimits(new_min_width, new_min_height); + setResizeLimits(new_min_width, new_min_height); S32 cur_height = getRect().getHeight(); @@ -510,3 +499,22 @@ void LLMultiFloater::updateResizeLimits() gFloaterView->adjustToFitScreen(this, TRUE); } } + +void LLMultiFloater::computeResizeLimits(S32& new_min_width, S32& new_min_height) +{ + static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0); + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; + S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size; + + // possibly increase minimum size constraint due to children's minimums. + for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + { + LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx); + if (floaterp) + { + new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2); + new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height); + } + } +} diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h index 9fa917eca1..f299ae5dd3 100644 --- a/indra/llui/llmultifloater.h +++ b/indra/llui/llmultifloater.h @@ -93,6 +93,9 @@ protected: LLTabContainer::TabPosition mTabPos; BOOL mAutoResize; S32 mOrigMinWidth, mOrigMinHeight; // logically const but initialized late + +private: + virtual void computeResizeLimits(S32& new_min_width, S32& new_min_height); }; #endif // LL_MULTI_FLOATER_H diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 8cdd8ed838..fdc52b7394 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -22,6 +22,61 @@ <key>Value</key> <string>The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing.</string> </map> + <key>ConversationsExpandMessagePaneFirst</key> + <map> + <key>Comment</key> + <string>Expand either messages or conversations list pane from Conversations compact mode.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ConversationsListPaneCollapsed</key> + <map> + <key>Comment</key> + <string>Stores the expanded/collapsed state of the conversations list pane in Conversations floater.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ConversationsListPaneWidth</key> + <map> + <key>Comment</key> + <string>Conversations floater list pane width.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>268</integer> + </map> + <key>ConversationsMessagePaneCollapsed</key> + <map> + <key>Comment</key> + <string>Stores the expanded/collapsed state of Conversations floater message pane.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ConversationsMessagePaneWidth</key> + <map> + <key>Comment</key> + <string>Conversations floater message pane width.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>412</integer> + </map> <key>InstantMessageLogPath</key> <map> <key>Comment</key> diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 1ca3545aae..051bb39540 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -188,7 +188,7 @@ void LLIMFloater::onOpen(const LLSD& key) if (host_floater) { // Show the messages pane when opening a floater hosted in the Conversations - host_floater->toggleMessagesPane(true); + host_floater->collapseMessagesPane(false); } } @@ -536,7 +536,7 @@ void LLIMFloater::onSlide() if (host_floater) { // Hide the messages pane if a floater is hosted in the Conversations - host_floater->toggleMessagesPane(false); + host_floater->collapseMessagesPane(true); } else ///< floater is torn off { diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index c8b8cb208d..b051440589 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -28,19 +28,23 @@ #include "llviewerprecompiledheaders.h" #include "llimfloatercontainer.h" + #include "llfloaterreg.h" -#include "llimview.h" +#include "lllayoutstack.h" + +#include "llagent.h" #include "llavatariconctrl.h" #include "llgroupiconctrl.h" -#include "llagent.h" +#include "llimview.h" #include "lltransientfloatermgr.h" +#include "llviewercontrol.h" // // LLIMFloaterContainer // LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) : LLMultiFloater(seed) - ,mMessagesPaneWidth(0) + ,mExpandCollapseBtn(NULL) { mAutoResize = FALSE; LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); @@ -50,6 +54,9 @@ LLIMFloaterContainer::~LLIMFloaterContainer() { mNewMessageConnection.disconnect(); LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); + + gSavedPerAccountSettings.setBOOL("ConversationsListPaneCollapsed", mConversationsPane->isCollapsed()); + gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed()); } BOOL LLIMFloaterContainer::postBuild() @@ -60,6 +67,16 @@ BOOL LLIMFloaterContainer::postBuild() setTabContainer(getChild<LLTabContainer>("im_box_tab_container")); + mConversationsStack = getChild<LLLayoutStack>("conversations_stack"); + mConversationsPane = getChild<LLLayoutPanel>("conversations_layout_panel"); + mMessagesPane = getChild<LLLayoutPanel>("messages_layout_panel"); + + mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); + mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this)); + + collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); + collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); + return TRUE; } @@ -146,6 +163,37 @@ void LLIMFloaterContainer::onCloseFloater(LLUUID& id) mSessions.erase(id); } +// virtual +void LLIMFloaterContainer::computeResizeLimits(S32& new_min_width, S32& new_min_height) +{ + bool is_left_pane_expanded = !mConversationsPane->isCollapsed(); + bool is_right_pane_expanded = !mMessagesPane->isCollapsed(); + + S32 conversations_pane_min_dim = mConversationsPane->getMinDim(); + + if (is_right_pane_expanded) + { + S32 conversations_pane_width = + (is_left_pane_expanded ? gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") : conversations_pane_min_dim); + + // possibly increase minimum size constraint due to children's minimums. + for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + { + LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getPanelByIndex(tab_idx)); + if (floaterp) + { + new_min_width = llmax(new_min_width, + floaterp->getMinWidth() + conversations_pane_width + LLPANEL_BORDER_WIDTH * 2); + new_min_height = llmax(new_min_height, floaterp->getMinHeight()); + } + } + } + else + { + new_min_width = conversations_pane_min_dim; + } +} + void LLIMFloaterContainer::onNewMessageReceived(const LLSD& data) { LLUUID session_id = data["session_id"].asUUID(); @@ -160,6 +208,21 @@ void LLIMFloaterContainer::onNewMessageReceived(const LLSD& data) } } +void LLIMFloaterContainer::onExpandCollapseButtonClicked() +{ + if (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed() + && gSavedPerAccountSettings.getBOOL("ConversationsExpandMessagePaneFirst")) + { + // Expand the messages pane from ultra minimized state + // if it was collapsed last in order. + collapseMessagesPane(false); + } + else + { + collapseConversationsPane(!mConversationsPane->isCollapsed()); + } +} + LLIMFloaterContainer* LLIMFloaterContainer::findInstance() { return LLFloaterReg::findTypedInstance<LLIMFloaterContainer>("im_container"); @@ -186,29 +249,67 @@ void LLIMFloaterContainer::setMinimized(BOOL b) } } -void LLIMFloaterContainer::toggleMessagesPane(bool expand) +void LLIMFloaterContainer::collapseMessagesPane(bool collapse) { - LLView* messages_pane = getChild<LLView>("im_box_tab_container"); - bool is_expanded = messages_pane->getVisible(); - if (is_expanded == expand) + if (mMessagesPane->isCollapsed() == collapse) { return; } - // Store the messages pane width before collapsing it. - if (!expand) + if (collapse) { - LLView* conversations_pane = getChild<LLView>("conversations_pane"); - S32 horizontal_pad = messages_pane->getRect().mLeft - conversations_pane->getRect().mRight; - mMessagesPaneWidth = messages_pane->getRect().getWidth() + horizontal_pad; + // Save the messages pane width before collapsing it. + gSavedPerAccountSettings.setS32("ConversationsMessagePaneWidth", mMessagesPane->getRect().getWidth()); + + // Save the order in which the panels are closed to reverse user's last action. + gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", mConversationsPane->isCollapsed()); } // Show/hide the messages pane. - messages_pane->setVisible(expand); + mConversationsStack->collapsePanel(mMessagesPane, collapse); + + updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); +} + +void LLIMFloaterContainer::collapseConversationsPane(bool collapse) +{ + if (mConversationsPane->isCollapsed() == collapse) + { + return; + } + + LLView* button_panel = getChild<LLView>("conversations_pane_buttons_expanded"); + button_panel->setVisible(!collapse); + mExpandCollapseBtn->setImageOverlay(getString(collapse ? "expand_icon" : "collapse_icon")); + + if (collapse) + { + // Save the conversations pane width before collapsing it. + gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", mConversationsPane->getRect().getWidth()); + + // Save the order in which the panels are closed to reverse user's last action. + gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", !mMessagesPane->isCollapsed()); + } + + mConversationsStack->collapsePanel(mConversationsPane, collapse); + + S32 collapsed_width = mConversationsPane->getMinDim(); + updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - collapsed_width); +} + +void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) +{ + LLRect floater_rect = getRect(); + floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); + setShape(floater_rect); + + updateResizeLimits(); + + bool is_left_pane_expanded = !mConversationsPane->isCollapsed(); + bool is_right_pane_expanded = !mMessagesPane->isCollapsed(); - S32 floater_width = getRect().getWidth(); - floater_width += (expand ? mMessagesPaneWidth : -mMessagesPaneWidth); - reshape(floater_width, getRect().getHeight()); + setCanResize(is_left_pane_expanded || is_right_pane_expanded); + setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); } // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 045f053b1c..92938ff405 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -35,6 +35,9 @@ #include "llavatarpropertiesprocessor.h" #include "llgroupmgr.h" +class LLButton; +class LLLayoutPanel; +class LLLayoutStack; class LLTabContainer; class LLIMFloaterContainer : public LLMultiFloater @@ -60,16 +63,27 @@ public: virtual void setMinimized(BOOL b); - void toggleMessagesPane(bool expand); + void collapseMessagesPane(bool collapse); private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; avatarID_panel_map_t mSessions; boost::signals2::connection mNewMessageConnection; + /*virtual*/ void computeResizeLimits(S32& new_min_width, S32& new_min_height); + void onNewMessageReceived(const LLSD& data); - S32 mMessagesPaneWidth; + void onExpandCollapseButtonClicked(); + + void collapseConversationsPane(bool collapse); + + void updateState(bool collapse, S32 delta_width); + + LLButton* mExpandCollapseBtn; + LLLayoutPanel* mMessagesPane; + LLLayoutPanel* mConversationsPane; + LLLayoutStack* mConversationsStack; }; #endif // LL_LLIMFLOATERCONTAINER_H diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 8a0181bae4..ce40f44a64 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -5,7 +5,7 @@ can_resize="true" height="430" layout="topleft" - min_width="510" + min_height="50" name="floater_im_box" help_topic="floater_im_box" save_rect="true" @@ -13,62 +13,110 @@ single_instance="true" title="CONVERSATIONS" width="680"> - <panel - border="true" - follows="top|bottom|left" - layout="topleft" - name="conversations_pane" - opaque="true" - top="0" - left="5" - height="425" - width="263"> - <menu_button - follows="top|left" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left="5" - name="sort_btn" - top="5" - width="31" /> - <button - follows="top|left" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - top="5" - left_pad="4" - name="add_btn" - tool_tip="Add button on the left panel" - width="31"> - </button> - <button - follows="right|top" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="TabIcon_Open_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - top="5" - left="228" - name="expand_collapse_btn" - width="31" /> - </panel> - <panel_container + <string + name="collapse_icon" + value="TabIcon_Open_Off"/> + <string + name="expand_icon" + value="TabIcon_Close_Off"/> + <layout_stack + animate="true" follows="all" height="430" layout="topleft" - left_pad="15" - min_width="290" - name="im_box_tab_container" + left="0" + name="conversations_stack" + orientation="horizontal" top="0" - width="389"/> + width="680"> + <layout_panel + auto_resize="true" + height="430" + name="conversations_layout_panel" + min_dim="41" + width="268"> + <layout_stack + animate="false" + follows="left|top|right" + height="35" + layout="topleft" + left="0" + name="conversations_pane_buttons_stack" + orientation="horizontal" + top="0" + width="268"> + <layout_panel + auto_resize="true" + height="35" + name="conversations_pane_buttons_expanded"> + <menu_button + follows="top|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left="10" + name="sort_btn" + top="5" + width="31" /> + <button + follows="top|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_pad="4" + name="add_btn" + tool_tip="Add button on the left panel" + width="31"/> + </layout_panel> + <layout_panel + auto_resize="false" + height="35" + name="conversations_pane_buttons_collapsed" + width="41"> + <button + follows="right|top" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TabIcon_Open_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left="5" + name="expand_collapse_btn" + width="31" /> + </layout_panel> + </layout_stack> + <panel + follows="all" + layout="topleft" + name="conversations_list_panel" + opaque="true" + top_pad="0" + left="5" + height="390" + width="263"/> + </layout_panel> + <layout_panel + auto_resize="true" + height="430" + name="messages_layout_panel" + width="412"> + <panel_container + follows="all" + height="430" + layout="topleft" + left="10" + name="im_box_tab_container" + top="0" + width="402"/> + </layout_panel> + </layout_stack> </multi_floater> -- cgit v1.2.3 From 4fc8000d6692290516eae1f865b6b41f1d56cc0b Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 17 May 2012 19:35:05 +0300 Subject: CHUI-105 ADD. FIX Implement changes to all open conversations and nearby chat --- indra/newview/llfloaterpreference.cpp | 21 +++---- indra/newview/llimfloater.cpp | 85 ++++++++++++++------------- indra/newview/llimfloater.h | 14 +++-- indra/newview/llimview.cpp | 18 +++--- indra/newview/llimview.h | 14 ++--- indra/newview/llnearbychat.cpp | 104 +++++++++++++++++----------------- indra/newview/llnearbychat.h | 8 ++- 7 files changed, 140 insertions(+), 124 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 1c29323594..3ed575086c 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -423,13 +423,13 @@ void LLFloaterPreference::saveAvatarProperties( void ) BOOL LLFloaterPreference::postBuild() { - gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2)); + gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate)); - gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2)); + gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate)); - gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2)); + gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate)); - gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2)); + gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate)); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLViewerChat::signalChatFontChanged)); @@ -457,14 +457,11 @@ BOOL LLFloaterPreference::postBuild() void LLFloaterPreference::onBusyResponseChanged() { // set "BusyResponseChanged" TRUE if user edited message differs from default, FALSE otherwise - if (LLTrans::getString("BusyModeResponseDefault") != getChild<LLUICtrl>("busy_response")->getValue().asString()) - { - gSavedPerAccountSettings.setBOOL("BusyResponseChanged", TRUE ); - } - else - { - gSavedPerAccountSettings.setBOOL("BusyResponseChanged", FALSE ); - } + bool busy_flag = + LLTrans::getString("BusyModeResponseDefault") + != getChild<LLUICtrl>("busy_response")->getValue().asString(); + + gSavedPerAccountSettings.setBOOL("BusyResponseChanged", busy_flag ); } LLFloaterPreference::~LLFloaterPreference() diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 051bb39540..c6608337c8 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -44,6 +44,7 @@ #include "lllayoutstack.h" #include "lllineeditor.h" #include "lllogchat.h" +#include "llnearbychat.h" #include "llpanelimcontrolpanel.h" #include "llscreenchannel.h" #include "llsyswellwindow.h" @@ -63,13 +64,14 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mSessionID(session_id), mLastMessageIndex(-1), mDialog(IM_NOTHING_SPECIAL), - mChatHistory(NULL), mInputEditor(NULL), mExpandCollapseBtn(NULL), mTearOffBtn(NULL), mSavedTitle(), mTypingStart(), + mIsP2PChat(false), mShouldSendTypingState(false), + mChatHistory(NULL), mMeTyping(false), mOtherTyping(false), mTypingTimer(), @@ -77,12 +79,14 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mPositioned(false), mSessionInitialized(false) { - LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionID); - if (im_session) + mSession = LLIMModel::getInstance()->findIMSession(mSessionID); + + if (mSession) { - mSessionInitialized = im_session->mSessionInitialized; + mIsP2PChat = mSession->isP2PSessionType(); + mSessionInitialized = mSession->mSessionInitialized; - mDialog = im_session->mType; + mDialog = mSession->mType; switch (mDialog) { case IM_SESSION_CONFERENCE_START: @@ -101,8 +105,6 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); } break; - case IM_NOTHING_SPECIAL: - case IM_SESSION_P2P_INVITE: default: break; } @@ -135,14 +137,13 @@ bool LLIMFloater::onIMShowModesMenuItemCheck(const LLSD& userdata) return gSavedSettings.getBOOL(userdata.asString()); } +// enable/disable states for the "show time" and "show names" items of the show-modes menu bool LLIMFloater::onIMShowModesMenuItemEnable(const LLSD& userdata) { std::string item = userdata.asString(); bool plain_text = gSavedSettings.getBOOL("PlainTextChatHistory"); bool is_not_names = (item != "IMShowNamesForP2PConv"); - LLIMModel::LLIMSession* im_session = LLIMModel::instance().findIMSession(mSessionID); - bool is_p2p_chat = im_session && im_session->isP2PSessionType(); - return (plain_text && (is_not_names || is_p2p_chat)); + return (plain_text && (is_not_names || mIsP2PChat)); } void LLIMFloater::onIMSessionMenuItemClicked(const LLSD& userdata) @@ -159,7 +160,8 @@ void LLIMFloater::onIMSessionMenuItemClicked(const LLSD& userdata) gSavedSettings.setBOOL(item, !prev_value); } - reloadMessages(); + LLIMFloater::processChatHistoryStyleUpdate(); + LLNearbyChat::processChatHistoryStyleUpdate(); } void LLIMFloater::onFocusLost() @@ -353,18 +355,16 @@ BOOL LLIMFloater::postBuild() mTypingStart = LLTrans::getString("IM_typing_start_string"); // Disable input editor if session cannot accept text - LLIMModel::LLIMSession* im_session = - LLIMModel::instance().findIMSession(mSessionID); - if ( im_session && !im_session->mTextIMPossible ) + if ( mSession && !mSession->mTextIMPossible ) { mInputEditor->setEnabled(FALSE); mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label")); } - if (im_session && im_session->isP2PSessionType()) + if (mIsP2PChat) { // look up display name for window title - LLAvatarNameCache::get(im_session->mOtherParticipantID, + LLAvatarNameCache::get(mSession->mOtherParticipantID, boost::bind(&LLIMFloater::onAvatarNameCache, this, _1, _2)); } @@ -424,16 +424,14 @@ void LLIMFloater::enableDisableCallBtn() bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); - LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionID); - - if (!session) + if (!mSession) { getChildView("voice_call_btn")->setEnabled(false); return; } - bool session_initialized = session->mSessionInitialized; - bool callback_enabled = session->mCallBackEnabled; + bool session_initialized = mSession->mSessionInitialized; + bool callback_enabled = mSession->mCallBackEnabled; BOOL enable_connect = session_initialized && voice_enabled @@ -763,12 +761,16 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) if (mSessionID != im_session_id) { mSessionID = im_session_id; + setKey(im_session_id); if (mControlPanel) { mControlPanel->setSessionId(im_session_id); } boundVoiceChannel(); + + mSession = LLIMModel::getInstance()->findIMSession(mSessionID); + mIsP2PChat = mSession && mSession->isP2PSessionType(); } //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) @@ -785,30 +787,35 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) } } -void LLIMFloater::updateMessages() +void LLIMFloater::appendMessage(const LLChat& chat, const LLSD &args) { - bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory"); + LLChat& tmp_chat = const_cast<LLChat&>(chat); + + if (!chat.mMuted) + { + tmp_chat.mFromName = chat.mFromName; + LLSD chat_args; + if (args) chat_args = args; + chat_args["use_plain_text_chat_history"] = + gSavedSettings.getBOOL("PlainTextChatHistory"); + chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); + chat_args["show_names_for_p2p_conv"] = !mIsP2PChat + || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + mChatHistory->appendMessage(chat, chat_args); + } +} + +void LLIMFloater::updateMessages() +{ std::list<LLSD> messages; // we shouldn't reset unread message counters if IM floater doesn't have focus - if (hasFocus()) - { - LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex + 1); - } - else - { - LLIMModel::instance().getMessagesSilently(mSessionID, messages, mLastMessageIndex + 1); - } + LLIMModel::instance().getMessages( + mSessionID, messages, mLastMessageIndex + 1, hasFocus()); if (messages.size()) { - bool is_p2p_chat = (mDialog == IM_SESSION_P2P_INVITE || mDialog == IM_NOTHING_SPECIAL); - LLSD chat_args; - chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history; - chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); - chat_args["show_names_for_p2p_conv"] = (!is_p2p_chat) || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); - std::ostringstream message; std::list<LLSD>::const_reverse_iterator iter = messages.rbegin(); std::list<LLSD>::const_reverse_iterator iter_end = messages.rend(); @@ -858,7 +865,7 @@ void LLIMFloater::updateMessages() chat.mText = message; } - mChatHistory->appendMessage(chat, chat_args); + appendMessage(chat); mLastMessageIndex = msg["index"].asInteger(); // if it is a notification - next message is a notification history log, so skip it @@ -1014,7 +1021,7 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body) } } -void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue) +void LLIMFloater::processChatHistoryStyleUpdate() { LLFontGL* font = LLViewerChat::getChatFont(); LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 03f52fb316..4cbdaccea5 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -27,12 +27,13 @@ #ifndef LL_IMFLOATER_H #define LL_IMFLOATER_H +#include "llimview.h" #include "llinstantmessage.h" #include "lllogchat.h" #include "lltooldraganddrop.h" -#include "lltransientdockablefloater.h" #include "llvoicechannel.h" #include "llvoiceclient.h" +#include "lltransientdockablefloater.h" class LLAvatarName; class LLButton; @@ -47,7 +48,7 @@ class LLInventoryCategory; * optionally "docked" to the bottom tray. */ class LLIMFloater - : public LLTransientDockableFloater + : public LLTransientDockableFloater , public LLVoiceClientStatusObserver { LOG_CLASS(LLIMFloater); @@ -109,7 +110,7 @@ public: void processAgentListUpdates(const LLSD& body); void processSessionUpdate(const LLSD& session_update); - static void processChatHistoryStyleUpdate(const LLSD& newvalue); + static void processChatHistoryStyleUpdate(); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, @@ -153,7 +154,7 @@ private: BOOL isInviteAllowed() const; BOOL inviteToSession(const uuid_vec_t& agent_ids); - + void appendMessage(const LLChat& chat, const LLSD &args = 0); static void onInputEditorFocusReceived( LLFocusableElement* caller,void* userdata ); static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); @@ -186,11 +187,13 @@ private: LLPanelChatControlPanel* mControlPanel; LLUUID mSessionID; + LLIMModel::LLIMSession* mSession; S32 mLastMessageIndex; + LLChatHistory* mChatHistory; + EInstantMessage mDialog; LLUUID mOtherParticipantUUID; - LLChatHistory* mChatHistory; LLLineEditor* mInputEditor; bool mPositioned; @@ -199,6 +202,7 @@ private: bool mMeTyping; bool mOtherTyping; bool mShouldSendTypingState; + bool mIsP2PChat; LLFrameTimer mTypingTimer; LLFrameTimer mTypingTimeoutTimer; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index a7c4618fa4..18d39b7aa4 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -716,6 +716,16 @@ bool LLIMModel::clearSession(const LLUUID& session_id) return true; } +void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index, const bool sendNoUnreadMsgs) +{ + getMessagesSilently(session_id, messages, start_index); + + if (sendNoUnreadMsgs) + { + sendNoUnreadMessages(session_id); + } +} + void LLIMModel::getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index) { LLIMSession* session = findIMSession(session_id); @@ -757,13 +767,6 @@ void LLIMModel::sendNoUnreadMessages(const LLUUID& session_id) mNoUnreadMsgsSignal(arg); } -void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index) -{ - getMessagesSilently(session_id, messages, start_index); - - sendNoUnreadMessages(session_id); -} - bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) { LLIMSession* session = findIMSession(session_id); @@ -2497,6 +2500,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess gIMMgr->addMessage(session_id, LLUUID::null, SYSTEM_FROM, message.getString()); } // log message to file + else { std::string session_name; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 7c2cd03d97..9d19af4b62 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -191,12 +191,6 @@ public: */ bool clearSession(const LLUUID& session_id); - /** - * Populate supplied std::list with messages starting from index specified by start_index without - * emitting no unread messages signal. - */ - void getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); - /** * Sends no unread messages signal. */ @@ -205,7 +199,7 @@ public: /** * Populate supplied std::list with messages starting from index specified by start_index */ - void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); + void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0, const bool sendNoUnreadMsgs = true); /** * Add a message to an IM Model - the message is saved in a message store associated with a session specified by session_id @@ -287,6 +281,12 @@ public: private: + /** + * Populate supplied std::list with messages starting from index specified by start_index without + * emitting no unread messages signal. + */ + void getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); + /** * Add message to a list of message associated with session specified by session_id */ diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 3a43750408..3c4b0b9aae 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -25,7 +25,6 @@ */ #include "llviewerprecompiledheaders.h" - #include "llnearbychat.h" #include "llviewercontrol.h" #include "llviewerwindow.h" @@ -55,8 +54,42 @@ #include "llfloaterreg.h" #include "lltrans.h" -static const S32 RESIZE_BAR_THICKNESS = 3; +// --- 2 functions in the global namespace :( --- +bool isWordsName(const std::string& name) +{ + // checking to see if it's display name plus username in parentheses + S32 open_paren = name.find(" (", 0); + S32 close_paren = name.find(')', 0); + + if (open_paren != std::string::npos && + close_paren == name.length()-1) + { + return true; + } + else + { + //checking for a single space + S32 pos = name.find(' ', 0); + return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos; + } +} + +std::string appendTime() +{ + time_t utc_time; + utc_time = time_corrected(); + std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" + +LLTrans::getString("TimeMin")+"]"; + + LLSD substitution; + + substitution["datetime"] = (S32) utc_time; + LLStringUtil::format (timeStr, substitution); + return timeStr; +} + +static const S32 RESIZE_BAR_THICKNESS = 3; static LLRegisterPanelClassWrapper<LLNearbyChat> t_panel_nearby_chat("panel_nearby_chat"); @@ -90,41 +123,32 @@ BOOL LLNearbyChat::postBuild() return true; } -std::string appendTime() -{ - time_t utc_time; - utc_time = time_corrected(); - std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" - +LLTrans::getString("TimeMin")+"]"; - - LLSD substitution; - - substitution["datetime"] = (S32) utc_time; - LLStringUtil::format (timeStr, substitution); - - return timeStr; -} - -void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +void LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args) { LLChat& tmp_chat = const_cast<LLChat&>(chat); if(tmp_chat.mTimeStr.empty()) tmp_chat.mTimeStr = appendTime(); - bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory"); - if (!chat.mMuted) { tmp_chat.mFromName = chat.mFromName; - LLSD chat_args = args; - chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history; - chat_args["show_time"] = true; - chat_args["show_names_for_p2p_conv"] = true; + LLSD chat_args; + if (args) chat_args = args; + chat_args["use_plain_text_chat_history"] = + gSavedSettings.getBOOL("PlainTextChatHistory"); + chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); + chat_args["show_names_for_p2p_conv"] = false + || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); mChatHistory->appendMessage(chat, chat_args); } +} + +void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +{ + appendMessage(chat, args); if(archive) { @@ -133,12 +157,9 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) mMessageArchive.erase(mMessageArchive.begin()); } - if (args["do_not_log"].asBoolean()) - { - return; - } - - if (gSavedPerAccountSettings.getBOOL("LogNearbyChat")) + // logging + if (!args["do_not_log"].asBoolean() + && gSavedPerAccountSettings.getBOOL("LogNearbyChat")) { std::string from_name = chat.mFromName; @@ -165,10 +186,10 @@ void LLNearbyChat::onNearbySpeakers() LLFloaterSidePanelContainer::showPanel("people", "panel_people", param); } - void LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata) { } + bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata) { std::string str = userdata.asString(); @@ -216,7 +237,7 @@ void LLNearbyChat::updateChatHistoryStyle() } //static -void LLNearbyChat::processChatHistoryStyleUpdate(const LLSD& newvalue) +void LLNearbyChat::processChatHistoryStyleUpdate() { LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); @@ -224,25 +245,6 @@ void LLNearbyChat::processChatHistoryStyleUpdate(const LLSD& newvalue) nearby_chat->updateChatHistoryStyle(); } -bool isWordsName(const std::string& name) -{ - // checking to see if it's display name plus username in parentheses - S32 open_paren = name.find(" (", 0); - S32 close_paren = name.find(')', 0); - - if (open_paren != std::string::npos && - close_paren == name.length()-1) - { - return true; - } - else - { - //checking for a single space - S32 pos = name.find(' ', 0); - return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos; - } -} - void LLNearbyChat::loadHistory() { LLSD do_not_log; diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 7c5975cbc5..47f4de1c6d 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -34,7 +34,8 @@ class LLResizeBar; class LLChatHistory; -class LLNearbyChat: public LLPanel +class LLNearbyChat +: public LLPanel { public: LLNearbyChat(const Params& p = LLPanel::getDefaultParams()); @@ -57,7 +58,7 @@ public: virtual void updateChatHistoryStyle(); - static void processChatHistoryStyleUpdate(const LLSD& newvalue); + static void processChatHistoryStyleUpdate(); void loadHistory(); @@ -67,7 +68,8 @@ public: private: void getAllowedRect (LLRect& rect); - + // prepare chat's params and out one message to chatHistory + void appendMessage(const LLChat& chat, const LLSD &args = 0); void onNearbySpeakers (); -- cgit v1.2.3 From acbce3248987d7e71be0fa0a251879c4066d9042 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Fri, 18 May 2012 02:04:22 +0300 Subject: CHUI-105 WIP Minor code clean up and optimization. Removed overloaded updateTitleButtons() and moved its functionality to a new method that should be called less frequently. --- indra/newview/llimfloater.cpp | 120 +++++++++++++++++++----------------------- indra/newview/llimfloater.h | 9 ++-- 2 files changed, 61 insertions(+), 68 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index c6608337c8..981250d223 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -65,6 +65,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mLastMessageIndex(-1), mDialog(IM_NOTHING_SPECIAL), mInputEditor(NULL), + mCloseBtn(NULL), mExpandCollapseBtn(NULL), mTearOffBtn(NULL), mSavedTitle(), @@ -192,6 +193,8 @@ void LLIMFloater::onOpen(const LLSD& key) // Show the messages pane when opening a floater hosted in the Conversations host_floater->collapseMessagesPane(false); } + + updateHeaderAndToolbar(); } // virtual @@ -308,7 +311,8 @@ BOOL LLIMFloater::postBuild() boundVoiceChannel(); - getChild<LLButton>("close_btn")->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); + mCloseBtn = getChild<LLButton>("close_btn"); + mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); @@ -328,7 +332,7 @@ BOOL LLIMFloater::postBuild() } mTearOffBtn = getChild<LLButton>("tear_off_btn"); - mTearOffBtn->setCommitCallback(boost::bind(&LLFloater::onClickTearOff, this)); + mTearOffBtn->setCommitCallback(boost::bind(&LLIMFloater::onTearOffClicked, this)); mInputEditor = getChild<LLLineEditor>("chat_editor"); mInputEditor->setMaxTextLength(1023); @@ -391,10 +395,11 @@ BOOL LLIMFloater::postBuild() } } -void LLIMFloater::onTearOffClicked(LLIMFloater* self) +void LLIMFloater::onTearOffClicked() { - onClickTearOff(self); - updateTitleButtons(); + onClickTearOff(this); + + updateHeaderAndToolbar(); } void LLIMFloater::boundVoiceChannel() @@ -1256,6 +1261,51 @@ void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info) } } +void LLIMFloater::updateHeaderAndToolbar() +{ + bool is_hosted = getHost() != NULL; + + if (is_hosted) + { + for (S32 i = 0; i < BUTTON_COUNT; i++) + { + if (!mButtons[i]) + { + continue; + } + + // Hide the standard header buttons in a docked IM floater. + mButtons[i]->setVisible(false); + } + } + + // Display collapse image (<<) if the floater is hosted + // or if it is torn off but has an open control panel. + bool is_expanded = is_hosted || (mControlPanel && mControlPanel->getParent()->getVisible()); + mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); + + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); + if (session) + { + // The button (>>) should be disabled for torn off P2P conversations. + mExpandCollapseBtn->setEnabled(is_hosted || !session->isP2PSessionType()); + } + else + { + llwarns << "IM session not found." << llendl; + } + + if (mDragHandle) + { + // toggle floater's drag handle and title visibility + mDragHandle->setVisible(!is_hosted); + } + + mTearOffBtn->setImageOverlay(getString(is_hosted ? "tear_off_icon" : "return_icon")); + + mCloseBtn->setVisible(is_hosted); +} + // static void LLIMFloater::closeHiddenIMToasts() { @@ -1376,63 +1426,3 @@ void LLIMFloater::onClickCloseBtn() LLFloater::onClickCloseBtn(); } - -// virtual -void LLIMFloater::updateTitleButtons() -{ - // This gets called before LLIMFloater::postBuild() while some LLIMFloater members are NULL - if ( !mDragHandle - //|| !mControlPanel - || !mExpandCollapseBtn - || !mTearOffBtn) - { - return; - } - - bool is_hosted = getHost() != NULL; - - if (is_hosted) ///< floater is hosted - { - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - if (!mButtons[i]) - { - continue; - } - - // Hide the standard header buttons in a docked IM floater. - mButtons[i]->setVisible(false); - } - - mExpandCollapseBtn->setImageOverlay(getString("collapse_icon")); - - } - else ///< floater is torn off - { - LLFloater::updateTitleButtons(); - - if (mControlPanel) - { - bool is_expanded = mControlPanel->getParent()->getVisible(); - mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); - } - } - - getChild<LLButton>("close_btn")->setVisible(is_hosted); - - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); - if (session) - { - mExpandCollapseBtn->setEnabled(is_hosted || !session->isP2PSessionType()); - } - else - { - llwarns << "Empty session." << llendl; - return; - } - - // toggle floater's drag handle and title visibility - mDragHandle->setVisible(!is_hosted); - - mTearOffBtn->setImageOverlay(getString(is_hosted ? "tear_off_icon" : "return_icon")); -} diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 4cbdaccea5..8e7ab4cc21 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -134,15 +134,12 @@ public: protected: /* virtual */ void onClickCloseBtn(); - /* virtual */ void updateTitleButtons(); private: // process focus events to set a currently active session /* virtual */ void onFocusLost(); /* virtual */ void onFocusReceived(); - void onTearOffClicked(LLIMFloater *self); - // Update the window title, input field help text, etc. void updateSessionName(const std::string& ui_title, const std::string& ui_label); @@ -163,6 +160,8 @@ private: static void* createPanelGroupControl(void* userdata); static void* createPanelAdHocControl(void* userdata); + void onTearOffClicked(); + bool onIMCompactExpandedMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemEnable(const LLSD& userdata); @@ -181,6 +180,9 @@ private: // Remove the "User is typing..." indicator. void removeTypingIndicator(const LLIMInfo* im_info = NULL); + /// Update floater header and toolbar buttons when hosted/torn off state is toggled. + void updateHeaderAndToolbar(); + static void closeHiddenIMToasts(); static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); @@ -212,6 +214,7 @@ private: // connection to voice channel state change signal boost::signals2::connection mVoiceChannelStateChangeConnection; + LLButton* mCloseBtn; LLButton* mExpandCollapseBtn; LLButton* mTearOffBtn; }; -- cgit v1.2.3 From a572f31ffb79ddfd61bcbb4b6fcb79bfa796d191 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Fri, 18 May 2012 20:50:50 +0300 Subject: CHUI-121 FIXED showing chat participants list only in torn off IM floaters. --- indra/newview/llimfloater.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 981250d223..97f59f9a15 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -1279,9 +1279,17 @@ void LLIMFloater::updateHeaderAndToolbar() } } + bool is_control_panel_visible = false; + if (mControlPanel) + { + // Control panel should be visible only in torn off floaters. + is_control_panel_visible = !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel"); + mControlPanel->getParent()->setVisible(is_control_panel_visible); + } + // Display collapse image (<<) if the floater is hosted // or if it is torn off but has an open control panel. - bool is_expanded = is_hosted || (mControlPanel && mControlPanel->getParent()->getVisible()); + bool is_expanded = is_hosted || is_control_panel_visible; mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); -- cgit v1.2.3 From 296e55c1b323c05b6544b69ace04afe19102396b Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 18 May 2012 13:20:32 -0700 Subject: CHUI-112 FIX Clicking Show or Discard in an inventory offer toast does not dismiss toast removed special case logic for dealing with user online/offline collisions added ability to cancel old duplicate notifications --- indra/llui/llnotifications.cpp | 135 +++-- indra/llui/llnotifications.h | 24 +- indra/llui/llnotificationtemplate.h | 10 +- indra/newview/llavataractions.cpp | 1 - indra/newview/llcallingcard.cpp | 6 +- indra/newview/llchathistory.cpp | 30 +- indra/newview/llchatitemscontainerctrl.cpp | 1 - indra/newview/llchatitemscontainerctrl.h | 2 +- indra/newview/llimfloater.cpp | 1 + indra/newview/llnearbychathandler.cpp | 70 +-- indra/newview/llnotificationgrouphandler.cpp | 11 - indra/newview/llnotificationhandler.h | 21 +- indra/newview/llnotificationhandlerutil.cpp | 68 +-- indra/newview/llnotificationofferhandler.cpp | 124 ++-- indra/newview/llnotificationscripthandler.cpp | 16 +- indra/newview/llnotificationtiphandler.cpp | 15 - indra/newview/llscreenchannel.cpp | 104 ++-- indra/newview/llscreenchannel.h | 8 +- indra/newview/lltoast.h | 7 +- indra/newview/lltoastimpanel.h | 10 +- indra/newview/lltoastnotifypanel.cpp | 660 +++++++++++---------- indra/newview/lltoastnotifypanel.h | 28 +- indra/newview/lltoastpanel.cpp | 11 +- indra/newview/lltoastpanel.h | 8 +- indra/newview/llviewermessage.cpp | 41 +- .../newview/skins/default/xui/en/notifications.xml | 22 +- indra/newview/skins/default/xui/en/strings.xml | 2 + 27 files changed, 721 insertions(+), 715 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 9ef9b4bbec..663749b983 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -60,7 +60,8 @@ void NotificationPriorityValues::declareValues() } LLNotificationForm::FormElementBase::FormElementBase() -: name("name") +: name("name"), + enabled("enabled", true) {} LLNotificationForm::FormIgnore::FormIgnore() @@ -210,6 +211,14 @@ LLNotificationForm::LLNotificationForm() { } +LLNotificationForm::LLNotificationForm( const LLNotificationForm& other ) +{ + mFormData = other.mFormData; + mIgnore = other.mIgnore; + mIgnoreMsg = other.mIgnoreMsg; + mIgnoreSetting = other.mIgnoreSetting; + mInvertSetting = other.mInvertSetting; +} LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotificationForm::Params& p) : mIgnore(IGNORE_NO), @@ -300,7 +309,7 @@ LLSD LLNotificationForm::getElement(const std::string& element_name) } -bool LLNotificationForm::hasElement(const std::string& element_name) +bool LLNotificationForm::hasElement(const std::string& element_name) const { for (LLSD::array_const_iterator it = mFormData.beginArray(); it != mFormData.endArray(); @@ -311,7 +320,36 @@ bool LLNotificationForm::hasElement(const std::string& element_name) return false; } -void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value) +bool LLNotificationForm::getElementEnabled(const std::string& element_name) const +{ + for (LLSD::array_const_iterator it = mFormData.beginArray(); + it != mFormData.endArray(); + ++it) + { + if ((*it)["name"].asString() == element_name) + { + return (*it)["enabled"].asBoolean(); + } + } + + return false; +} + +void LLNotificationForm::setElementEnabled(const std::string& element_name, bool enabled) +{ + for (LLSD::array_iterator it = mFormData.beginArray(); + it != mFormData.endArray(); + ++it) + { + if ((*it)["name"].asString() == element_name) + { + (*it)["enabled"] = enabled; + } + } +} + + +void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value, bool enabled) { LLSD element; element["type"] = type; @@ -319,6 +357,7 @@ void LLNotificationForm::addElement(const std::string& type, const std::string& element["text"] = name; element["value"] = value; element["index"] = mFormData.size(); + element["enabled"] = enabled; mFormData.append(element); } @@ -412,7 +451,8 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par mPersist(p.persist), mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()), mLogToChat(p.log_to_chat), - mLogToIM(p.log_to_im) + mLogToIM(p.log_to_im), + mShowToast(p.show_toast) { if (p.sound.isProvided() && LLUI::sSettingGroups["config"]->controlExists(p.sound)) @@ -571,7 +611,6 @@ void LLNotification::updateFrom(LLNotificationPtr other) mRespondedTo = other->mRespondedTo; mResponse = other->mResponse; mTemporaryResponder = other->mTemporaryResponder; - mIsReusable = other->isReusable(); update(); } @@ -670,7 +709,7 @@ void LLNotification::respond(const LLSD& response) return; } - if (mTemporaryResponder && !isReusable()) + if (mTemporaryResponder) { LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName); mResponseFunctorName = ""; @@ -899,6 +938,11 @@ bool LLNotification::canLogToIM() const return mTemplatep->mLogToIM; } +bool LLNotification::canShowToast() const +{ + return mTemplatep->mShowToast; +} + bool LLNotification::hasFormElements() const { return mTemplatep->mForm->getNumElements() != 0; @@ -909,6 +953,17 @@ LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const return mTemplatep->mCombineBehavior; } +void LLNotification::updateForm( const LLNotificationFormPtr& form ) +{ + mForm = form; +} + +void LLNotification::repost() +{ + mRespondedTo = false; + LLNotifications::instance().update(shared_from_this()); +} + // ========================================================= @@ -1065,12 +1120,8 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt if (wasFound) { abortProcessing = mChanged(payload); - // do not delete the notification to make LLChatHistory::appendMessage add notification panel to IM window - if( ! pNotification->isReusable() ) - { - mItems.erase(pNotification); - onDelete(pNotification); - } + mItems.erase(pNotification); + onDelete(pNotification); } } return abortProcessing; @@ -1207,7 +1258,15 @@ bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif) if (pNotif != existing_notification && pNotif->isEquivalentTo(existing_notification)) { - return false; + if (pNotif->getCombineBehavior() == LLNotification::CANCEL_OLD) + { + cancel(existing_notification); + return true; + } + else + { + return false; + } } } @@ -1247,26 +1306,35 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload) return false; } - if (pNotif->getCombineBehavior() == LLNotification::USE_NEWEST) - { - // Update the existing unique notification with the data from this particular instance... - // This guarantees that duplicate notifications will be collapsed to the one - // most recently triggered - for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); - existing_it != mUniqueNotifications.end(); - ++existing_it) + switch(pNotif->getCombineBehavior()) { - LLNotificationPtr existing_notification = existing_it->second; - if (pNotif != existing_notification - && pNotif->isEquivalentTo(existing_notification)) + case LLNotification::REPLACE_WITH_NEW: + // Update the existing unique notification with the data from this particular instance... + // This guarantees that duplicate notifications will be collapsed to the one + // most recently triggered + for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); + existing_it != mUniqueNotifications.end(); + ++existing_it) { - // copy notification instance data over to oldest instance - // of this unique notification and update it - existing_notification->updateFrom(pNotif); - // then delete the new one - cancel(pNotif); + LLNotificationPtr existing_notification = existing_it->second; + if (pNotif != existing_notification + && pNotif->isEquivalentTo(existing_notification)) + { + // copy notification instance data over to oldest instance + // of this unique notification and update it + existing_notification->updateFrom(pNotif); + // then delete the new one + cancel(pNotif); + } } - } + break; + case LLNotification::KEEP_OLD: + break; + case LLNotification::CANCEL_OLD: + // already handled by filter logic + break; + default: + break; } return false; @@ -1594,12 +1662,11 @@ void LLNotifications::cancel(LLNotificationPtr pNotif) if (pNotif == NULL || pNotif->isCancelled()) return; LLNotificationSet::iterator it=mItems.find(pNotif); - if (it == mItems.end()) + if (it != mItems.end()) { - llerrs << "Attempted to delete nonexistent notification " << pNotif->getName() << llendl; + pNotif->cancel(); + updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif); } - pNotif->cancel(); - updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif); } void LLNotifications::cancelByName(const std::string& name) diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 21a4318aab..e9449eae69 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -165,6 +165,7 @@ public: struct FormElementBase : public LLInitParam::Block<FormElementBase> { Optional<std::string> name; + Optional<bool> enabled; FormElementBase(); }; @@ -234,16 +235,20 @@ public: } EIgnoreType; LLNotificationForm(); + LLNotificationForm(const LLNotificationForm&); LLNotificationForm(const LLSD& sd); LLNotificationForm(const std::string& name, const Params& p); + void fromLLSD(const LLSD& sd); LLSD asLLSD() const; S32 getNumElements() { return mFormData.size(); } LLSD getElement(S32 index) { return mFormData.get(index); } LLSD getElement(const std::string& element_name); - bool hasElement(const std::string& element_name); - void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD()); + bool hasElement(const std::string& element_name) const; + bool getElementEnabled(const std::string& element_name) const; + void setElementEnabled(const std::string& element_name, bool enabled); + void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD(), bool enabled = true); void formatElements(const LLSD& substitutions); // appends form elements from another form serialized as LLSD void append(const LLSD& sub_form); @@ -450,6 +455,11 @@ public: // ["responseFunctor"] = name of registered functor that handles responses to notification; LLSD asLLSD(); + const LLNotificationFormPtr getForm(); + void updateForm(const LLNotificationFormPtr& form); + + void repost(); + void respond(const LLSD& sd); void respondWithDefault(); @@ -517,16 +527,18 @@ public: S32 getURLOpenExternally() const; bool canLogToChat() const; bool canLogToIM() const; + bool canShowToast() const; bool hasFormElements() const; typedef enum e_combine_behavior { - USE_NEWEST, - USE_OLDEST + REPLACE_WITH_NEW, + KEEP_OLD, + CANCEL_OLD + } ECombineBehavior; ECombineBehavior getCombineBehavior() const; - const LLNotificationFormPtr getForm(); const LLDate getExpiration() const { @@ -545,8 +557,6 @@ public: bool isReusable() { return mIsReusable; } - void setReusable(bool reusable) { mIsReusable = reusable; } - // comparing two notifications normally means comparing them by UUID (so we can look them // up quickly this way) bool operator<(const LLNotification& rhs) const diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index f7d08ae1f4..ca9c4294c1 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -66,8 +66,9 @@ struct LLNotificationTemplate { static void declareValues() { - declare("newest", LLNotification::USE_NEWEST); - declare("oldest", LLNotification::USE_OLDEST); + declare("replace_with_new", LLNotification::REPLACE_WITH_NEW); + declare("keep_old", LLNotification::KEEP_OLD); + declare("cancel_old", LLNotification::CANCEL_OLD); } }; @@ -109,7 +110,7 @@ struct LLNotificationTemplate UniquenessConstraint() : contexts("context"), - combine("combine", LLNotification::USE_NEWEST), + combine("combine", LLNotification::REPLACE_WITH_NEW), dummy_val("") {} }; @@ -185,6 +186,7 @@ struct LLNotificationTemplate Mandatory<std::string> name; Optional<bool> persist, log_to_im, + show_toast, log_to_chat; Optional<std::string> functor, icon, @@ -206,6 +208,7 @@ struct LLNotificationTemplate : name("name"), persist("persist", false), log_to_im("log_to_im", false), + show_toast("show_toast", true), log_to_chat("log_to_chat", true), functor("functor"), icon("icon"), @@ -313,6 +316,7 @@ struct LLNotificationTemplate // inject these notifications into chat/IM streams bool mLogToChat; bool mLogToIM; + bool mShowToast; }; #endif //LL_LLNOTIFICATION_TEMPLATE_H diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index ac14ec2cc0..aa626a9a30 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -1024,7 +1024,6 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri LLSD payload; payload["from_id"] = target_id; - payload["SUPPRESS_TOAST"] = true; LLNotificationsUtil::add("FriendshipOffered", args, payload); } diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 0d55c4429a..60d60abd45 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -54,6 +54,7 @@ #include "llresmgr.h" #include "llslurl.h" #include "llimview.h" +#include "lltrans.h" #include "llviewercontrol.h" #include "llviewernetwork.h" #include "llviewerobjectlist.h" @@ -723,12 +724,13 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, // Use display name only because this user is your friend LLSD args; args["NAME"] = av_name.mDisplayName; + args["STATUS"] = online ? LLTrans::getString("OnlineStatus") : LLTrans::getString("OfflineStatus"); LLNotificationPtr notification; if (online) { notification = - LLNotificationsUtil::add("FriendOnline", + LLNotificationsUtil::add("FriendOnlineOffline", args, payload.with("respond_on_mousedown", TRUE), boost::bind(&LLAvatarActions::startIM, agent_id)); @@ -736,7 +738,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, else { notification = - LLNotificationsUtil::add("FriendOffline", args, payload); + LLNotificationsUtil::add("FriendOnlineOffline", args, payload); } // If there's an open IM session with this agent, send a notification there too. diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 5bdfb5adbc..3da868945b 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -877,35 +877,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (notification != NULL) { LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel( - notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history); - //we can't set follows in xml since it broke toasts behavior - notify_box->setFollowsLeft(); - notify_box->setFollowsRight(); - notify_box->setFollowsTop(); - - ctrl_list_t ctrls = notify_box->getControlPanel()->getCtrlList(); - S32 offset = 0; - // Children were added by addChild() which uses push_front to insert them into list, - // so to get buttons in correct order reverse iterator is used (EXT-5906) - for (ctrl_list_t::reverse_iterator it = ctrls.rbegin(); it != ctrls.rend(); it++) - { - LLButton * button = dynamic_cast<LLButton*> (*it); - if (button != NULL) - { - button->setOrigin( offset, - button->getRect().mBottom); - button->setLeftHPad(2 * HPAD); - button->setRightHPad(2 * HPAD); - // set zero width before perform autoResize() - button->setRect(LLRect(button->getRect().mLeft, - button->getRect().mTop, button->getRect().mLeft, - button->getRect().mBottom)); - button->setAutoResize(true); - button->autoResize(); - offset += HPAD + button->getRect().getWidth(); - button->setFollowsNone(); - } - } + notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history, mEditor); //Prepare the rect for the view LLRect target_rect = mEditor->getDocumentView()->getRect(); diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 9a84280f25..7477fbd656 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -372,7 +372,6 @@ void LLNearbyChatToastPanel::draw() } mIsDirty = false; } - LLToastPanelBase::draw(); } diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h index 1d700dcede..89b0c4f37a 100644 --- a/indra/newview/llchatitemscontainerctrl.h +++ b/indra/newview/llchatitemscontainerctrl.h @@ -40,7 +40,7 @@ typedef enum e_show_item_header CHATITEMHEADER_SHOW_BOTH } EShowItemHeader; -class LLNearbyChatToastPanel: public LLToastPanelBase +class LLNearbyChatToastPanel : public LLPanel { protected: LLNearbyChatToastPanel() diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index f67464078b..724ae3c25e 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -56,6 +56,7 @@ #include "llrootview.h" #include "llspeakers.h" #include "llviewerchat.h" +#include "llnotificationmanager.h" LLIMFloater::LLIMFloater(const LLUUID& session_id) diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 4d9db01e0d..f26cc85019 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -1,6 +1,6 @@ /** * @file LLNearbyChatHandler.cpp - * @brief Nearby chat notification managment + * @brief Nearby chat chat managment * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code @@ -47,15 +47,17 @@ //add LLNearbyChatHandler to LLNotificationsUI namespace using namespace LLNotificationsUI; -//----------------------------------------------------------------------------------------------- -//LLNearbyChatScreenChannel -//----------------------------------------------------------------------------------------------- -LLToastPanelBase* createToastPanel() +static LLNearbyChatToastPanel* createToastPanel() { LLNearbyChatToastPanel* item = LLNearbyChatToastPanel::createInstance(); return item; } + +//----------------------------------------------------------------------------------------------- +//LLNearbyChatScreenChannel +//----------------------------------------------------------------------------------------------- + class LLNearbyChatScreenChannel: public LLScreenChannelBase { LOG_CLASS(LLNearbyChatScreenChannel); @@ -81,10 +83,10 @@ public: } } - void addNotification (LLSD& notification); + void addChat (LLSD& chat); void arrangeToasts (); - typedef boost::function<LLToastPanelBase* (void )> create_toast_panel_callback_t; + typedef boost::function<LLNearbyChatToastPanel* (void )> create_toast_panel_callback_t; void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;} void onToastDestroyed (LLToast* toast, bool app_quitting); @@ -152,6 +154,8 @@ protected: bool mChannelRect; }; + + //----------------------------------------------------------------------------------------------- // LLNearbyChatToast //----------------------------------------------------------------------------------------------- @@ -255,7 +259,7 @@ void LLNearbyChatScreenChannel::updateToastFadingTime() bool LLNearbyChatScreenChannel::createPoolToast() { - LLToastPanelBase* panel= m_create_toast_panel_callback_t(); + LLNearbyChatToastPanel* panel= m_create_toast_panel_callback_t(); if(!panel) return false; @@ -277,7 +281,7 @@ bool LLNearbyChatScreenChannel::createPoolToast() return true; } -void LLNearbyChatScreenChannel::addNotification(LLSD& notification) +void LLNearbyChatScreenChannel::addChat(LLSD& chat) { //look in pool. if there is any message if(mStopProcessing) @@ -289,8 +293,8 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification) if(m_active_toasts.size()) { - LLUUID fromID = notification["from_id"].asUUID(); // agent id or object id - std::string from = notification["from"].asString(); + LLUUID fromID = chat["from_id"].asUUID(); // agent id or object id + std::string from = chat["from"].asString(); LLToast* toast = m_active_toasts[0].get(); if (toast) { @@ -298,7 +302,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification) if(panel && panel->messageID() == fromID && panel->getFromName() == from && panel->canAddText()) { - panel->addMessage(notification); + panel->addMessage(chat); toast->reshapeToPanel(); toast->startTimer(); @@ -316,11 +320,11 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification) LL_DEBUGS("NearbyChat") << "Empty pool" << llendl; if(!createPoolToast())//created toast will go to pool. so next call will find it return; - addNotification(notification); + addChat(chat); return; } - int chat_type = notification["chat_type"].asInteger(); + int chat_type = chat["chat_type"].asInteger(); if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG)) { @@ -339,10 +343,10 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification) m_toast_pool.pop_back(); - LLToastPanelBase* panel = dynamic_cast<LLToastPanelBase*>(toast->getPanel()); + LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel()); if(!panel) return; - panel->init(notification); + panel->init(chat); toast->reshapeToPanel(); toast->startTimer(); @@ -488,23 +492,23 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); // Build notification data - LLSD notification; - notification["message"] = chat_msg.mText; - notification["from"] = chat_msg.mFromName; - notification["from_id"] = chat_msg.mFromID; - notification["time"] = chat_msg.mTime; - notification["source"] = (S32)chat_msg.mSourceType; - notification["chat_type"] = (S32)chat_msg.mChatType; - notification["chat_style"] = (S32)chat_msg.mChatStyle; + LLSD chat; + chat["message"] = chat_msg.mText; + chat["from"] = chat_msg.mFromName; + chat["from_id"] = chat_msg.mFromID; + chat["time"] = chat_msg.mTime; + chat["source"] = (S32)chat_msg.mSourceType; + chat["chat_type"] = (S32)chat_msg.mChatType; + chat["chat_style"] = (S32)chat_msg.mChatStyle; // Pass sender info so that it can be rendered properly (STORM-1021). - notification["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args); + chat["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args); if (chat_msg.mChatType == CHAT_TYPE_DIRECT && chat_msg.mText.length() > 0 && chat_msg.mText[0] == '@') { // Send event on to LLEventStream and exit - sChatWatcher->post(notification); + sChatWatcher->post(chat); return; } @@ -551,7 +555,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, } // Send event on to LLEventStream - sChatWatcher->post(notification); + sChatWatcher->post(chat); if( !chat_bar->isMinimized() @@ -602,16 +606,16 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, // Add a nearby chat toast. LLUUID id; id.generate(); - notification["id"] = id; + chat["id"] = id; std::string r_color_name = "White"; F32 r_color_alpha = 1.0f; LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha); - notification["text_color"] = r_color_name; - notification["color_alpha"] = r_color_alpha; - notification["font_size"] = (S32)LLViewerChat::getChatFontSize() ; - notification["message"] = toast_msg; - channel->addNotification(notification); + chat["text_color"] = r_color_name; + chat["color_alpha"] = r_color_alpha; + chat["font_size"] = (S32)LLViewerChat::getChatFontSize() ; + chat["message"] = toast_msg; + channel->addChat(chat); } } diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 6946b78cbf..18cd94e685 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -44,7 +44,6 @@ LLGroupHandler::LLGroupHandler() LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); if(channel) { - channel->addOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1)); mChannel = channel->getHandle(); } } @@ -94,16 +93,6 @@ bool LLGroupHandler::processNotification(const LLNotificationPtr& notification) return false; } -//-------------------------------------------------------------------------- -void LLGroupHandler::onRejectToast(LLUUID& id) -{ - LLNotificationPtr notification = LLNotifications::instance().find(id); - - if (notification && mItems.find(notification) != mItems.end()) - { - LLNotifications::instance().cancel(notification); - } -} //-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 83d228e799..4d54bb78fc 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -95,16 +95,9 @@ public: // base interface functions /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } /*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->killToastByNotificationID(p->getID());} + /*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());} virtual bool processNotification(const LLNotificationPtr& notify)=0; - -protected : - static void init(); - void removeExclusiveNotifications(const LLNotificationPtr& notif); - - typedef std::list< std::set<std::string> > exclusive_notif_sets; - static exclusive_notif_sets sExclusiveNotificationGroups; }; /** @@ -148,7 +141,6 @@ public: /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: - /*virtual*/ void onRejectToast(const LLUUID& id); /*virtual*/ void initChannel(); }; @@ -169,9 +161,6 @@ public: protected: /*virtual*/ void onDeleteToast(LLToast* toast); /*virtual*/ void initChannel(); - - // own handlers - void onRejectToast(LLUUID& id); }; @@ -190,9 +179,6 @@ public: protected: virtual void initChannel(); - - // own handlers - void onRejectToast(LLUUID& id); }; /** @@ -225,15 +211,12 @@ public: virtual ~LLOfferHandler(); // base interface functions - /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onChange(LLNotificationPtr p); /*virtual*/ void onDelete(LLNotificationPtr notification); /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: /*virtual*/ void initChannel(); - - // own handlers - void onRejectToast(LLUUID& id); }; /** diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 1494ac6b5c..cba22b233b 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -41,75 +41,9 @@ using namespace LLNotificationsUI; -// static -std::list< std::set<std::string> > LLSysHandler::sExclusiveNotificationGroups; - -// static -void LLSysHandler::init() -{ - std::set<std::string> online_offline_group; - online_offline_group.insert("FriendOnline"); - online_offline_group.insert("FriendOffline"); - - sExclusiveNotificationGroups.push_back(online_offline_group); -} - LLSysHandler::LLSysHandler(const std::string& name, const std::string& notification_type) : LLNotificationChannel(name, "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, notification_type)) -{ - if(sExclusiveNotificationGroups.empty()) - { - init(); - } -} - -void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif) -{ - LLScreenChannel* channel = dynamic_cast<LLScreenChannel *>(mChannel.get()); - if (channel == NULL) - { - return; - } - - class ExclusiveMatcher: public LLScreenChannel::Matcher - { - public: - ExclusiveMatcher(const std::set<std::string>& excl_group, - const std::string& from_name) : - mExclGroup(excl_group), mFromName(from_name) - { - } - bool matches(const LLNotificationPtr notification) const - { - for (std::set<std::string>::const_iterator it = mExclGroup.begin(); it - != mExclGroup.end(); it++) - { - std::string from_name = LLHandlerUtil::getSubstitutionName(notification); - if (notification->getName() == *it && from_name == mFromName) - { - return true; - } - } - return false; - } - private: - const std::set<std::string>& mExclGroup; - const std::string& mFromName; - }; - - - for (exclusive_notif_sets::iterator it = sExclusiveNotificationGroups.begin(); it - != sExclusiveNotificationGroups.end(); it++) - { - std::set<std::string> group = *it; - std::set<std::string>::iterator g_it = group.find(notif->getName()); - if (g_it != group.end()) - { - channel->killMatchedToasts(ExclusiveMatcher(group, - LLHandlerUtil::getSubstitutionName(notif))); - } - } -} +{} // static bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 2112b0d35e..6e641575fa 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -48,7 +48,6 @@ LLOfferHandler::LLOfferHandler() if(channel) { channel->setControlHovering(true); - channel->addOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1)); mChannel = channel->getHandle(); } } @@ -81,92 +80,95 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) } - if( notification->getPayload().has("give_inventory_notification") + if( notification->getPayload().has("give_inventory_notification") && notification->getPayload()["give_inventory_notification"].asBoolean() == false) - { - // This is an original inventory offer, so add a script floater - LLScriptFloaterManager::instance().onAddNotification(notification->getID()); - } - else - { + { + // This is an original inventory offer, so add a script floater + LLScriptFloaterManager::instance().onAddNotification(notification->getID()); + } + else + { bool add_notif_to_im = notification->canLogToIM() && notification->hasFormElements(); - notification->setReusable(add_notif_to_im); - - LLUUID session_id; if (add_notif_to_im) - { - const std::string name = LLHandlerUtil::getSubstitutionName(notification); + { + const std::string name = LLHandlerUtil::getSubstitutionName(notification); - LLUUID from_id = notification->getPayload()["from_id"]; + LLUUID from_id = notification->getPayload()["from_id"]; - session_id = LLHandlerUtil::spawnIMSession(name, from_id); - LLHandlerUtil::addNotifPanelToIM(notification); - } + LLHandlerUtil::spawnIMSession(name, from_id); + LLHandlerUtil::addNotifPanelToIM(notification); + } - if (notification->getPayload().has("SUPPRESS_TOAST") - && notification->getPayload()["SUPPRESS_TOAST"]) - { - LLNotificationsUtil::cancel(notification); - } + if (!notification->canShowToast()) + { + LLNotificationsUtil::cancel(notification); + } else if(!notification->canLogToIM() || !LLHandlerUtil::isIMFloaterOpened(notification)) - { - LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); - // don't close notification on panel destroy since it will be used by IM floater - notify_box->setCloseNotificationOnDestroy(!add_notif_to_im); - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.panel = notify_box; - // we not save offer notifications to the syswell floater that should be added to the IM floater + { + LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = notify_box; + // we not save offer notifications to the syswell floater that should be added to the IM floater p.can_be_stored = !add_notif_to_im; - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); - if(channel) - channel->addToast(p); - } + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); + if(channel) + channel->addToast(p); + } if (notification->canLogToIM()) - { - // log only to file if notif panel can be embedded to IM and IM is opened + { + // log only to file if notif panel can be embedded to IM and IM is opened bool file_only = add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification); LLHandlerUtil::logToIMP2P(notification, file_only); - } - } + } + } return false; - } +} -/*virtual*/ void LLOfferHandler::onDelete(LLNotificationPtr notification) +/*virtual*/ void LLOfferHandler::onChange(LLNotificationPtr p) +{ + LLToastNotifyPanel* panelp = LLToastNotifyPanel::getInstance(p->getID()); + if (panelp) { - if( notification->getPayload().has("give_inventory_notification") - && !notification->getPayload()["give_inventory_notification"] ) + // + // HACK: if we're dealing with a notification embedded in IM, update it + // otherwise remove its toast + // + if (dynamic_cast<LLIMToastNotifyPanel*>(panelp)) { - // Remove original inventory offer script floater - LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); + panelp->updateNotification(); } else { - if (notification->canLogToIM() - && notification->hasFormElements() - && !LLHandlerUtil::isIMFloaterOpened(notification)) - { - LLHandlerUtil::decIMMesageCounter(notification); - } - mChannel.get()->killToastByNotificationID(notification->getID()); + // if notification has changed, hide it + mChannel.get()->removeToastByNotificationID(p->getID()); } } +} -//-------------------------------------------------------------------------- -void LLOfferHandler::onRejectToast(LLUUID& id) -{ - LLNotificationPtr notification = LLNotifications::instance().find(id); - if (notification - && mItems.find(notification) != mItems.end() - // don't delete notification since it may be used by IM floater - && (!notification->canLogToIM() || !notification->hasFormElements())) +/*virtual*/ void LLOfferHandler::onDelete(LLNotificationPtr notification) +{ + if( notification->getPayload().has("give_inventory_notification") + && !notification->getPayload()["give_inventory_notification"] ) + { + // Remove original inventory offer script floater + LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); + } + else { - LLNotifications::instance().cancel(notification); + if (notification->canLogToIM() + && notification->hasFormElements() + && !LLHandlerUtil::isIMFloaterOpened(notification)) + { + LLHandlerUtil::decIMMesageCounter(notification); + } + mChannel.get()->removeToastByNotificationID(notification->getID()); } } + diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 8472f9b2ae..9f7d0cc2f5 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -46,7 +46,6 @@ LLScriptHandler::LLScriptHandler() if(channel) { channel->setControlHovering(true); - channel->addOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1)); mChannel = channel->getHandle(); } } @@ -116,7 +115,7 @@ void LLScriptHandler::onDelete( LLNotificationPtr notification ) } else { - mChannel.get()->killToastByNotificationID(notification->getID()); + mChannel.get()->removeToastByNotificationID(notification->getID()); } } @@ -135,19 +134,6 @@ void LLScriptHandler::onDeleteToast(LLToast* toast) } } -//-------------------------------------------------------------------------- -void LLScriptHandler::onRejectToast(LLUUID& id) -{ - LLNotificationPtr notification = LLNotifications::instance().find(id); - - if (notification && mItems.find(notification) != mItems.end()) - { - LLNotifications::instance().cancel(notification); - } -} - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 3588721849..a1d5db2e27 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -48,7 +48,6 @@ LLTipHandler::LLTipHandler() LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); if(channel) { - channel->addOnRejectToastCallback(boost::bind(&LLTipHandler::onRejectToast, this, _1)); mChannel = channel->getHandle(); } } @@ -127,22 +126,8 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) p.is_tip = true; p.can_be_stored = false; - removeExclusiveNotifications(notification); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->addToast(p); return false; } - -//-------------------------------------------------------------------------- - -void LLTipHandler::onRejectToast(const LLUUID& id) -{ - LLNotificationPtr notification = LLNotifications::instance().find(id); - - if (notification && mItems.find(notification) != mItems.end()) - { - LLNotifications::instance().cancel(notification); - } -} diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 003b53b28c..839ca0f9c5 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -265,7 +265,14 @@ void LLScreenChannel::addToast(const LLToast::Params& p) if(!show_toast && !store_toast) { - mRejectToastSignal(p.notif_id); + LLNotificationPtr notification = LLNotifications::instance().find(p.notif_id); + + if (notification && + (!notification->canLogToIM() || !notification->hasFormElements())) + { + // only cancel notification if it isn't being used in IM session + LLNotifications::instance().cancel(notification); + } return; } @@ -431,35 +438,13 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id) redrawToasts(); } -//-------------------------------------------------------------------------- -void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id) -{ - // *TODO: may be remove this function - std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - - if( it == mStoredToastList.end() ) - return; - - const LLToast* toast = it->getToast(); - if (toast) - { - mRejectToastSignal(toast->getNotificationID()); - } - - // Call find() once more, because the mStoredToastList could have been changed - // in mRejectToastSignal callback and the iterator could have become invalid. - it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - if (it != mStoredToastList.end()) - { - mStoredToastList.erase(it); - } -} - //-------------------------------------------------------------------------- void LLScreenChannel::killToastByNotificationID(LLUUID id) { // searching among toasts on a screen std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); + LLNotificationPtr notification = LLNotifications::instance().find(id); + if (!notification) return; if( it != mToastList.end()) { @@ -472,42 +457,67 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id) // the toast will be destroyed. if(toast && toast->isNotificationValid()) { - mRejectToastSignal(toast->getNotificationID()); + if (!notification->canLogToIM() || !notification->hasFormElements()) + { + // only cancel notification if it isn't being used in IM session + LLNotifications::instance().cancel(notification); + } } else { - - deleteToast(toast); - mToastList.erase(it); - redrawToasts(); + removeToastByNotificationID(id); } - return; } - - // searching among stored toasts - it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - - if( it != mStoredToastList.end() ) + else { - LLToast* toast = it->getToast(); - if (toast) + // searching among stored toasts + it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + + if( it != mStoredToastList.end() ) + { + LLToast* toast = it->getToast(); + if (toast) + { + if (!notification->canLogToIM() || !notification->hasFormElements()) + { + // only cancel notification if it isn't being used in IM session + LLNotifications::instance().cancel(notification); + } + deleteToast(toast); + } + } + + // Call find() once more, because the mStoredToastList could have been changed + // via notification cancellation and the iterator could have become invalid. + it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + if (it != mStoredToastList.end()) { - // send signal to a listener to let him perform some action on toast rejecting - mRejectToastSignal(toast->getNotificationID()); - deleteToast(toast); + mStoredToastList.erase(it); + } } } - // Call find() once more, because the mStoredToastList could have been changed - // in mRejectToastSignal callback and the iterator could have become invalid. - it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - if (it != mStoredToastList.end()) +void LLScreenChannel::removeToastByNotificationID(LLUUID id) +{ + std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); + if( it != mToastList.end()) { - mStoredToastList.erase(it); + deleteToast(it->getToast()); + mToastList.erase(it); + redrawToasts(); + } + else + { + it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + if (it != mStoredToastList.end()) + { + deleteToast(it->getToast()); + mStoredToastList.erase(it); + } } - } + void LLScreenChannel::killMatchedToasts(const Matcher& matcher) { std::list<const LLToast*> to_delete = findToasts(matcher); diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index eaff61a0f4..e5f4807ab7 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -84,6 +84,7 @@ public: // kill or modify a toast by its ID virtual void killToastByNotificationID(LLUUID id) {}; virtual void modifyToastNotificationByID(LLUUID id, LLSD data) {}; + virtual void removeToastByNotificationID(LLUUID id){}; // hide all toasts from screen, but not remove them from a channel virtual void hideToastsFromScreen() {}; @@ -175,6 +176,7 @@ public: void addToast(const LLToast::Params& p); // kill or modify a toast by its ID void killToastByNotificationID(LLUUID id); + void removeToastByNotificationID(LLUUID id); void killMatchedToasts(const Matcher& matcher); void modifyToastByNotificationID(LLUUID id, LLPanel* panel); // hide all toasts from screen, but not remove them from a channel @@ -195,8 +197,6 @@ public: void loadStoredToastsToChannel(); // finds a toast among stored by its Notification ID and throws it on a screen to a channel void loadStoredToastByNotificationIDToChannel(LLUUID id); - // removes a toast from stored finding it by its Notification ID - void removeStoredToastByNotificationID(LLUUID id); // removes from channel all toasts that belongs to the certain IM session void removeToastsBySessionID(LLUUID id); // remove all storable toasts from screen and store them @@ -229,13 +229,9 @@ public: // signal on storing of faded toasts event typedef boost::signals2::signal<void (LLPanel* info_panel, const LLUUID id)> store_toast_signal_t; boost::signals2::connection addOnStoreToastCallback(store_toast_signal_t::slot_type cb) { return mOnStoreToast.connect(cb); } - // signal on rejecting of a toast event - typedef boost::signals2::signal<void (LLUUID id)> reject_toast_signal_t; - boost::signals2::connection addOnRejectToastCallback(reject_toast_signal_t::slot_type cb) { return mRejectToastSignal.connect(cb); } private: store_toast_signal_t mOnStoreToast; - reject_toast_signal_t mRejectToastSignal; class ToastElem { diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index e1d99b1bcb..ea62f758f8 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -169,6 +169,7 @@ public: // get/set Toast's flags or states // get information whether the notification corresponding to the toast is valid or not bool isNotificationValid(); + // get toast's Notification ID const LLUUID getNotificationID() const { return mNotificationID;} // get toast's Session ID @@ -212,7 +213,7 @@ private: //LLRootHandle<LLToast> mHandle; - LLPanel* mWrapperPanel; + LLPanel* mWrapperPanel; // timer counts a lifetime of a toast std::auto_ptr<LLToastLifeTimer> mTimer; @@ -220,8 +221,8 @@ private: F32 mToastLifetime; // in seconds F32 mToastFadingTime; // in seconds - LLPanel* mPanel; - LLButton* mHideBtn; + LLPanel* mPanel; + LLButton* mHideBtn; LLColor4 mBgColor; bool mCanFade; diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index a803387576..279dd69bc7 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -41,11 +41,11 @@ public: struct Params { LLNotificationPtr notification; - LLUUID avatar_id; - LLUUID session_id; - std::string from; - std::string time; - std::string message; + LLUUID avatar_id, + session_id; + std::string from, + time, + message; Params() {} }; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index dc5cc88dc4..77a5a5d17d 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -45,6 +45,9 @@ const S32 BOTTOM_PAD = VPAD * 3; const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding S32 BUTTON_WIDTH = 90; +// *TODO: magic numbers(???) - copied from llnotify.cpp(250) +const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; + //static const LLFontGL* LLToastNotifyPanel::sFont = NULL; @@ -52,171 +55,24 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL; LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal; -LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) : -LLToastPanel(notification), -mTextBox(NULL), -mInfoPanel(NULL), -mControlPanel(NULL), -mNumOptions(0), -mNumButtons(0), -mAddedDefaultBtn(false), -mCloseNotificationOnDestroy(true) +LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) +: LLToastPanel(notification), + LLInstanceTracker(notification->getID()) { - buildFromFile( "panel_notification.xml"); - if(rect != LLRect::null) - { - this->setShape(rect); - } - mInfoPanel = getChild<LLPanel>("info_panel"); - mControlPanel = getChild<LLPanel>("control_panel"); - BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); - // customize panel's attributes - // is it intended for displaying a tip? - mIsTip = notification->getType() == "notifytip"; - // is it a script dialog? - mIsScriptDialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); - // is it a caution? - // - // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the - // notify xml template specifies that it is a caution - // tip-style notification handle 'caution' differently -they display the tip in a different color - mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; + init(rect, show_images); - // setup parameters - // get a notification message - mMessage = notification->getMessage(); - // init font variables - if (!sFont) - { - sFont = LLFontGL::getFontSansSerif(); - sFontSmall = LLFontGL::getFontSansSerifSmall(); - } - // initialize - setFocusRoot(!mIsTip); - // get a form for the notification - LLNotificationFormPtr form(notification->getForm()); - // get number of elements - mNumOptions = form->getNumElements(); - // customize panel's outfit - // preliminary adjust panel's layout - //move to the end - //mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); - - // adjust text options according to the notification type - // add a caution textbox at the top of a caution notification - if (mIsCaution && !mIsTip) - { - mTextBox = getChild<LLTextBox>("caution_text_box"); - } - else - { - mTextBox = getChild<LLTextEditor>("text_editor_box"); - } - - // *TODO: magic numbers(???) - copied from llnotify.cpp(250) - const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; - - mTextBox->setMaxTextLength(MAX_LENGTH); - mTextBox->setVisible(TRUE); - mTextBox->setPlainText(!show_images); - mTextBox->setValue(notification->getMessage()); - - // add buttons for a script notification - if (mIsTip) - { - adjustPanelForTipNotice(); - } - else - { - std::vector<index_button_pair_t> buttons; - buttons.reserve(mNumOptions); - S32 buttons_width = 0; - // create all buttons and accumulate they total width to reshape mControlPanel - for (S32 i = 0; i < mNumOptions; i++) - { - LLSD form_element = form->getElement(i); - if (form_element["type"].asString() != "button") - { - // not a button. - continue; - } - if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) - { - // a textbox pretending to be a button. - continue; - } - LLButton* new_button = createButton(form_element, TRUE); - buttons_width += new_button->getRect().getWidth(); - S32 index = form_element["index"].asInteger(); - buttons.push_back(index_button_pair_t(index,new_button)); - } - if (buttons.empty()) - { - addDefaultButton(); - } - else - { - const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel - S32 button_panel_height = mControlPanel->getRect().getHeight(); - //try get an average h_pad to spread out buttons - S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); - if(h_pad < 2*HPAD) - { - /* - * Probably it is a scriptdialog toast - * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. - * In last case set default h_pad to avoid heaping of buttons - */ - S32 button_per_row = button_panel_width / BUTTON_WIDTH; - h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row - if(h_pad < 2*HPAD) // still not enough space between buttons ? - { - h_pad = 2*HPAD; - } - } - if (mIsScriptDialog) - { - // we are using default width for script buttons so we can determinate button_rows - //to get a number of rows we divide the required width of the buttons to button_panel_width - S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); - //S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; - //reserve one row for the ignore_btn - button_rows++; - //calculate required panel height for scripdialog notification. - button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; - } - else - { - // in common case buttons can have different widths so we need to calculate button_rows according to buttons_width - //S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); - S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); - //calculate required panel height - button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + BOTTOM_PAD; - } - - // we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed - adjustPanelForScriptNotice(button_panel_width, button_panel_height); - updateButtonsLayout(buttons, h_pad); - // save buttons for later use in disableButtons() - mButtons.assign(buttons.begin(), buttons.end()); - } - } - // adjust panel's height to the text size - mInfoPanel->setFollowsAll(); - snapToMessageHeight(mTextBox, MAX_LENGTH); - - if(notification->isReusable()) - { - mButtonClickConnection = sButtonClickSignal.connect( - boost::bind(&LLToastNotifyPanel::onToastPanelButtonClicked, this, _1, _2)); - - if(notification->isRespondedTo()) - { - // User selected an option in toast, now disable required buttons in IM window - disableRespondedOptions(notification); - } - } + //if(notification->isRespondedTo()) + //{ + // // User selected an option in toast, now disable required buttons in IM window + // disableRespondedOptions(notification); + //} + // + //if(notification->isReusable()) + //{ + // mButtonClickConnection = sButtonClickSignal.connect( + // boost::bind(&LLToastNotifyPanel::disableRespondedOptions, this, notification)); + //} } void LLToastNotifyPanel::addDefaultButton() { @@ -235,7 +91,6 @@ void LLToastNotifyPanel::addDefaultButton() } LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_option) { - InstanceAndS32* userdata = new InstanceAndS32; userdata->mSelf = this; userdata->mButtonName = is_option ? form_element["name"].asString() : ""; @@ -245,14 +100,15 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt LLButton::Params p; bool is_ignore_btn = form_element["index"].asInteger() == -1; const LLFontGL* font = is_ignore_btn ? sFontSmall: sFont; // for ignore button in script dialog - p.name(form_element["name"].asString()); - p.label(form_element["text"].asString()); - p.font(font); + p.name = form_element["name"].asString(); + p.label = form_element["text"].asString(); + p.font = font; p.rect.height = BTN_HEIGHT; p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata)); p.rect.width = BUTTON_WIDTH; p.auto_resize = false; p.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); + p.enabled = !form_element.has("enabled") || form_element["enabled"].asBoolean(); if (mIsCaution) { p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); @@ -287,14 +143,9 @@ LLToastNotifyPanel::~LLToastNotifyPanel() mButtonClickConnection.disconnect(); std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); - if (mCloseNotificationOnDestroy && LLNotificationsUtil::find(mNotification->getID()) != NULL) + if (mIsTip) { - // let reusable notification be deleted - mNotification->setReusable(false); - if (!mNotification->isPersistent()) - { - LLNotifications::getInstance()->cancel(mNotification); - } + LLNotifications::getInstance()->cancel(mNotification); } } @@ -393,103 +244,103 @@ void LLToastNotifyPanel::adjustPanelForTipNotice() } } -typedef std::set<std::string> button_name_set_t; -typedef std::map<std::string, button_name_set_t> disable_button_map_t; - -disable_button_map_t initUserGiveItemDisableButtonMap() -{ - // see EXT-5905 for disable rules - - disable_button_map_t disable_map; - button_name_set_t buttons; - - buttons.insert("Show"); - disable_map.insert(std::make_pair("Show", buttons)); - - buttons.insert("Discard"); - disable_map.insert(std::make_pair("Discard", buttons)); - - buttons.insert("Mute"); - disable_map.insert(std::make_pair("Mute", buttons)); - - return disable_map; -} - -disable_button_map_t initTeleportOfferedDisableButtonMap() -{ - disable_button_map_t disable_map; - button_name_set_t buttons; - - buttons.insert("Teleport"); - buttons.insert("Cancel"); - - disable_map.insert(std::make_pair("Teleport", buttons)); - disable_map.insert(std::make_pair("Cancel", buttons)); - - return disable_map; -} - -disable_button_map_t initFriendshipOfferedDisableButtonMap() -{ - disable_button_map_t disable_map; - button_name_set_t buttons; - - buttons.insert("Accept"); - buttons.insert("Decline"); - - disable_map.insert(std::make_pair("Accept", buttons)); - disable_map.insert(std::make_pair("Decline", buttons)); - - return disable_map; -} - -button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) -{ - static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); - static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); - static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); - - disable_button_map_t::const_iterator it; - disable_button_map_t::const_iterator it_end; - disable_button_map_t search_map; - - if("UserGiveItem" == notification_name) - { - search_map = user_give_item_disable_map; - } - else if("TeleportOffered" == notification_name) - { - search_map = teleport_offered_disable_map; - } - else if("OfferFriendship" == notification_name) - { - search_map = friendship_offered_disable_map; - } - - it = search_map.find(button_name); - it_end = search_map.end(); - - if(it_end != it) - { - return it->second; - } - return button_name_set_t(); -} - -void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) -{ - button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); - - std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); - for ( ; it != mButtons.end(); it++) - { - LLButton* btn = it->second; - if(buttons.find(btn->getName()) != buttons.end()) - { - btn->setEnabled(FALSE); - } - } -} +//typedef std::set<std::string> button_name_set_t; +//typedef std::map<std::string, button_name_set_t> disable_button_map_t; +// +//disable_button_map_t initUserGiveItemDisableButtonMap() +//{ +// // see EXT-5905 for disable rules +// +// disable_button_map_t disable_map; +// button_name_set_t buttons; +// +// buttons.insert("Show"); +// disable_map.insert(std::make_pair("Show", buttons)); +// +// buttons.insert("Discard"); +// disable_map.insert(std::make_pair("Discard", buttons)); +// +// buttons.insert("Mute"); +// disable_map.insert(std::make_pair("Mute", buttons)); +// +// return disable_map; +//} +// +//disable_button_map_t initTeleportOfferedDisableButtonMap() +//{ +// disable_button_map_t disable_map; +// button_name_set_t buttons; +// +// buttons.insert("Teleport"); +// buttons.insert("Cancel"); +// +// disable_map.insert(std::make_pair("Teleport", buttons)); +// disable_map.insert(std::make_pair("Cancel", buttons)); +// +// return disable_map; +//} +// +//disable_button_map_t initFriendshipOfferedDisableButtonMap() +//{ +// disable_button_map_t disable_map; +// button_name_set_t buttons; +// +// buttons.insert("Accept"); +// buttons.insert("Decline"); +// +// disable_map.insert(std::make_pair("Accept", buttons)); +// disable_map.insert(std::make_pair("Decline", buttons)); +// +// return disable_map; +//} +// +//button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) +//{ +// static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); +// static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); +// static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); +// +// disable_button_map_t::const_iterator it; +// disable_button_map_t::const_iterator it_end; +// disable_button_map_t search_map; +// +// if("UserGiveItem" == notification_name) +// { +// search_map = user_give_item_disable_map; +// } +// else if("TeleportOffered" == notification_name) +// { +// search_map = teleport_offered_disable_map; +// } +// else if("OfferFriendship" == notification_name) +// { +// search_map = friendship_offered_disable_map; +// } +// +// it = search_map.find(button_name); +// it_end = search_map.end(); +// +// if(it_end != it) +// { +// return it->second; +// } +// return button_name_set_t(); +//} + +//void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) +//{ + //button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); + + //std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); + //for ( ; it != mButtons.end(); it++) + //{ + // LLButton* btn = it->second; + // if(buttons.find(btn->getName()) != buttons.end()) + // { + // btn->setEnabled(FALSE); + // } + //} +//} // static void LLToastNotifyPanel::onClickButton(void* data) @@ -515,88 +366,263 @@ void LLToastNotifyPanel::onClickButton(void* data) self->mNotification->setResponder(new_info); } + // disable all buttons + self->mControlPanel->setEnabled(FALSE); + + // this might repost notification with new form data/enabled buttons self->mNotification->respond(response); +} - if(is_reusable) +void LLToastNotifyPanel::init( LLRect rect, bool show_images ) +{ + deleteAllChildren(); + + mTextBox = NULL; + mInfoPanel = NULL; + mControlPanel = NULL; + mNumOptions = 0; + mNumButtons = 0; + mAddedDefaultBtn = false; + + buildFromFile( "panel_notification.xml"); + if(rect != LLRect::null) { - sButtonClickSignal(self->mNotification->getID(), button_name); + this->setShape(rect); + } + mInfoPanel = getChild<LLPanel>("info_panel"); + mInfoPanel->setFollowsAll(); + + mControlPanel = getChild<LLPanel>("control_panel"); + BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); + // customize panel's attributes + // is it intended for displaying a tip? + mIsTip = mNotification->getType() == "notifytip"; + // is it a script dialog? + mIsScriptDialog = (mNotification->getName() == "ScriptDialog" || mNotification->getName() == "ScriptDialogGroup"); + // is it a caution? + // + // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the + // notify xml template specifies that it is a caution + // tip-style notification handle 'caution' differently -they display the tip in a different color + mIsCaution = mNotification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; + + // setup parameters + // get a notification message + mMessage = mNotification->getMessage(); + // init font variables + if (!sFont) + { + sFont = LLFontGL::getFontSansSerif(); + sFontSmall = LLFontGL::getFontSansSerifSmall(); + } + // initialize + setFocusRoot(!mIsTip); + // get a form for the notification + LLNotificationFormPtr form(mNotification->getForm()); + // get number of elements + mNumOptions = form->getNumElements(); + + // customize panel's outfit + // preliminary adjust panel's layout + //move to the end + //mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); + + // adjust text options according to the notification type + // add a caution textbox at the top of a caution notification + if (mIsCaution && !mIsTip) + { + mTextBox = getChild<LLTextBox>("caution_text_box"); } else { - // disable all buttons - self->mControlPanel->setEnabled(FALSE); + mTextBox = getChild<LLTextEditor>("text_editor_box"); } -} -void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) -{ - if(mNotification->getID() == notification_id) + mTextBox->setMaxTextLength(MAX_LENGTH); + mTextBox->setVisible(TRUE); + mTextBox->setPlainText(!show_images); + mTextBox->setValue(mNotification->getMessage()); + + // add buttons for a script notification + if (mIsTip) { - disableButtons(mNotification->getName(), btn_name); + adjustPanelForTipNotice(); } -} - -void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) -{ - LLSD response = notification->getResponse(); - for (LLSD::map_const_iterator response_it = response.beginMap(); - response_it != response.endMap(); ++response_it) + else { - if (response_it->second.isBoolean() && response_it->second.asBoolean()) + std::vector<index_button_pair_t> buttons; + buttons.reserve(mNumOptions); + S32 buttons_width = 0; + // create all buttons and accumulate they total width to reshape mControlPanel + for (S32 i = 0; i < mNumOptions; i++) { - // that after multiple responses there can be many pressed buttons - // need to process them all - disableButtons(notification->getName(), response_it->first); + LLSD form_element = form->getElement(i); + if (form_element["type"].asString() != "button") + { + // not a button. + continue; + } + if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) + { + // a textbox pretending to be a button. + continue; + } + LLButton* new_button = createButton(form_element, TRUE); + buttons_width += new_button->getRect().getWidth(); + S32 index = form_element["index"].asInteger(); + buttons.push_back(index_button_pair_t(index,new_button)); + } + if (buttons.empty()) + { + addDefaultButton(); + } + else + { + const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel + S32 button_panel_height = mControlPanel->getRect().getHeight(); + //try get an average h_pad to spread out buttons + S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); + if(h_pad < 2*HPAD) + { + /* + * Probably it is a scriptdialog toast + * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. + * In last case set default h_pad to avoid heaping of buttons + */ + S32 button_per_row = button_panel_width / BUTTON_WIDTH; + h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row + if(h_pad < 2*HPAD) // still not enough space between buttons ? + { + h_pad = 2*HPAD; + } + } + if (mIsScriptDialog) + { + // we are using default width for script buttons so we can determinate button_rows + //to get a number of rows we divide the required width of the buttons to button_panel_width + S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); + //S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; + //reserve one row for the ignore_btn + button_rows++; + //calculate required panel height for scripdialog notification. + button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; + } + else + { + // in common case buttons can have different widths so we need to calculate button_rows according to buttons_width + //S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); + S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); + //calculate required panel height + button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + BOTTOM_PAD; + } + + // we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed + adjustPanelForScriptNotice(button_panel_width, button_panel_height); + updateButtonsLayout(buttons, h_pad); + // save buttons for later use in disableButtons() + //mButtons.assign(buttons.begin(), buttons.end()); } } + // adjust panel's height to the text size + snapToMessageHeight(mTextBox, MAX_LENGTH); } + +//void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) +//{ +// if(mNotification->getID() == notification_id) +// { +// disableButtons(mNotification->getName(), btn_name); +// } +//} + +//void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) +//{ +// LLSD response = notification->getResponse(); +// for (LLSD::map_const_iterator response_it = response.beginMap(); +// response_it != response.endMap(); ++response_it) +// { +// if (response_it->second.isBoolean() && response_it->second.asBoolean()) +// { +// // that after multiple responses there can be many pressed buttons +// // need to process them all +// disableButtons(notification->getName(), response_it->first); +// } +// } +//} + + ////////////////////////////////////////////////////////////////////////// LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect /* = LLRect::null */, - bool show_images /* = true */) - : mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images) + bool show_images /* = true */, LLTextBase* parent_text) +: mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images), + mParentText(parent_text) { - mTextBox->setFollowsAll(); + compactButtons(); } LLIMToastNotifyPanel::~LLIMToastNotifyPanel() { - // We shouldn't delete notification when IM floater exists - // since that notification will be reused by IM floater. - // This may happened when IM floater reloads messages, exactly when user - // changes layout of IM chat log(disable/enable plaintext mode). - // See EXT-6500 - LLIMFloater* im_floater = LLIMFloater::findInstance(mSessionID); - if (im_floater != NULL && !im_floater->isDead()) - { - mCloseNotificationOnDestroy = false; - } } void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) { - S32 text_height = mTextBox->getTextBoundingRect().getHeight(); - S32 widget_height = mTextBox->getRect().getHeight(); - S32 delta = text_height - widget_height; - LLRect rc = getRect(); + LLToastPanel::reshape(width, height, called_from_parent); - rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height + delta); - height = rc.getHeight(); - width = rc.getWidth(); + snapToMessageHeight(mTextBox, MAX_LENGTH); +} - bool is_width_changed = width != getRect().getWidth(); +void LLIMToastNotifyPanel::compactButtons() +{ + mTextBox->setFollowsAll(); - LLToastPanel::reshape(width, height, called_from_parent); + //we can't set follows in xml since it broke toasts behavior + setFollows(FOLLOWS_LEFT|FOLLOWS_RIGHT|FOLLOWS_TOP); - // Notification height required to display the text message depends on - // the width of the text box thus if panel width is changed the text box - // width is also changed then reshape() is called to adjust proper height. - if (is_width_changed) + const child_list_t* children = getControlPanel()->getChildList(); + S32 offset = 0; + // Children were added by addChild() which uses push_front to insert them into list, + // so to get buttons in correct order reverse iterator is used (EXT-5906) + for (child_list_t::const_reverse_iterator it = children->rbegin(); it != children->rend(); it++) { - reshape(width, height, called_from_parent); + LLButton * button = dynamic_cast<LLButton*> (*it); + if (button != NULL) + { + button->setOrigin( offset,button->getRect().mBottom); + button->setLeftHPad(2 * HPAD); + button->setRightHPad(2 * HPAD); + // set zero width before perform autoResize() + button->setRect(LLRect(button->getRect().mLeft, + button->getRect().mTop, + button->getRect().mLeft, + button->getRect().mBottom)); + button->setAutoResize(true); + button->autoResize(); + offset += HPAD + button->getRect().getWidth(); + button->setFollowsNone(); + } } + + if (mParentText) + { + mParentText->needsReflow(); + } +} + +void LLIMToastNotifyPanel::updateNotification() +{ + init(LLRect(), true); +} + +void LLIMToastNotifyPanel::init( LLRect rect, bool show_images ) +{ + LLToastNotifyPanel::init(LLRect(), show_images); + + compactButtons(); } + // EOF + diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index db517ec858..f93c7745af 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -47,7 +47,7 @@ class LLNotificationForm; * @deprecated this class will be removed after all toast panel types are * implemented in separate classes. */ -class LLToastNotifyPanel: public LLToastPanel +class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID> { public: /** @@ -61,10 +61,14 @@ public: * implement right class for desired toast panel. @see LLGenericTipPanel as example. */ LLToastNotifyPanel(const LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); + + virtual void init( LLRect rect, bool show_images ); + virtual ~LLToastNotifyPanel(); LLPanel * getControlPanel() { return mControlPanel; } - void setCloseNotificationOnDestroy(bool close) { mCloseNotificationOnDestroy = close; } + virtual void updateNotification() {} + protected: LLButton* createButton(const LLSD& form_element, BOOL is_option); @@ -76,8 +80,6 @@ protected: }; std::vector<InstanceAndS32*> mBtnCallbackData; - bool mCloseNotificationOnDestroy; - typedef std::pair<int,LLButton*> index_button_pair_t; void adjustPanelForScriptNotice(S32 max_width, S32 max_height); void adjustPanelForTipNotice(); @@ -93,9 +95,9 @@ protected: /** * Disable specific button(s) based on notification name and clicked button */ - void disableButtons(const std::string& notification_name, const std::string& selected_button); + //void disableButtons(const std::string& notification_name, const std::string& selected_button); - std::vector<index_button_pair_t> mButtons; + //std::vector<index_button_pair_t> mButtons; // panel elements LLTextBase* mTextBox; @@ -118,7 +120,7 @@ protected: /** * Process response data. Will disable selected options */ - void disableRespondedOptions(const LLNotificationPtr& notification); + //void disableRespondedOptions(const LLNotificationPtr& notification); bool mIsTip; bool mAddedDefaultBtn; @@ -137,13 +139,23 @@ class LLIMToastNotifyPanel : public LLToastNotifyPanel { public: - LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect = LLRect::null, bool show_images = true); + LLIMToastNotifyPanel(LLNotificationPtr& pNotification, + const LLUUID& session_id, + const LLRect& rect = LLRect::null, + bool show_images = true, + LLTextBase* parent_text = NULL); + + void compactButtons(); + + virtual void updateNotification(); + virtual void init( LLRect rect, bool show_images ); ~LLIMToastNotifyPanel(); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); protected: + LLTextBase* mParentText; LLUUID mSessionID; }; diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index d2a4ce8745..e20d516392 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -78,11 +78,14 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount) S32 requiredTextHeight = message->getTextBoundingRect().getHeight(); S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); - //Calculate last delta height deducting previous heightDelta - heightDelta = newTextHeight - oldTextHeight - heightDelta; + heightDelta = newTextHeight - oldTextHeight; + S32 new_panel_height = llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT); //reshape the panel with new height - reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT)); + if (new_panel_height != getRect().getHeight()) + { + reshape( getRect().getWidth(), new_panel_height); + } } } @@ -96,7 +99,7 @@ LLToastPanel* LLToastPanel::buidPanelFromNotification( if ("notifytip" == notification->getType()) { // if it is online/offline notification - if ("FriendOffline" == notification->getName() || "FriendOnline" == notification->getName()) + if ("FriendOnlineOffline" == notification->getName()) { res = new LLPanelOnlineStatus(notification); } diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h index 346e014d73..c22557206b 100644 --- a/indra/newview/lltoastpanel.h +++ b/indra/newview/lltoastpanel.h @@ -33,19 +33,13 @@ #include <string> -class LLToastPanelBase: public LLPanel -{ -public: - virtual void init(LLSD& data){}; -}; - /** * Base class for all panels that can be added to the toast. * All toast panels should contain necessary logic for representing certain notification * but shouldn't contain logic related to this panel lifetime control and positioning * on the parent view. */ -class LLToastPanel: public LLPanel { +class LLToastPanel : public LLPanel { public: LLToastPanel(const LLNotificationPtr&); virtual ~LLToastPanel() = 0; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c2bafd043d..cefd9ef91d 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -179,6 +179,7 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLMessageSystem* msg = gMessageSystem; const LLSD& payload = notification["payload"]; + LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); // add friend to recent people list LLRecentPeople::instance().add(payload["from_id"]); @@ -204,7 +205,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) msg->sendReliable(LLHost(payload["sender"].asString())); LLSD payload = notification["payload"]; - payload["SUPPRESS_TOAST"] = true; LLNotificationsUtil::add("FriendshipAcceptedByMe", notification["substitutions"], payload); break; @@ -212,7 +212,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) case 1: // Decline { LLSD payload = notification["payload"]; - payload["SUPPRESS_TOAST"] = true; LLNotificationsUtil::add("FriendshipDeclinedByMe", notification["substitutions"], payload); } @@ -241,6 +240,12 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) break; } + LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); + modified_form->setElementEnabled("Accept", false); + modified_form->setElementEnabled("Decline", false); + notification_ptr->updateForm(modified_form); + notification_ptr->repost(); + return false; } static LLNotificationFunctorRegistration friendship_offer_callback_reg("OfferFriendship", friendship_offer_callback); @@ -1471,16 +1476,16 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID); } + LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); + llassert(notification_ptr != NULL); + // For muting, we need to add the mute, then decline the offer. // This must be done here because: // * callback may be called immediately, // * adding the mute sends a message, // * we can't build two messages at once. - if (2 == button) // Block + if (IOR_MUTE == button) // Block { - LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); - - llassert(notification_ptr != NULL); if (notification_ptr != NULL) { gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback, _1, _2, _3)); @@ -1495,6 +1500,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& bool busy = gAgent.getBusy(); + LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); + switch(button) { case IOR_SHOW: @@ -1538,6 +1545,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL; break; } + + modified_form->setElementEnabled("Show", false); break; // end switch (mIM) @@ -1550,9 +1559,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& args["MESSAGE"] = log_message; LLNotificationsUtil::add("SystemMessageTip", args); } + break; case IOR_MUTE: + modified_form->setElementEnabled("Mute", false); // MUTE falls through to decline case IOR_DECLINE: { @@ -1588,6 +1599,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& { busy_message(gMessageSystem, mFromID); } + + modified_form->setElementEnabled("Show", false); + modified_form->setElementEnabled("Discard", false); + break; } default: @@ -1607,6 +1622,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& { delete this; } + + notification_ptr->updateForm(modified_form); + notification_ptr->repost(); + return false; } @@ -1984,6 +2003,15 @@ bool lure_callback(const LLSD& notification, const LLSD& response) lure_id); break; } + + LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); + + LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); + modified_form->setElementEnabled("Teleport", false); + modified_form->setElementEnabled("Cancel", false); + notification_ptr->updateForm(modified_form); + notification_ptr->repost(); + return false; } static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback); @@ -6394,7 +6422,6 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response) //*TODO please rewrite all keys to the same case, lower or upper payload["from_id"] = target_id; - payload["SUPPRESS_TOAST"] = true; LLNotificationsUtil::add("TeleportOfferSent", args, payload); // Add the recepient to the recent people list. diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index d35cebbd16..5b7222c180 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -5208,20 +5208,14 @@ Topic: [SUBJECT], Message: [MESSAGE] <notification icon="notifytip.tga" - name="FriendOnline" + name="FriendOnlineOffline" log_to_chat="false" type="notifytip"> <tag>friendship</tag> -<nolink>[NAME]</nolink> is Online - </notification> - - <notification - icon="notifytip.tga" - name="FriendOffline" - log_to_chat="false" - type="notifytip"> - <tag>friendship</tag> -<nolink>[NAME]</nolink> is Offline +<nolink>[NAME]</nolink> is [STATUS] + <unique combine="cancel_old"> + <context>NAME</context> + </unique> </notification> <notification @@ -6160,7 +6154,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th <notification icon="notify.tga" name="TeleportOfferSent" - log_to_im="true" + log_to_im="true" + show_toast="false" type="offer"> Teleport offer sent to [TO_NAME] </notification> @@ -6213,6 +6208,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th icon="notify.tga" name="FriendshipOffered" log_to_im="true" + show_toast="false" type="offer"> <tag>friendship</tag> You have offered friendship to [TO_NAME] @@ -6262,6 +6258,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th icon="notify.tga" name="FriendshipAcceptedByMe" log_to_im="true" + show_toast="false" type="offer"> <tag>friendship</tag> Friendship offer accepted. @@ -6271,6 +6268,7 @@ Friendship offer accepted. icon="notify.tga" name="FriendshipDeclinedByMe" log_to_im="true" + show_toast="false" type="offer"> <tag>friendship</tag> Friendship offer declined. diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 9752652679..e932310622 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3242,6 +3242,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="IM_moderator_label">(Moderator)</string> <string name="Saved_message">(Saved [LONG_TIMESTAMP])</string> <string name="IM_unblock_only_groups_friends">To see this message, you must uncheck 'Only friends and groups can call or IM me' in Preferences/Privacy.</string> + <string name="OnlineStatus">Online</string> + <string name="OfflineStatus">Offline</string> <!-- voice calls --> <string name="answered_call">Your call has been answered</string> -- cgit v1.2.3 From 4c7142f4836da9da77ac6ff2910aaa19506a655b Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 18 May 2012 15:28:08 -0700 Subject: CHUI-96 FIX Cannot dismiss modal dialogs related to merchant outbox notification duplicate suppression now doesn't generate multiple dialogs --- indra/newview/llnotificationalerthandler.cpp | 62 ++++++++++++++-------------- indra/newview/llnotificationhandler.h | 2 +- indra/newview/llscreenchannel.cpp | 17 ++++---- 3 files changed, 40 insertions(+), 41 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index d13e2b629d..2bc9cdd3c1 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -82,39 +82,39 @@ bool LLAlertHandler::processNotification(const LLNotificationPtr& notification) } if (notification->canLogToIM() && notification->hasFormElements()) - { - const std::string name = LLHandlerUtil::getSubstitutionName(notification); - - LLUUID from_id = notification->getPayload()["from_id"]; - - // firstly create session... - LLHandlerUtil::spawnIMSession(name, from_id); - - // ...then log message to have IM Well notified about new message - LLHandlerUtil::logToIMP2P(notification); - } - - LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.panel = dynamic_cast<LLToastPanel*>(alert_dialog); - p.enable_hide_btn = false; - p.can_fade = false; - p.is_modal = mIsModal; - p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); - - // Show alert in middle of progress view (during teleport) (EXT-1093) - LLProgressView* progress = gViewerWindow->getProgressView(); - LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); - mChannel.get()->updatePositionAndSize(rc); - - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); - if(channel) - channel->addToast(p); + { + const std::string name = LLHandlerUtil::getSubstitutionName(notification); + + LLUUID from_id = notification->getPayload()["from_id"]; + + // firstly create session... + LLHandlerUtil::spawnIMSession(name, from_id); + + // ...then log message to have IM Well notified about new message + LLHandlerUtil::logToIMP2P(notification); + } + + LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = dynamic_cast<LLToastPanel*>(alert_dialog); + p.enable_hide_btn = false; + p.can_fade = false; + p.is_modal = mIsModal; + p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); + + // Show alert in middle of progress view (during teleport) (EXT-1093) + LLProgressView* progress = gViewerWindow->getProgressView(); + LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); + mChannel.get()->updatePositionAndSize(rc); + + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); + if(channel) + channel->addToast(p); return false; - } +} void LLAlertHandler::onChange( LLNotificationPtr notification ) { diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 4d54bb78fc..0899625242 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -258,7 +258,7 @@ public: : LLNotificationChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")) {} /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onChange(LLNotificationPtr p) { } /*virtual*/ void onDelete(LLNotificationPtr p); bool processNotification(const LLNotificationPtr& p); }; diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 839ca0f9c5..157821d554 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -499,21 +499,20 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id) void LLScreenChannel::removeToastByNotificationID(LLUUID id) { - std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); - if( it != mToastList.end()) + std::vector<ToastElem>::iterator it = mToastList.begin(); + while( it != mToastList.end()) { + // find next toast with matching id + it = find(it, mToastList.end(), id); deleteToast(it->getToast()); mToastList.erase(it); redrawToasts(); } - else + it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + if (it != mStoredToastList.end()) { - it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - if (it != mStoredToastList.end()) - { - deleteToast(it->getToast()); - mStoredToastList.erase(it); - } + deleteToast(it->getToast()); + mStoredToastList.erase(it); } } -- cgit v1.2.3 From 32717690ee6a9f33ca909f0df0226e9533f69399 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Mon, 21 May 2012 17:45:28 +0300 Subject: gcc build fix. --- indra/newview/lltoastnotifypanel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 77a5a5d17d..3692fd5672 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -57,7 +57,7 @@ LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) : LLToastPanel(notification), - LLInstanceTracker(notification->getID()) + LLInstanceTracker<LLToastNotifyPanel, LLUUID>(notification->getID()) { init(rect, show_images); -- cgit v1.2.3 From 61bc25211be31ad28b8ae342c17b4ea1c32d955c Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Mon, 21 May 2012 17:16:11 -0700 Subject: CHUI-111 FIX Saved notifications are not sorted in same order after logout and relog. sort notifications in separate list llnotification now uses param block to serialize to llsd --- indra/llui/llnotifications.cpp | 138 ++++++++--------------------- indra/llui/llnotifications.h | 148 +++++++++++++++++--------------- indra/llui/llsdparam.cpp | 8 +- indra/llxuixml/llinitparam.h | 4 +- indra/newview/llnotificationstorage.cpp | 18 +++- indra/newview/lltoastnotifypanel.cpp | 24 ------ 6 files changed, 137 insertions(+), 203 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 663749b983..08b93ead40 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -105,39 +105,7 @@ LLNotificationForm::Params::Params() form_elements("") {} -// Local channel for persistent notifications -// Stores only persistent notifications. -// Class users can use connectChanged() to process persistent notifications -// (see LLNotificationStorage for example). -class LLPersistentNotificationChannel : public LLNotificationChannel -{ - LOG_CLASS(LLPersistentNotificationChannel); -public: - LLPersistentNotificationChannel() : - LLNotificationChannel("Persistent", "Visible", ¬ificationFilter, LLNotificationComparators::orderByUUID()) - { - } -private: - - // The channel gets all persistent notifications except those that have been canceled - static bool notificationFilter(LLNotificationPtr pNotification) - { - bool handle_notification = false; - - handle_notification = pNotification->isPersistent() - && !pNotification->isCancelled(); - - return handle_notification; - } - - void onDelete(LLNotificationPtr pNotification) - { - // we want to keep deleted notifications in our log, otherwise some - // notifications will be lost on exit. - mItems.insert(pNotification); - } -}; bool filterIgnoredNotifications(LLNotificationPtr notification) { @@ -502,18 +470,18 @@ LLNotificationVisibilityRule::LLNotificationVisibilityRule(const LLNotificationV } } -LLNotification::LLNotification(const LLNotification::Params& p) : +LLNotification::LLNotification(const LLSDParamAdapter<Params>& p) : mTimestamp(p.time_stamp), mSubstitutions(p.substitutions), mPayload(p.payload), - mExpiresAt(0), + mExpiresAt(p.expiry), mTemporaryResponder(false), mRespondedTo(false), mPriority(p.priority), mCancelled(false), mIgnored(false), mResponderObj(NULL), - mIsReusable(false) + mId(p.id.isProvided() ? p.id : LLUUID::generateNewID()) { if (p.functor.name.isChosen()) { @@ -536,52 +504,32 @@ LLNotification::LLNotification(const LLNotification::Params& p) : mResponderObj = p.responder; } - mId.generate(); init(p.name, p.form_elements); } -LLNotification::LLNotification(const LLSD& sd) : - mTemporaryResponder(false), - mRespondedTo(false), - mCancelled(false), - mIgnored(false), - mResponderObj(NULL), - mIsReusable(false) -{ - mId.generate(); - mSubstitutions = sd["substitutions"]; - mPayload = sd["payload"]; - mTimestamp = sd["time"]; - mExpiresAt = sd["expiry"]; - mPriority = (ENotificationPriority)sd["priority"].asInteger(); - mResponseFunctorName = sd["responseFunctor"].asString(); - std::string templatename = sd["name"].asString(); - init(templatename, LLSD()); - // replace form with serialized version - mForm = LLNotificationFormPtr(new LLNotificationForm(sd["form"])); -} - - LLSD LLNotification::asLLSD() { - LLSD output; - output["id"] = mId; - output["name"] = mTemplatep->mName; - output["form"] = getForm()->asLLSD(); - output["substitutions"] = mSubstitutions; - output["payload"] = mPayload; - output["time"] = mTimestamp; - output["expiry"] = mExpiresAt; - output["priority"] = (S32)mPriority; - output["responseFunctor"] = mResponseFunctorName; - output["reusable"] = mIsReusable; + LLParamSDParser parser; - if(mResponder) + Params p; + p.id = mId; + p.name = mTemplatep->mName; + p.form_elements = getForm()->asLLSD(); + + p.substitutions = mSubstitutions; + p.payload = mPayload; + p.time_stamp = mTimestamp; + p.expiry = mExpiresAt; + p.priority = mPriority; + + if(!mResponseFunctorName.empty()) { - output["responder"] = mResponder->asLLSD(); + p.functor.name = mResponseFunctorName; } + LLSD output; + parser.writeSD(output, p); return output; } @@ -1056,8 +1004,8 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt { // not in our list, add it and say so mItems.insert(pNotification); - abortProcessing = mChanged(payload); onLoad(pNotification); + abortProcessing = mChanged(payload); } } else if (cmd == "change") @@ -1072,18 +1020,18 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt { // it already existed, so this is a change // since it changed in place, all we have to do is resend the signal - abortProcessing = mChanged(payload); onChange(pNotification); + abortProcessing = mChanged(payload); } else { // not in our list, add it and say so mItems.insert(pNotification); + onChange(pNotification); // our payload is const, so make a copy before changing it LLSD newpayload = payload; newpayload["sigtype"] = "add"; abortProcessing = mChanged(newpayload); - onChange(pNotification); } } else @@ -1092,11 +1040,11 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt { // it already existed, so this is a delete mItems.erase(pNotification); + onChange(pNotification); // our payload is const, so make a copy before changing it LLSD newpayload = payload; newpayload["sigtype"] = "delete"; abortProcessing = mChanged(newpayload); - onChange(pNotification); } // didn't pass, not on our list, do nothing } @@ -1110,8 +1058,8 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt { // not in our list, add it and say so mItems.insert(pNotification); - abortProcessing = mChanged(payload); onAdd(pNotification); + abortProcessing = mChanged(payload); } } else if (cmd == "delete") @@ -1119,16 +1067,16 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt // if we have it in our list, pass on the delete, then delete it, else do nothing if (wasFound) { - abortProcessing = mChanged(payload); mItems.erase(pNotification); onDelete(pNotification); + abortProcessing = mChanged(payload); } } return abortProcessing; } LLNotificationChannel::LLNotificationChannel(const Params& p) -: LLNotificationChannelBase(p.filter(), p.comparator()), +: LLNotificationChannelBase(p.filter()), LLInstanceTracker<LLNotificationChannel, std::string>(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()), mName(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()) { @@ -1141,9 +1089,8 @@ LLNotificationChannel::LLNotificationChannel(const Params& p) LLNotificationChannel::LLNotificationChannel(const std::string& name, const std::string& parent, - LLNotificationFilter filter, - LLNotificationComparator comparator) -: LLNotificationChannelBase(filter, comparator), + LLNotificationFilter filter) +: LLNotificationChannelBase(filter), LLInstanceTracker<LLNotificationChannel, std::string>(name), mName(name) { @@ -1151,18 +1098,6 @@ LLNotificationChannel::LLNotificationChannel(const std::string& name, connectToChannel(parent); } - -void LLNotificationChannel::setComparator(LLNotificationComparator comparator) -{ - mComparator = comparator; - LLNotificationSet s2(mComparator); - s2.insert(mItems.begin(), mItems.end()); - mItems.swap(s2); - - // notify clients that we've been resorted - mChanged(LLSD().with("sigtype", "sort")); -} - bool LLNotificationChannel::isEmpty() const { return mItems.empty(); @@ -1178,6 +1113,11 @@ LLNotificationChannel::Iterator LLNotificationChannel::end() return mItems.end(); } +size_t LLNotificationChannel::size() +{ + return mItems.size(); +} + std::string LLNotificationChannel::summarize() { std::string s("Channel '"); @@ -1205,19 +1145,17 @@ void LLNotificationChannel::connectToChannel( const std::string& channel_name ) } } - - // --- // END OF LLNotificationChannel implementation // ========================================================= -// ========================================================= +// ============================================== =========== // LLNotifications implementation // --- -LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFilters::includeEverything, - LLNotificationComparators::orderByUUID()), - mIgnoreAllNotifications(false) +LLNotifications::LLNotifications() +: LLNotificationChannelBase(LLNotificationFilters::includeEverything), + mIgnoreAllNotifications(false) { LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2)); @@ -1705,7 +1643,7 @@ void LLNotifications::update(const LLNotificationPtr pNotif) LLNotificationPtr LLNotifications::find(LLUUID uuid) { - LLNotificationPtr target = LLNotificationPtr(new LLNotification(uuid)); + LLNotificationPtr target = LLNotificationPtr(new LLNotification(LLNotification::Params().id(uuid))); LLNotificationSet::iterator it=mItems.find(target); if (it == mItems.end()) { diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index e9449eae69..783e9ffc88 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -88,10 +88,6 @@ #include <boost/enable_shared_from_this.hpp> #include <boost/type_traits.hpp> -// we want to minimize external dependencies, but this one is important -#include "llsd.h" - -// and we need this to manage the notification callbacks #include "llevents.h" #include "llfunctorregistry.h" #include "llinitparam.h" @@ -99,6 +95,7 @@ #include "llnotificationptr.h" #include "llpointer.h" #include "llrefcount.h" +#include "llsdparam.h" class LLAvatarName; typedef enum e_notification_priority @@ -309,13 +306,13 @@ public: friend class LLNotification; Mandatory<std::string> name; - - // optional - Optional<LLSD> substitutions; - Optional<LLSD> payload; + Optional<LLUUID> id; + Optional<LLSD> substitutions, + form_elements, + payload; Optional<ENotificationPriority, NotificationPriorityValues> priority; - Optional<LLSD> form_elements; - Optional<LLDate> time_stamp; + Optional<LLDate> time_stamp, + expiry; Optional<LLNotificationContext*> context; Optional<void*> responder; @@ -326,7 +323,7 @@ public: Alternative<LLNotificationResponderPtr> responder; Functor() - : name("functor_name"), + : name("responseFunctor"), function("functor"), responder("responder") {} @@ -335,10 +332,13 @@ public: Params() : name("name"), + id("id"), priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), - time_stamp("time_stamp"), + time_stamp("time"), payload("payload"), - form_elements("form_elements") + form_elements("form"), + substitutions("substitutions"), + expiry("expiry") { time_stamp = LLDate::now(); responder = NULL; @@ -347,9 +347,11 @@ public: Params(const std::string& _name) : name("name"), priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), - time_stamp("time_stamp"), + time_stamp("time"), payload("payload"), - form_elements("form_elements") + form_elements("form"), + substitutions("substitutions"), + expiry("expiry") { functor.name = _name; name = _name; @@ -362,7 +364,7 @@ public: private: - LLUUID mId; + const LLUUID mId; LLSD mPayload; LLSD mSubstitutions; LLDate mTimestamp; @@ -374,7 +376,6 @@ private: ENotificationPriority mPriority; LLNotificationFormPtr mForm; void* mResponderObj; // TODO - refactor/remove this field - bool mIsReusable; LLNotificationResponderPtr mResponder; // a reference to the template @@ -399,18 +400,10 @@ private: void init(const std::string& template_name, const LLSD& form_elements); - LLNotification(const Params& p); - - // this is just for making it easy to look things up in a set organized by UUID -- DON'T USE IT - // for anything real! - LLNotification(LLUUID uuid) : mId(uuid), mCancelled(false), mRespondedTo(false), mIgnored(false), mPriority(NOTIFICATION_PRIORITY_UNSPECIFIED), mTemporaryResponder(false) {} - void cancel(); public: - - // constructor from a saved notification - LLNotification(const LLSD& sd); + LLNotification(const LLSDParamAdapter<Params>& p); void setResponseFunctor(std::string const &responseFunctorName); @@ -555,8 +548,6 @@ public: return mId; } - bool isReusable() { return mIsReusable; } - // comparing two notifications normally means comparing them by UUID (so we can look them // up quickly this way) bool operator<(const LLNotification& rhs) const @@ -668,44 +659,18 @@ namespace LLNotificationFilters namespace LLNotificationComparators { - typedef enum e_direction { ORDER_DECREASING, ORDER_INCREASING } EDirection; - - // generic order functor that takes method or member variable reference - template<typename T> - struct orderBy + struct orderByUUID { - typedef boost::function<T (LLNotificationPtr)> field_t; - orderBy(field_t field, EDirection direction = ORDER_INCREASING) : mField(field), mDirection(direction) {} bool operator()(LLNotificationPtr lhs, LLNotificationPtr rhs) { - if (mDirection == ORDER_DECREASING) - { - return mField(lhs) > mField(rhs); - } - else - { - return mField(lhs) < mField(rhs); - } + return lhs->id() < rhs->id(); } - - field_t mField; - EDirection mDirection; - }; - - struct orderByUUID : public orderBy<const LLUUID&> - { - orderByUUID(EDirection direction = ORDER_INCREASING) : orderBy<const LLUUID&>(&LLNotification::id, direction) {} - }; - - struct orderByDate : public orderBy<const LLDate&> - { - orderByDate(EDirection direction = ORDER_INCREASING) : orderBy<const LLDate&>(&LLNotification::getDate, direction) {} }; }; typedef boost::function<bool (LLNotificationPtr)> LLNotificationFilter; typedef boost::function<bool (LLNotificationPtr, LLNotificationPtr)> LLNotificationComparator; -typedef std::set<LLNotificationPtr, LLNotificationComparator> LLNotificationSet; +typedef std::set<LLNotificationPtr, LLNotificationComparators::orderByUUID> LLNotificationSet; typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap; // ======================================================== @@ -731,8 +696,9 @@ class LLNotificationChannelBase : { LOG_CLASS(LLNotificationChannelBase); public: - LLNotificationChannelBase(LLNotificationFilter filter, LLNotificationComparator comp) : - mFilter(filter), mItems(comp) + LLNotificationChannelBase(LLNotificationFilter filter) + : mFilter(filter), + mItems() {} virtual ~LLNotificationChannelBase() {} // you can also connect to a Channel, so you can be notified of @@ -829,18 +795,11 @@ public: { Mandatory<std::string> name; Optional<LLNotificationFilter> filter; - Optional<LLNotificationComparator> comparator; Multiple<std::string> sources; - - Params() - : comparator("", LLNotificationComparators::orderByUUID()) - {} }; LLNotificationChannel(const Params& p = Params()); - - LLNotificationChannel(const std::string& name, const std::string& parent, - LLNotificationFilter filter, LLNotificationComparator comparator=LLNotificationComparators::orderByUUID()); + LLNotificationChannel(const std::string& name, const std::string& parent, LLNotificationFilter filter); virtual ~LLNotificationChannel() {} typedef LLNotificationSet::iterator Iterator; @@ -853,11 +812,8 @@ public: Iterator begin(); Iterator end(); + size_t size(); - // Channels have a comparator to control sort order; - // the default sorts by arrival date - void setComparator(LLNotificationComparator comparator); - std::string summarize(); private: @@ -1047,5 +1003,55 @@ protected: std::string mName; }; +// Stores only persistent notifications. +// Class users can use connectChanged() to process persistent notifications +// (see LLNotificationStorage for example). +class LLPersistentNotificationChannel : public LLNotificationChannel +{ + LOG_CLASS(LLPersistentNotificationChannel); +public: + LLPersistentNotificationChannel() + : LLNotificationChannel("Persistent", "Visible", ¬ificationFilter) + { + } + + typedef std::vector<LLNotificationPtr> history_list_t; + history_list_t::iterator beginHistory() { sortHistory(); return mHistory.begin(); } + history_list_t::iterator endHistory() { return mHistory.end(); } + +private: + + void sortHistory() + { + struct sortByTime + { + S32 operator ()(const LLNotificationPtr& a, const LLNotificationPtr& b) + { + return a->getDate() < b->getDate(); + } + }; + std::sort(mHistory.begin(), mHistory.end(), sortByTime()); + } + + + // The channel gets all persistent notifications except those that have been canceled + static bool notificationFilter(LLNotificationPtr pNotification) + { + bool handle_notification = false; + + handle_notification = pNotification->isPersistent() + && !pNotification->isCancelled(); + + return handle_notification; + } + + void onAdd(LLNotificationPtr p) + { + mHistory.push_back(p); + } + + std::vector<LLNotificationPtr> mHistory; +}; + #endif//LL_LLNOTIFICATIONS_H diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index bcfb38aa11..811e20e810 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -283,7 +283,10 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLI it != sd.endArray(); ++it) { - stack.back().second = true; + if (!stack.empty()) + { + stack.back().second = true; + } readSDValues(cb, *it, stack); } } @@ -336,7 +339,6 @@ namespace LLInitParam void ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const { // read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) - Parser::name_stack_t stack; - LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack); + LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack); } } diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 29f4a09cb7..435db1699c 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -1024,7 +1024,9 @@ namespace LLInitParam if (!parser.writeValue(typed_param.getValue(), name_stack)) { std::string calculated_key = typed_param.calcValueName(typed_param.getValue()); - if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key)) + if (calculated_key.size() + && (!diff_param + || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key))) { parser.writeValue(calculated_key, name_stack); } diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index fb1adc7ddf..a31b95811e 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -84,9 +84,11 @@ bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& pay return false; } +static LLFastTimer::DeclareTimer FTM_SAVE_NOTIFICATIONS("Save Notifications"); + void LLPersistentNotificationStorage::saveNotifications() { - // TODO - think about save optimization. + LLFastTimer _(FTM_SAVE_NOTIFICATIONS); llofstream notify_file(mFileName.c_str()); if (!notify_file.is_open()) @@ -98,10 +100,15 @@ void LLPersistentNotificationStorage::saveNotifications() LLSD output; LLSD& data = output["data"]; - LLNotificationChannelPtr history_channel = LLNotifications::instance().getChannel("Persistent"); - LLNotificationSet::iterator it = history_channel->begin(); + boost::intrusive_ptr<LLPersistentNotificationChannel> history_channel = boost::dynamic_pointer_cast<LLPersistentNotificationChannel>(LLNotifications::instance().getChannel("Persistent")); + if (!history_channel) + { + return; + } - for ( ; history_channel->end() != it; ++it) + for ( std::vector<LLNotificationPtr>::iterator it = history_channel->beginHistory(), end_it = history_channel->endHistory(); + it != end_it; + ++it) { LLNotificationPtr notification = *it; @@ -120,8 +127,11 @@ void LLPersistentNotificationStorage::saveNotifications() formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY); } +static LLFastTimer::DeclareTimer FTM_LOAD_NOTIFICATIONS("Load Notifications"); + void LLPersistentNotificationStorage::loadNotifications() { + LLFastTimer _(FTM_LOAD_NOTIFICATIONS); LLResponderRegistry::registerResponders(); LLNotifications::instance().getChannel("Persistent")-> diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 77a5a5d17d..884df27a18 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -60,19 +60,6 @@ LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, co LLInstanceTracker(notification->getID()) { init(rect, show_images); - - - //if(notification->isRespondedTo()) - //{ - // // User selected an option in toast, now disable required buttons in IM window - // disableRespondedOptions(notification); - //} - // - //if(notification->isReusable()) - //{ - // mButtonClickConnection = sButtonClickSignal.connect( - // boost::bind(&LLToastNotifyPanel::disableRespondedOptions, this, notification)); - //} } void LLToastNotifyPanel::addDefaultButton() { @@ -354,17 +341,6 @@ void LLToastNotifyPanel::onClickButton(void* data) { response[button_name] = true; } - - bool is_reusable = self->mNotification->isReusable(); - // When we call respond(), LLOfferInfo will delete itself in inventory_offer_callback(), - // lets copy it while it's still valid. - LLOfferInfo* old_info = static_cast<LLOfferInfo*>(self->mNotification->getResponder()); - LLOfferInfo* new_info = NULL; - if(is_reusable && old_info) - { - new_info = new LLOfferInfo(*old_info); - self->mNotification->setResponder(new_info); - } // disable all buttons self->mControlPanel->setEnabled(FALSE); -- cgit v1.2.3 From f89d94434c6e9d96ad71586d55c2b32d933a1e05 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Mon, 21 May 2012 18:26:18 -0700 Subject: made param blocks smaller by making param overhead 3 bytes instead of 4 Optional<bool> should now be 4 bytes smaller. --- indra/llui/tests/llurlentry_stub.cpp | 4 +++- indra/llui/tests/llurlmatch_test.cpp | 4 +++- indra/llxuixml/llinitparam.cpp | 6 ++++-- indra/llxuixml/llinitparam.h | 13 ++++++++++--- 4 files changed, 20 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index 9cb6a89eee..61e30d89d0 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -110,7 +110,9 @@ namespace LLInitParam { const U8* my_addr = reinterpret_cast<const U8*>(this); const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); - mEnclosingBlockOffset = (U16)(my_addr - block_addr); + U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr); + mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff; + mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16; } void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name){} diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index 36402f5b27..97fe5b2eea 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -88,7 +88,9 @@ namespace LLInitParam { const U8* my_addr = reinterpret_cast<const U8*>(this); const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); - mEnclosingBlockOffset = 0x7FFFffff & ((U32)(my_addr - block_addr)); + U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr); + mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff; + mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16; } bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name){ return true; } diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp index 3cf145cdde..3c0d0aaa7e 100644 --- a/indra/llxuixml/llinitparam.cpp +++ b/indra/llxuixml/llinitparam.cpp @@ -40,7 +40,9 @@ namespace LLInitParam { const U8* my_addr = reinterpret_cast<const U8*>(this); const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); - mEnclosingBlockOffset = 0x7FFFffff & (U32)(my_addr - block_addr); + U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr); + mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff; + mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16; } // @@ -459,7 +461,7 @@ namespace LLInitParam if (merge_func) { Param* paramp = getParamFromHandle((*it)->mParamHandle); - llassert(paramp->mEnclosingBlockOffset == (*it)->mParamHandle); + llassert(paramp->getEnclosingBlockOffset() == (*it)->mParamHandle); some_param_changed |= merge_func(*paramp, *other_paramp, overwrite); } } diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 435db1699c..ce59401e87 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -908,14 +908,21 @@ namespace LLInitParam // get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class return *const_cast<BaseBlock*> (reinterpret_cast<const BaseBlock*> - (my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset)); + (my_addr - (ptrdiff_t)getEnclosingBlockOffset())); + } + + U32 getEnclosingBlockOffset() const + { + return ((U32)mEnclosingBlockOffsetHigh << 16) | (U32)mEnclosingBlockOffsetLow; } private: friend class BaseBlock; - U32 mEnclosingBlockOffset:31; - U32 mIsProvided:1; + //24 bits for member offset field and 1 bit for provided flag + U16 mEnclosingBlockOffsetLow; + U8 mEnclosingBlockOffsetHigh:7; + U8 mIsProvided:1; }; -- cgit v1.2.3 From 4dffa3351401bd8ba8326958b38a3d500805b5d1 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Tue, 22 May 2012 20:34:34 +0300 Subject: Linux build fix GCC does not allow local functor classes to be used with template algorithms, because template arguments must refer to an entity with external linkage. --- indra/llui/llnotifications.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 783e9ffc88..12479f0788 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -1021,15 +1021,16 @@ public: private: - void sortHistory() + struct sortByTime { - struct sortByTime + S32 operator ()(const LLNotificationPtr& a, const LLNotificationPtr& b) { - S32 operator ()(const LLNotificationPtr& a, const LLNotificationPtr& b) - { - return a->getDate() < b->getDate(); - } - }; + return a->getDate() < b->getDate(); + } + }; + + void sortHistory() + { std::sort(mHistory.begin(), mHistory.end(), sortByTime()); } -- cgit v1.2.3 From 61d550ee85b371add15d174b4f6fbd93624c3490 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Thu, 24 May 2012 19:20:37 +0300 Subject: CHUI-78 FIXED group actions gear menu in People->Groups. Used the same menu for groups list context menu and gear menu in People->Groups. Changed the type of groups list context menu to toggleable. --- indra/llui/lltoggleablemenu.h | 2 ++ indra/newview/llgrouplist.cpp | 4 ++-- indra/newview/llgrouplist.h | 9 +++++++-- indra/newview/llpanelpeople.cpp | 13 +++++++++++++ indra/newview/skins/default/xui/en/panel_people.xml | 2 -- 5 files changed, 24 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltoggleablemenu.h b/indra/llui/lltoggleablemenu.h index 2094bd776f..dd9ac5b8c1 100644 --- a/indra/llui/lltoggleablemenu.h +++ b/indra/llui/lltoggleablemenu.h @@ -58,6 +58,8 @@ public: // its visibility off. bool toggleVisibility(); + LLHandle<LLToggleableMenu> getHandle() { return getDerivedHandle<LLToggleableMenu>(); } + protected: bool mClosedByButtonClick; LLRect mButtonRect; diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 129cddda45..2de891565c 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -86,7 +86,7 @@ LLGroupList::LLGroupList(const Params& p) registrar.add("People.Groups.Action", boost::bind(&LLGroupList::onContextMenuItemClick, this, _2)); enable_registrar.add("People.Groups.Enable", boost::bind(&LLGroupList::onContextMenuItemEnable, this, _2)); - LLMenuGL* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_groups.xml", + LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); if(context_menu) mContextMenuHandle = context_menu->getHandle(); @@ -112,7 +112,7 @@ BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); - LLMenuGL* context_menu = (LLMenuGL*)mContextMenuHandle.get(); + LLToggleableMenu* context_menu = mContextMenuHandle.get(); if (context_menu && size() > 0) { context_menu->buildDrawLabels(); diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 8abf14b3d0..6c8f4406ab 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -28,10 +28,13 @@ #define LL_LLGROUPLIST_H #include "llevent.h" +#include "llpointer.h" + #include "llflatlistview.h" #include "llpanel.h" -#include "llpointer.h" #include "llstyle.h" +#include "lltoggleablemenu.h" + #include "llgroupmgr.h" /** @@ -57,6 +60,8 @@ public: void toggleIcons(); bool getIconsVisible() const { return mShowIcons; } + LLToggleableMenu* getContextMenu() const { return mContextMenuHandle.get(); } + private: void setDirty(bool val = true) { mDirty = val; } void refresh(); @@ -66,7 +71,7 @@ private: bool onContextMenuItemClick(const LLSD& userdata); bool onContextMenuItemEnable(const LLSD& userdata); - LLHandle<LLView> mContextMenuHandle; + LLHandle<LLToggleableMenu> mContextMenuHandle; bool mShowIcons; bool mDirty; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 9b06d05b4b..260de40eef 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -630,6 +630,19 @@ BOOL LLPanelPeople::postBuild() mGroupList->setCommitCallback(boost::bind(&LLPanelPeople::updateButtons, this)); mGroupList->setReturnCallback(boost::bind(&LLPanelPeople::onChatButtonClicked, this)); + LLMenuButton* groups_gear_btn = getChild<LLMenuButton>("groups_gear_btn"); + + // Use the context menu of the Groups list for the Groups tab gear menu. + LLToggleableMenu* groups_gear_menu = mGroupList->getContextMenu(); + if (groups_gear_menu) + { + groups_gear_btn->setMenu(groups_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); + } + else + { + llwarns << "People->Groups list menu not found" << llendl; + } + LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>("tab_all"); accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _1, _2, mAllFriendList)); diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index abfb9c7a36..ceb03d03a9 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -418,8 +418,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Middle_Off" layout="topleft" left_pad="8" - menu_filename="menu_people_groups.xml" - menu_position="bottomleft" name="groups_gear_btn" top="3" width="31" /> -- cgit v1.2.3 From d713925f435add08f6e48fec2472671fae58f170 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 25 May 2012 11:39:37 -0700 Subject: CHUI-132 FIX Modal dialogs cannot be dismissed --- indra/llui/llnotifications.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 08b93ead40..487a2e5fe7 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1067,9 +1067,9 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt // if we have it in our list, pass on the delete, then delete it, else do nothing if (wasFound) { - mItems.erase(pNotification); onDelete(pNotification); abortProcessing = mChanged(payload); + mItems.erase(pNotification); } } return abortProcessing; -- cgit v1.2.3 From 8a2b6f7d2e56625c59c3e40d4a23942a91b824a1 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 25 May 2012 12:04:12 -0700 Subject: CHUI-131 FIX Crash when selecting Show on inventory offer notification if other notifications are being received --- indra/newview/llscreenchannel.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 157821d554..a4a0198305 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -499,15 +499,16 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id) void LLScreenChannel::removeToastByNotificationID(LLUUID id) { - std::vector<ToastElem>::iterator it = mToastList.begin(); + std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); while( it != mToastList.end()) { - // find next toast with matching id - it = find(it, mToastList.end(), id); deleteToast(it->getToast()); mToastList.erase(it); redrawToasts(); + // find next toast with matching id + it = find(mToastList.begin(), mToastList.end(), id); } + it = find(mStoredToastList.begin(), mStoredToastList.end(), id); if (it != mStoredToastList.end()) { -- cgit v1.2.3 From 2286dcb73bfddb9bd4102869005b14241053377d Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Tue, 29 May 2012 02:12:51 +0300 Subject: CHUI-105 WIP Fixed "is not a child of" warning when removing a tab from LLSideTrayPanelContainer. --- indra/llui/lltabcontainer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 5fc2cc350d..d0920685bf 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1209,7 +1209,11 @@ void LLTabContainer::removeTabPanel(LLPanel* child) update_images(mTabList[mTabList.size()-2], mLastTabParams, getTabPosition()); } - removeChild( tuple->mButton ); + if (!getTabsHidden()) + { + // We need to remove tab buttons only if the tabs are not hidden. + removeChild( tuple->mButton ); + } delete tuple->mButton; removeChild( tuple->mTabPanel ); -- cgit v1.2.3 From 47ec4faeb4dc67f9614e218a75d4957ccf6f794c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 30 May 2012 19:58:20 +0300 Subject: CHUI-119 WIP Prepare the nearby chat for hosting it by the IM-container --- indra/llui/llfloater.cpp | 2 + indra/llui/llfloater.h | 2 + indra/llui/llview.cpp | 2 +- indra/newview/CMakeLists.txt | 2 + indra/newview/llfloaterpreference.cpp | 8 +- indra/newview/llimconversation.cpp | 280 ++++++++++ indra/newview/llimconversation.h | 97 ++++ indra/newview/llimfloater.cpp | 600 +++++++-------------- indra/newview/llimfloater.h | 58 +- indra/newview/llimfloatercontainer.cpp | 1 + indra/newview/llimview.cpp | 2 +- indra/newview/llnearbychat.cpp | 26 +- indra/newview/llnearbychat.h | 10 +- indra/newview/llnearbychatbar.cpp | 110 ++-- indra/newview/llnearbychatbar.h | 16 +- .../skins/default/xui/en/floater_chat_bar.xml | 162 +++++- .../skins/default/xui/en/panel_nearby_chat.xml | 21 +- 17 files changed, 847 insertions(+), 552 deletions(-) create mode 100644 indra/newview/llimconversation.cpp create mode 100644 indra/newview/llimconversation.h (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index b087205a5c..5635905327 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1635,6 +1635,7 @@ void LLFloater::onClickTearOff(LLFloater* self) // give focus to new window to keep continuity for the user self->setFocus(TRUE); self->setTornOff(true); + } else //Attach to parent. { @@ -1649,6 +1650,7 @@ void LLFloater::onClickTearOff(LLFloater* self) self->setTornOff(false); } self->updateTitleButtons(); + self->setOpenPositioning(LLFloaterEnums::OPEN_POSITIONING_NONE); } // static diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index a7cc9ae961..cd02310bf8 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -329,6 +329,8 @@ public: virtual void setDocked(bool docked, bool pop_on_undock = true); virtual void setTornOff(bool torn_off) { mTornOff = torn_off; } + bool getTornOff() {return mTornOff;} + void setOpenPositioning(LLFloaterEnums::EOpenPositioning pos) {mOpenPositioning = pos;} // Return a closeable floater, if any, given the current focus. static LLFloater* getClosableFloaterFromFocus(); diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 421166dcd4..166cd99d03 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -349,7 +349,7 @@ void LLView::removeChild(LLView* child) } else { - llwarns << child->getName() << "is not a child of " << getName() << llendl; + llwarns << "\"" << child->getName() << "\" is not a child of " << getName() << llendl; } updateBoundingRect(); } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b780a27ce2..86d30c239f 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -277,6 +277,7 @@ set(viewer_SOURCE_FILES llhudrender.cpp llhudtext.cpp llhudview.cpp + llimconversation.cpp llimfloater.cpp llimfloatercontainer.cpp llimhandler.cpp @@ -834,6 +835,7 @@ set(viewer_HEADER_FILES llhudrender.h llhudtext.h llhudview.h + llimconversation.h llimfloater.h llimfloatercontainer.h llimview.h diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 3ed575086c..18ab9dc264 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -423,13 +423,9 @@ void LLFloaterPreference::saveAvatarProperties( void ) BOOL LLFloaterPreference::postBuild() { - gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate)); +// gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); - gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate)); - - gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate)); - - gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate)); + gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLViewerChat::signalChatFontChanged)); diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp new file mode 100644 index 0000000000..7220ab6a82 --- /dev/null +++ b/indra/newview/llimconversation.cpp @@ -0,0 +1,280 @@ +/** + * @file llimconversation.cpp + * @brief LLIMConversation class implements the common behavior of LNearbyChatBar + * @brief and LLIMFloater for hosting both in LLIMContainer + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llpanelimcontrolpanel.h" + +#include "lldraghandle.h" +#include "llfloaterreg.h" +#include "llimconversation.h" +#include "llimfloater.h" +#include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container +#include "lllayoutstack.h" +#include "llnearbychat.h" +#include "llnearbychatbar.h" + +LLIMConversation::LLIMConversation(const LLUUID& session_id) + : LLTransientDockableFloater(NULL, true, session_id) + , mControlPanel(NULL) + , mIsP2PChat(false) + , mExpandCollapseBtn(NULL) + , mTearOffBtn(NULL) + , mCloseBtn(NULL) + , mSessionID(session_id) +{ + mCommitCallbackRegistrar.add("IMSession.Menu.Action", + boost::bind(&LLIMConversation::onIMSessionMenuItemClicked, this, _2)); +// mCommitCallbackRegistrar.add("IMSession.ExpCollapseBtn.Click", +// boost::bind(&LLIMConversation::onSlide, this)); +// mCommitCallbackRegistrar.add("IMSession.CloseBtn.Click", +// boost::bind(&LLFloater::onClickClose, this)); + mCommitCallbackRegistrar.add("IMSession.TearOffBtn.Click", + boost::bind(&LLIMConversation::onTearOffClicked, this)); + mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", + boost::bind(&LLIMConversation::onIMCompactExpandedMenuItemCheck, this, _2)); + mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.CheckItem", + boost::bind(&LLIMConversation::onIMShowModesMenuItemCheck, this, _2)); + mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", + boost::bind(&LLIMConversation::onIMShowModesMenuItemEnable, this, _2)); +} + +BOOL LLIMConversation::postBuild() +{ + mCloseBtn = getChild<LLButton>("close_btn"); + mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); + + mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); + mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this)); + + if (mControlPanel) + { + mControlPanel->setSessionId(mSessionID); + mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel")); + + mExpandCollapseBtn->setImageOverlay( + getString(mControlPanel->getParent()->getVisible() ? "collapse_icon" : "expand_icon")); + } + else + { + mExpandCollapseBtn->setEnabled(false); + getChild<LLLayoutPanel>("im_control_panel_holder")->setVisible(false); + } + + mTearOffBtn = getChild<LLButton>("tear_off_btn"); + mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); + + if (!getTornOff()) + { + setOpenPositioning(LLFloaterEnums::OPEN_POSITIONING_NONE); + } + + if (isChatMultiTab()) + { + return LLFloater::postBuild(); + } + else + { + return LLDockableFloater::postBuild(); + } + +} + +void LLIMConversation::onIMSessionMenuItemClicked(const LLSD& userdata) +{ + std::string item = userdata.asString(); + + if (item == "compact_view" || item == "expanded_view") + { + gSavedSettings.setBOOL("PlainTextChatHistory", item == "compact_view"); + } + else + { + bool prev_value = gSavedSettings.getBOOL(item); + gSavedSettings.setBOOL(item, !prev_value); + } + + LLIMConversation::processChatHistoryStyleUpdate(); +} + + +bool LLIMConversation::onIMCompactExpandedMenuItemCheck(const LLSD& userdata) +{ + std::string item = userdata.asString(); + bool is_plain_text_mode = gSavedSettings.getBOOL("PlainTextChatHistory"); + + return is_plain_text_mode? item == "compact_view" : item == "expanded_view"; +} + + +bool LLIMConversation::onIMShowModesMenuItemCheck(const LLSD& userdata) +{ + return gSavedSettings.getBOOL(userdata.asString()); +} + +// enable/disable states for the "show time" and "show names" items of the show-modes menu +bool LLIMConversation::onIMShowModesMenuItemEnable(const LLSD& userdata) +{ + std::string item = userdata.asString(); + bool plain_text = gSavedSettings.getBOOL("PlainTextChatHistory"); + bool is_not_names = (item != "IMShowNamesForP2PConv"); + return (plain_text && (is_not_names || mIsP2PChat)); +} + +void LLIMConversation::updateHeaderAndToolbar() +{ + bool is_hosted = getHost() != NULL; + + if (is_hosted) + { + for (S32 i = 0; i < BUTTON_COUNT; i++) + { + if (mButtons[i]) + { + // Hide the standard header buttons in a docked IM floater. + mButtons[i]->setVisible(false); + } + } + } + + bool is_control_panel_visible = false; + if (mControlPanel) + { + // Control panel should be visible only in torn off floaters. + is_control_panel_visible = !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel"); + mControlPanel->getParent()->setVisible(is_control_panel_visible); + } + + // Display collapse image (<<) if the floater is hosted + // or if it is torn off but has an open control panel. + bool is_expanded = is_hosted || is_control_panel_visible; + mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); + + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); + if (session) + { + // The button (>>) should be disabled for torn off P2P conversations. + mExpandCollapseBtn->setEnabled(is_hosted || !session->isP2PSessionType()); + } + else + { + if (!mIsNearbyChat) + { + llwarns << "IM session not found." << llendl; + } + } + + if (mDragHandle) + { + // toggle floater's drag handle and title visibility + mDragHandle->setVisible(!is_hosted); + } + + mTearOffBtn->setImageOverlay(getString(is_hosted ? "tear_off_icon" : "return_icon")); + + mCloseBtn->setVisible(is_hosted); + + enableDisableCallBtn(); +} + +// static +void LLIMConversation::processChatHistoryStyleUpdate() +{ + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); + iter != inst_list.end(); ++iter) + { + LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); + if (floater) + { + floater->reloadMessages(); + } + } + + LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); + if (nearby_chat_bar) + { + nearby_chat_bar->reloadMessages(); + } +} + +void LLIMConversation::updateCallBtnState(bool callIsActive) +{ + getChild<LLButton>("voice_call_btn")->setImageOverlay( + callIsActive? getString("call_btn_stop") : getString("call_btn_start")); + enableDisableCallBtn(); + +} + +void LLIMConversation::onSlide(LLIMConversation* self) +{ + LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(self->getHost()); + if (host_floater) + { + // Hide the messages pane if a floater is hosted in the Conversations + host_floater->collapseMessagesPane(true); + } + else ///< floater is torn off + { + if (self->mControlPanel) + { + bool expand = !self->mControlPanel->getParent()->getVisible(); + + // Expand/collapse the IM control panel + self->mControlPanel->getParent()->setVisible(expand); + + gSavedSettings.setBOOL("IMShowControlPanel", expand); + + self->mExpandCollapseBtn->setImageOverlay(self->getString(expand ? "collapse_icon" : "expand_icon")); + } + } +} + +/*virtual*/ +void LLIMConversation::onOpen(const LLSD& key) +{ + LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); + if (host_floater) + { + // Show the messages pane when opening a floater hosted in the Conversations + host_floater->collapseMessagesPane(false); + } + + updateHeaderAndToolbar(); +} + +void LLIMConversation::onTearOffClicked() +{ + onClickTearOff(this); + updateHeaderAndToolbar(); +} + +// static +bool LLIMConversation::isChatMultiTab() +{ + // Restart is required in order to change chat window type. + static bool is_single_window = gSavedSettings.getS32("ChatWindow") == 1; + return is_single_window; +} diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h new file mode 100644 index 0000000000..501977e061 --- /dev/null +++ b/indra/newview/llimconversation.h @@ -0,0 +1,97 @@ +/** + * @file llimconversation.h + * @brief LLIMConversation class implements the common behavior of LNearbyChatBar + * @brief and LLIMFloater for hosting both in LLIMContainer + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_IMCONVERSATION_H +#define LL_IMCONVERSATION_H + +#include "lltransientdockablefloater.h" +#include "llviewercontrol.h" + +class LLPanelChatControlPanel; + +class LLIMConversation + : public LLTransientDockableFloater +{ + +public: + LOG_CLASS(LLIMConversation); + + LLIMConversation(const LLUUID& session_id); + + // reload all message with new settings of visual modes + static void processChatHistoryStyleUpdate(); + + /** + * Returns true if chat is displayed in multi tabbed floater + * false if chat is displayed in multiple windows + */ + static bool isChatMultiTab(); + + // LLFloater overrides + /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ BOOL postBuild(); + +protected: + + // callback for click on any items of the visual states menu + void onIMSessionMenuItemClicked(const LLSD& userdata); + + // callback for check/uncheck of the expanded/collapse mode's switcher + bool onIMCompactExpandedMenuItemCheck(const LLSD& userdata); + + // + bool onIMShowModesMenuItemCheck(const LLSD& userdata); + bool onIMShowModesMenuItemEnable(const LLSD& userdata); + static void onSlide(LLIMConversation *self); + void onTearOffClicked(); + + // refresh a visual state of the Call button + void updateCallBtnState(bool callIsActive); + + // set the enable/disable state for the Call button + virtual void enableDisableCallBtn() = 0; + +// /* virtual */ void updateTitleButtons(); + + + LLPanelChatControlPanel* mControlPanel; + bool mIsNearbyChat; + bool mIsP2PChat; + + LLUUID mSessionID; + + LLButton* mExpandCollapseBtn; + LLButton* mTearOffBtn; + LLButton* mCloseBtn; + +private: + /// Update floater header and toolbar buttons when hosted/torn off state is toggled. + void updateHeaderAndToolbar(); +}; + + +#endif // LL_IMCONVERSATION_H diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index cd795fcfc7..5339bcb936 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -41,10 +41,9 @@ #include "llfloaterreg.h" #include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container #include "llinventoryfunctions.h" -#include "lllayoutstack.h" +//#include "lllayoutstack.h" #include "lllineeditor.h" #include "lllogchat.h" -#include "llnearbychat.h" #include "llpanelimcontrolpanel.h" #include "llscreenchannel.h" #include "llsyswellwindow.h" @@ -60,18 +59,12 @@ #include "llnotificationmanager.h" LLIMFloater::LLIMFloater(const LLUUID& session_id) - : LLTransientDockableFloater(NULL, true, session_id), - mControlPanel(NULL), - mSessionID(session_id), + : LLIMConversation(session_id), mLastMessageIndex(-1), mDialog(IM_NOTHING_SPECIAL), mInputEditor(NULL), - mCloseBtn(NULL), - mExpandCollapseBtn(NULL), - mTearOffBtn(NULL), mSavedTitle(), mTypingStart(), - mIsP2PChat(false), mShouldSendTypingState(false), mChatHistory(NULL), mMeTyping(false), @@ -81,6 +74,8 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mPositioned(false), mSessionInitialized(false) { + mIsNearbyChat = false; + mSession = LLIMModel::getInstance()->findIMSession(mSessionID); if (mSession) @@ -97,7 +92,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) case IM_SESSION_GROUP_START: mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); break; - case IM_SESSION_INVITE: + case IM_SESSION_INVITE: if (gAgent.isInGroup(mSessionID)) { mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); @@ -116,60 +111,30 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); setDocked(true); - mCommitCallbackRegistrar.add("IMSession.Menu.Action", - boost::bind(&LLIMFloater::onIMSessionMenuItemClicked, this, _2)); - mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", - boost::bind(&LLIMFloater::onIMCompactExpandedMenuItemCheck, this, _2)); - mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.CheckItem", - boost::bind(&LLIMFloater::onIMShowModesMenuItemCheck, this, _2)); - mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", - boost::bind(&LLIMFloater::onIMShowModesMenuItemEnable, this, _2)); -} - -bool LLIMFloater::onIMCompactExpandedMenuItemCheck(const LLSD& userdata) -{ - std::string item = userdata.asString(); - bool is_plain_text_mode = gSavedSettings.getBOOL("PlainTextChatHistory"); - - return is_plain_text_mode? item == "compact_view" : item == "expanded_view"; -} - -bool LLIMFloater::onIMShowModesMenuItemCheck(const LLSD& userdata) -{ - return gSavedSettings.getBOOL(userdata.asString()); } -// enable/disable states for the "show time" and "show names" items of the show-modes menu -bool LLIMFloater::onIMShowModesMenuItemEnable(const LLSD& userdata) +// static +void* LLIMFloater::createPanelGroupControl(void* userdata) { - std::string item = userdata.asString(); - bool plain_text = gSavedSettings.getBOOL("PlainTextChatHistory"); - bool is_not_names = (item != "IMShowNamesForP2PConv"); - return (plain_text && (is_not_names || mIsP2PChat)); + LLIMFloater *self = (LLIMFloater*) userdata; + self->mControlPanel = new LLPanelGroupControlPanel(self->mSessionID); + self->mControlPanel->setXMLFilename("panel_group_control_panel.xml"); + return self->mControlPanel; } -void LLIMFloater::onIMSessionMenuItemClicked(const LLSD& userdata) +// static +void* LLIMFloater::createPanelAdHocControl(void* userdata) { - std::string item = userdata.asString(); - - if (item == "compact_view" || item == "expanded_view") - { - gSavedSettings.setBOOL("PlainTextChatHistory", item == "compact_view"); - } - else - { - bool prev_value = gSavedSettings.getBOOL(item); - gSavedSettings.setBOOL(item, !prev_value); - } - - LLIMFloater::processChatHistoryStyleUpdate(); - LLNearbyChat::processChatHistoryStyleUpdate(); + LLIMFloater *self = (LLIMFloater*) userdata; + self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID); + self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml"); + return self->mControlPanel; } void LLIMFloater::onFocusLost() { LLIMModel::getInstance()->resetActiveSessionID(); - + LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, false); } @@ -185,19 +150,6 @@ void LLIMFloater::onFocusReceived() } } -/*virtual*/ -void LLIMFloater::onOpen(const LLSD& key) -{ - LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); - if (host_floater) - { - // Show the messages pane when opening a floater hosted in the Conversations - host_floater->collapseMessagesPane(false); - } - - updateHeaderAndToolbar(); -} - // virtual void LLIMFloater::onClose(bool app_quitting) { @@ -219,10 +171,9 @@ void LLIMFloater::newIMCallback(const LLSD& data) LLUUID session_id = data["session_id"].asUUID(); LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); - if (floater == NULL) return; // update if visible, otherwise will be updated when opened - if (floater->getVisible()) + if (floater && floater->getVisible()) { floater->updateMessages(); } @@ -255,38 +206,39 @@ void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata ) void LLIMFloater::sendMsg() { - if (!gAgent.isGodlike() - && (mDialog == IM_NOTHING_SPECIAL) - && mOtherParticipantUUID.isNull()) - { - llinfos << "Cannot send IM to everyone unless you're a god." << llendl; - return; - } - - if (mInputEditor) + if (gAgent.isGodlike() + || (mDialog != IM_NOTHING_SPECIAL) + || !mOtherParticipantUUID.isNull()) { - LLWString text = mInputEditor->getConvertedText(); - if(!text.empty()) + if (mInputEditor) { - // Truncate and convert to UTF8 for transport - std::string utf8_text = wstring_to_utf8str(text); - utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); - - if (mSessionInitialized) + LLWString text = mInputEditor->getConvertedText(); + if(!text.empty()) { - LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog); - } - else - { - //queue up the message to send once the session is initialized - mQueuedMsgsForInit.append(utf8_text); - } + // Truncate and convert to UTF8 for transport + std::string utf8_text = wstring_to_utf8str(text); + utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); - mInputEditor->setText(LLStringUtil::null); + if (mSessionInitialized) + { + LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog); + } + else + { + //queue up the message to send once the session is initialized + mQueuedMsgsForInit.append(utf8_text); + } + + mInputEditor->setText(LLStringUtil::null); - updateMessages(); + updateMessages(); + } } } + else + { + llinfos << "Cannot send IM to everyone unless you're a god." << llendl; + } } LLIMFloater::~LLIMFloater() @@ -312,28 +264,6 @@ BOOL LLIMFloater::postBuild() boundVoiceChannel(); - mCloseBtn = getChild<LLButton>("close_btn"); - mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); - - mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); - mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); - - if (mControlPanel) - { - mControlPanel->setSessionId(mSessionID); - mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel")); - - mExpandCollapseBtn->setImageOverlay( - getString(mControlPanel->getParent()->getVisible() ? "collapse_icon" : "expand_icon")); - } - else - { - mExpandCollapseBtn->setEnabled(false); - getChild<LLLayoutPanel>("im_control_panel_holder")->setVisible(false); - } - - mTearOffBtn = getChild<LLButton>("tear_off_btn"); - mTearOffBtn->setCommitCallback(boost::bind(&LLIMFloater::onTearOffClicked, this)); mInputEditor = getChild<LLLineEditor>("chat_editor"); mInputEditor->setMaxTextLength(1023); @@ -386,21 +316,7 @@ BOOL LLIMFloater::postBuild() //*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla" //see LLFloaterIMPanel for how it is done (IB) - if(isChatMultiTab()) - { - return LLFloater::postBuild(); - } - else - { - return LLDockableFloater::postBuild(); - } -} - -void LLIMFloater::onTearOffClicked() -{ - onClickTearOff(this); - - updateHeaderAndToolbar(); + return LLIMConversation::postBuild(); } void LLIMFloater::boundVoiceChannel() @@ -412,37 +328,29 @@ void LLIMFloater::boundVoiceChannel() boost::bind(&LLIMFloater::onVoiceChannelStateChanged, this, _1, _2)); //call (either p2p, group or ad-hoc) can be already in started state - updateCallState(voice_channel->getState()); + bool callIsActive = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED; + updateCallBtnState(callIsActive); } } -void LLIMFloater::updateCallState(LLVoiceChannel::EState state) -{ - bool is_call_started = state >= LLVoiceChannel::STATE_CALL_STARTED; - getChild<LLButton>("voice_call_btn")->setImageOverlay( - is_call_started? getString("call_btn_stop") : getString("call_btn_start")); - enableDisableCallBtn(); - -} - void LLIMFloater::enableDisableCallBtn() { bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); - if (!mSession) + if (mSession) + { + bool session_initialized = mSession->mSessionInitialized; + bool callback_enabled = mSession->mCallBackEnabled; + + BOOL enable_connect = + session_initialized && voice_enabled && callback_enabled; + getChildView("voice_call_btn")->setEnabled(enable_connect); + } + else { getChildView("voice_call_btn")->setEnabled(false); - return; } - - bool session_initialized = mSession->mSessionInitialized; - bool callback_enabled = mSession->mCallBackEnabled; - - BOOL enable_connect = session_initialized - && voice_enabled - && callback_enabled; - getChildView("voice_call_btn")->setEnabled(enable_connect); } @@ -470,18 +378,17 @@ void LLIMFloater::onCallButtonClicked() void LLIMFloater::onChange(EStatusType status, const std::string &channelURI, bool proximal) { - if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) + if(status != STATUS_JOINING && status != STATUS_LEFT_CHANNEL) { - return; + enableDisableCallBtn(); } - - enableDisableCallBtn(); } void LLIMFloater::onVoiceChannelStateChanged( const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) { - updateCallState(new_state); + bool callIsActive = new_state >= LLVoiceChannel::STATE_CALL_STARTED; + updateCallBtnState(callIsActive); } void LLIMFloater::updateSessionName(const std::string& ui_title, @@ -516,48 +423,6 @@ void LLIMFloater::draw() LLTransientDockableFloater::draw(); } -// static -void* LLIMFloater::createPanelGroupControl(void* userdata) -{ - LLIMFloater *self = (LLIMFloater*)userdata; - self->mControlPanel = new LLPanelGroupControlPanel(self->mSessionID); - self->mControlPanel->setXMLFilename("panel_group_control_panel.xml"); - return self->mControlPanel; -} - -// static -void* LLIMFloater::createPanelAdHocControl(void* userdata) -{ - LLIMFloater *self = (LLIMFloater*)userdata; - self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID); - self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml"); - return self->mControlPanel; -} - -void LLIMFloater::onSlide() -{ - LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); - if (host_floater) - { - // Hide the messages pane if a floater is hosted in the Conversations - host_floater->collapseMessagesPane(true); - } - else ///< floater is torn off - { - if (mControlPanel) - { - bool expand = !mControlPanel->getParent()->getVisible(); - - // Expand/collapse the IM control panel - mControlPanel->getParent()->setVisible(expand); - - gSavedSettings.setBOOL("IMShowControlPanel", expand); - - mExpandCollapseBtn->setImageOverlay(getString(expand ? "collapse_icon" : "expand_icon")); - } - } -} - //static LLIMFloater* LLIMFloater::show(const LLUUID& session_id) { @@ -635,6 +500,22 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) return floater; } +//static +LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id) +{ + LLIMFloater* conversation = + LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); + + return conversation; +} + +LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) +{ + LLIMFloater* conversation = + LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id); + + return conversation; +} void LLIMFloater::setDocked(bool docked, bool pop_on_undock) { @@ -697,6 +578,8 @@ void LLIMFloater::setVisible(BOOL visible) BOOL LLIMFloater::getVisible() { + bool visible; + if(isChatMultiTab()) { LLIMFloaterContainer* im_container = @@ -708,17 +591,21 @@ BOOL LLIMFloater::getVisible() //torn off floater is always inactive if (!is_active && getHost() != im_container) { - return LLTransientDockableFloater::getVisible(); + visible = LLTransientDockableFloater::getVisible(); + } + else + { + // getVisible() returns TRUE when Tabbed IM window is minimized. + visible = is_active && !im_container->isMinimized() + && im_container->getVisible(); } - - // getVisible() returns TRUE when Tabbed IM window is minimized. - return is_active && !im_container->isMinimized() - && im_container->getVisible(); } else { - return LLTransientDockableFloater::getVisible(); + visible = LLTransientDockableFloater::getVisible(); } + + return visible; } //static @@ -748,17 +635,6 @@ bool LLIMFloater::toggle(const LLUUID& session_id) return true; } -//static -LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id) -{ - return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -} - -LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) -{ - return LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id); -} - void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) { mSessionInitialized = true; @@ -782,14 +658,15 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) //need to send delayed messaged collected while waiting for session initialization - if (!mQueuedMsgsForInit.size()) - return; - LLSD::array_iterator iter; - for ( iter = mQueuedMsgsForInit.beginArray(); - iter != mQueuedMsgsForInit.endArray(); ++iter) + if (mQueuedMsgsForInit.size()) { - LLIMModel::sendMessage(iter->asString(), mSessionID, - mOtherParticipantUUID, mDialog); + LLSD::array_iterator iter; + for ( iter = mQueuedMsgsForInit.beginArray(); + iter != mQueuedMsgsForInit.endArray(); ++iter) + { + LLIMModel::sendMessage(iter->asString(), mSessionID, + mOtherParticipantUUID, mDialog); + } } } @@ -878,16 +755,16 @@ void LLIMFloater::updateMessages() if (chat.mNotifId.notNull() && LLNotificationsUtil::find(chat.mNotifId) != NULL) { if (++iter == iter_end) - { - break; - } - else - { - mLastMessageIndex++; - } - } - } - } + { + break; + } + else + { + mLastMessageIndex++; + } + } + } + } } void LLIMFloater::reloadMessages() @@ -895,6 +772,7 @@ void LLIMFloater::reloadMessages() mChatHistory->clear(); mLastMessageIndex = -1; updateMessages(); + mInputEditor->setFont(LLViewerChat::getChatFont()); } // static @@ -923,28 +801,22 @@ void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userd // static void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata) { - LLIMFloater* self = (LLIMFloater*)userdata; + LLIMFloater* self = (LLIMFloater*) userdata; std::string text = self->mInputEditor->getText(); - if (!text.empty()) - { - self->setTyping(true); - } - else - { - // Deleting all text counts as stopping typing. - self->setTyping(false); - } + + // Deleting all text counts as stopping typing. + self->setTyping(!text.empty()); } void LLIMFloater::setTyping(bool typing) { - if ( typing ) + if (typing) { // Started or proceeded typing, reset the typing timeout timer mTypingTimeoutTimer.reset(); } - if ( mMeTyping != typing ) + if (mMeTyping != typing) { // Typing state is changed mMeTyping = typing; @@ -956,24 +828,16 @@ void LLIMFloater::setTyping(bool typing) // Don't want to send typing indicators to multiple people, potentially too // much network traffic. Only send in person-to-person IMs. - if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL ) + if (mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL) { - if ( mMeTyping ) - { - if ( mTypingTimer.getElapsedTimeF32() > 1.f ) - { - // Still typing, send 'start typing' notification - LLIMModel::instance().sendTypingState(mSessionID, - mOtherParticipantUUID, TRUE); - mShouldSendTypingState = false; - } - } - else + // Still typing, send 'start typing' notification or + // send 'stop typing' notification immediately + if (!mMeTyping || mTypingTimer.getElapsedTimeF32() > 1.f) { - // Send 'stop typing' notification immediately LLIMModel::instance().sendTypingState(mSessionID, - mOtherParticipantUUID, FALSE); + mOtherParticipantUUID, mMeTyping); mShouldSendTypingState = false; + } } @@ -985,7 +849,7 @@ void LLIMFloater::setTyping(bool typing) void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) { - if ( typing ) + if (typing) { // other user started typing addTypingIndicator(im_info); @@ -999,10 +863,7 @@ void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) void LLIMFloater::processAgentListUpdates(const LLSD& body) { - if (!body.isMap()) - return; - - if ( body.has("agent_updates") && body["agent_updates"].isMap() ) + if (body.isMap() && body.has("agent_updates") && body["agent_updates"].isMap()) { LLSD agent_data = body["agent_updates"].get(gAgentID.asString()); if (agent_data.isMap() && agent_data.has("info")) @@ -1011,7 +872,7 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body) if (agent_info.has("mutes")) { - BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean(); + BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean(); mInputEditor->setEnabled(!moderator_muted_text); std::string label; if (moderator_muted_text) @@ -1027,27 +888,11 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body) } } -void LLIMFloater::processChatHistoryStyleUpdate() -{ - LLFontGL* font = LLViewerChat::getChatFont(); - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); - iter != inst_list.end(); ++iter) - { - LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); - if (floater) - { - floater->reloadMessages(); - floater->mInputEditor->setFont(font); - } - } -} - void LLIMFloater::processSessionUpdate(const LLSD& session_update) { // *TODO : verify following code when moderated mode will be implemented - if ( false && session_update.has("moderated_mode") && - session_update["moderated_mode"].has("voice") ) + if (false && session_update.has("moderated_mode") && + session_update["moderated_mode"].has("voice")) { BOOL voice_moderated = session_update["moderated_mode"]["voice"]; const std::string session_label = LLIMModel::instance().getName(mSessionID); @@ -1069,14 +914,14 @@ void LLIMFloater::processSessionUpdate(const LLSD& session_update) } BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, EDragAndDropType cargo_type, - void *cargo_data, EAcceptance *accept, - std::string& tooltip_msg) + BOOL drop, EDragAndDropType cargo_type, + void *cargo_data, EAcceptance *accept, + std::string& tooltip_msg) { if (mDialog == IM_NOTHING_SPECIAL) { LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, - cargo_type, cargo_data, accept); + cargo_type, cargo_data, accept); } // handle case for dropping calling cards (and folders of calling cards) onto invitation panel for invites @@ -1086,14 +931,14 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, if (cargo_type == DAD_CALLINGCARD) { - if (dropCallingCard((LLInventoryItem*)cargo_data, drop)) + if (dropCallingCard((LLInventoryItem*) cargo_data, drop)) { *accept = ACCEPT_YES_MULTI; } } else if (cargo_type == DAD_CATEGORY) { - if (dropCategory((LLInventoryCategory*)cargo_data, drop)) + if (dropCategory((LLInventoryCategory*) cargo_data, drop)) { *accept = ACCEPT_YES_MULTI; } @@ -1105,9 +950,9 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop) { BOOL rv = isInviteAllowed(); - if(rv && item && item->getCreatorUUID().notNull()) + if (rv && item && item->getCreatorUUID().notNull()) { - if(drop) + if (drop) { uuid_vec_t ids; ids.push_back(item->getCreatorUUID()); @@ -1125,26 +970,26 @@ BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop) BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop) { BOOL rv = isInviteAllowed(); - if(rv && category) + if (rv && category) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; LLUniqueBuddyCollector buddies; gInventory.collectDescendentsIf(category->getUUID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - buddies); + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + buddies); S32 count = items.count(); - if(count == 0) + if (count == 0) { rv = FALSE; } - else if(drop) + else if (drop) { uuid_vec_t ids; ids.reserve(count); - for(S32 i = 0; i < count; ++i) + for (S32 i = 0; i < count; ++i) { ids.push_back(items.get(i)->getCreatorUUID()); } @@ -1156,11 +1001,11 @@ BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop) BOOL LLIMFloater::isInviteAllowed() const { - return ( (IM_SESSION_CONFERENCE_START == mDialog) - || (IM_SESSION_INVITE == mDialog) ); + return ((IM_SESSION_CONFERENCE_START == mDialog) + || (IM_SESSION_INVITE == mDialog)); } -class LLSessionInviteResponder : public LLHTTPClient::Responder +class LLSessionInviteResponder: public LLHTTPClient::Responder { public: LLSessionInviteResponder(const LLUUID& session_id) @@ -1181,60 +1026,60 @@ private: BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) { LLViewerRegion* region = gAgent.getRegion(); - if (!region) + bool is_region_exist = !!region; + + if (is_region_exist) { - return FALSE; - } + S32 count = ids.size(); - S32 count = ids.size(); + if (isInviteAllowed() && (count > 0)) + { + llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl; - if( isInviteAllowed() && (count > 0) ) - { - llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl; + std::string url = region->getCapability("ChatSessionRequest"); - std::string url = region->getCapability("ChatSessionRequest"); + LLSD data; - LLSD data; + data["params"] = LLSD::emptyArray(); + for (int i = 0; i < count; i++) + { + data["params"].append(ids[i]); + } - data["params"] = LLSD::emptyArray(); - for (int i = 0; i < count; i++) + data["method"] = "invite"; + data["session-id"] = mSessionID; + LLHTTPClient::post( + url, + data, + new LLSessionInviteResponder(mSessionID)); + } + else { - data["params"].append(ids[i]); + llinfos << "LLIMFloater::inviteToSession -" + << " no need to invite agents for " + << mDialog << llendl; + // successful add, because everyone that needed to get added + // was added. } - - data["method"] = "invite"; - data["session-id"] = mSessionID; - LLHTTPClient::post( - url, - data, - new LLSessionInviteResponder(mSessionID)); - } - else - { - llinfos << "LLIMFloater::inviteToSession -" - << " no need to invite agents for " - << mDialog << llendl; - // successful add, because everyone that needed to get added - // was added. } - return TRUE; + return is_region_exist; } void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info) { // We may have lost a "stop-typing" packet, don't add it twice - if ( im_info && !mOtherTyping ) + if (im_info && !mOtherTyping) { mOtherTyping = true; // Save and set new title mSavedTitle = getTitle(); - setTitle (mTypingStart); + setTitle(mTypingStart); // Update speaker LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if ( speaker_mgr ) + if (speaker_mgr) { speaker_mgr->setSpeakerTyping(im_info->mFromID, TRUE); } @@ -1243,18 +1088,18 @@ void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info) void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info) { - if ( mOtherTyping ) + if (mOtherTyping) { mOtherTyping = false; // Revert the title to saved one setTitle(mSavedTitle); - if ( im_info ) + if (im_info) { // Update speaker LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if ( speaker_mgr ) + if (speaker_mgr) { speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE); } @@ -1262,59 +1107,6 @@ void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info) } } -void LLIMFloater::updateHeaderAndToolbar() -{ - bool is_hosted = getHost() != NULL; - - if (is_hosted) - { - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - if (!mButtons[i]) - { - continue; - } - - // Hide the standard header buttons in a docked IM floater. - mButtons[i]->setVisible(false); - } -} - - bool is_control_panel_visible = false; - if (mControlPanel) - { - // Control panel should be visible only in torn off floaters. - is_control_panel_visible = !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel"); - mControlPanel->getParent()->setVisible(is_control_panel_visible); - } - - // Display collapse image (<<) if the floater is hosted - // or if it is torn off but has an open control panel. - bool is_expanded = is_hosted || is_control_panel_visible; - mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); - - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); - if (session) - { - // The button (>>) should be disabled for torn off P2P conversations. - mExpandCollapseBtn->setEnabled(is_hosted || !session->isP2PSessionType()); - } - else - { - llwarns << "IM session not found." << llendl; - } - - if (mDragHandle) - { - // toggle floater's drag handle and title visibility - mDragHandle->setVisible(!is_hosted); - } - - mTearOffBtn->setImageOverlay(getString(is_hosted ? "tear_off_icon" : "return_icon")); - - mCloseBtn->setVisible(is_hosted); -} - // static void LLIMFloater::closeHiddenIMToasts() { @@ -1351,14 +1143,6 @@ void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD& return; } -// static -bool LLIMFloater::isChatMultiTab() -{ - // Restart is required in order to change chat window type. - static bool is_single_window = gSavedSettings.getS32("ChatWindow") == 1; - return is_single_window; -} - // static void LLIMFloater::initIMFloater() { @@ -1390,28 +1174,32 @@ void LLIMFloater::sRemoveTypingIndicator(const LLSD& data) void LLIMFloater::onIMChicletCreated( const LLUUID& session_id ) { + LLIMFloater::addToHost(session_id); +} - if (isChatMultiTab()) +void LLIMFloater::addToHost(const LLUUID& session_id) +{ + if (LLIMConversation::isChatMultiTab()) { - LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); if (!im_box) - return; - - if (LLIMFloater::findInstance(session_id)) - return; - - LLIMFloater* new_tab = LLIMFloater::getInstance(session_id); + { + im_box = LLIMFloaterContainer::getInstance(); + } - im_box->addFloater(new_tab, FALSE, LLTabContainer::END); + if (im_box && !LLIMFloater::findInstance(session_id)) + { + LLIMFloater* new_tab = LLIMFloater::getInstance(session_id); + im_box->addFloater(new_tab, FALSE, LLTabContainer::END); + } } - } void LLIMFloater::onClickCloseBtn() { LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - mSessionID); + mSessionID); if (session == NULL) { diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 8e7ab4cc21..c7793f73eb 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -28,17 +28,16 @@ #define LL_IMFLOATER_H #include "llimview.h" +#include "llimconversation.h" #include "llinstantmessage.h" #include "lllogchat.h" #include "lltooldraganddrop.h" #include "llvoicechannel.h" #include "llvoiceclient.h" -#include "lltransientdockablefloater.h" class LLAvatarName; class LLButton; class LLLineEditor; -class LLPanelChatControlPanel; class LLChatHistory; class LLInventoryItem; class LLInventoryCategory; @@ -48,8 +47,8 @@ class LLInventoryCategory; * optionally "docked" to the bottom tray. */ class LLIMFloater - : public LLTransientDockableFloater - , public LLVoiceClientStatusObserver + : public LLVoiceClientStatusObserver + , public LLIMConversation { LOG_CLASS(LLIMFloater); public: @@ -64,11 +63,16 @@ public: // Check typing timeout timer. /*virtual*/ void draw(); + static void* createPanelGroupControl(void* userdata); + static void* createPanelAdHocControl(void* userdata); + + static LLIMFloater* findInstance(const LLUUID& session_id); + static LLIMFloater* getInstance(const LLUUID& session_id); + static void addToHost(const LLUUID& session_id); + // LLFloater overrides - /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); - // Make IM conversion visible and update the message history static LLIMFloater* show(const LLUUID& session_id); @@ -76,10 +80,6 @@ public: // Returns true iff panel became visible static bool toggle(const LLUUID& session_id); - static LLIMFloater* findInstance(const LLUUID& session_id); - - static LLIMFloater* getInstance(const LLUUID& session_id); - void sessionInitReplyReceived(const LLUUID& im_session_id); // get new messages from LLIMModel @@ -102,6 +102,7 @@ public: void onChange(EStatusType status, const std::string &channelURI, bool proximal); + virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } virtual void onVoiceChannelStateChanged( const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); @@ -110,28 +111,18 @@ public: void processAgentListUpdates(const LLSD& body); void processSessionUpdate(const LLSD& session_update); - static void processChatHistoryStyleUpdate(); - BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg); - /** - * Returns true if chat is displayed in multi tabbed floater - * false if chat is displayed in multiple windows - */ - static bool isChatMultiTab(); static void initIMFloater(); //used as a callback on receiving new IM message static void sRemoveTypingIndicator(const LLSD& data); - static void onIMChicletCreated(const LLUUID& session_id); - virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } - protected: /* virtual */ void onClickCloseBtn(); @@ -156,23 +147,13 @@ private: static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); void setTyping(bool typing); - void onSlide(); - static void* createPanelGroupControl(void* userdata); - static void* createPanelAdHocControl(void* userdata); - void onTearOffClicked(); - - bool onIMCompactExpandedMenuItemCheck(const LLSD& userdata); - bool onIMShowModesMenuItemCheck(const LLSD& userdata); - bool onIMShowModesMenuItemEnable(const LLSD& userdata); - void onIMSessionMenuItemClicked(const LLSD& userdata); void onCallButtonClicked(); - void boundVoiceChannel(); - void enableDisableCallBtn(); + // set the enable/disable state for the Call button + virtual void enableDisableCallBtn(); - // refresh a visual state of the Call button - void updateCallState(LLVoiceChannel::EState state); + void boundVoiceChannel(); // Add the "User is typing..." indicator. void addTypingIndicator(const LLIMInfo* im_info); @@ -180,15 +161,11 @@ private: // Remove the "User is typing..." indicator. void removeTypingIndicator(const LLIMInfo* im_info = NULL); - /// Update floater header and toolbar buttons when hosted/torn off state is toggled. - void updateHeaderAndToolbar(); - static void closeHiddenIMToasts(); static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); - LLPanelChatControlPanel* mControlPanel; - LLUUID mSessionID; + LLIMModel::LLIMSession* mSession; S32 mLastMessageIndex; @@ -204,7 +181,6 @@ private: bool mMeTyping; bool mOtherTyping; bool mShouldSendTypingState; - bool mIsP2PChat; LLFrameTimer mTypingTimer; LLFrameTimer mTypingTimeoutTimer; @@ -213,10 +189,6 @@ private: // connection to voice channel state change signal boost::signals2::connection mVoiceChannelStateChangeConnection; - - LLButton* mCloseBtn; - LLButton* mExpandCollapseBtn; - LLButton* mTearOffBtn; }; #endif // LL_IMFLOATER_H diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index b051440589..f72ddef412 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -31,6 +31,7 @@ #include "llfloaterreg.h" #include "lllayoutstack.h" +#include "llnearbychatbar.h" #include "llagent.h" #include "llavatariconctrl.h" diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 18d39b7aa4..c3ac1d32cb 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -41,7 +41,7 @@ #include "lltextutil.h" #include "lltrans.h" #include "lluictrlfactory.h" - +#include "llimconversation.h" #include "llagent.h" #include "llagentui.h" #include "llappviewer.h" diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 3c4b0b9aae..497690d656 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -25,7 +25,6 @@ */ #include "llviewerprecompiledheaders.h" -#include "llnearbychat.h" #include "llviewercontrol.h" #include "llviewerwindow.h" #include "llrootview.h" @@ -93,9 +92,9 @@ static const S32 RESIZE_BAR_THICKNESS = 3; static LLRegisterPanelClassWrapper<LLNearbyChat> t_panel_nearby_chat("panel_nearby_chat"); -LLNearbyChat::LLNearbyChat(const LLNearbyChat::Params& p) -: LLPanel(p), - mChatHistory(NULL) +LLNearbyChat::LLNearbyChat(const LLNearbyChat::Params& p) + : LLPanel(p), + mChatHistory(NULL) { } @@ -117,10 +116,7 @@ BOOL LLNearbyChat::postBuild() mChatHistory = getChild<LLChatHistory>("chat_history"); - if(!LLPanel::postBuild()) - return false; - - return true; + return LLPanel::postBuild(); } @@ -139,8 +135,7 @@ void LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args) chat_args["use_plain_text_chat_history"] = gSavedSettings.getBOOL("PlainTextChatHistory"); chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); - chat_args["show_names_for_p2p_conv"] = false - || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + chat_args["show_names_for_p2p_conv"] = true; mChatHistory->appendMessage(chat, chat_args); } @@ -223,7 +218,7 @@ void LLNearbyChat::getAllowedRect(LLRect& rect) rect = gViewerWindow->getWorldViewRectScaled(); } -void LLNearbyChat::updateChatHistoryStyle() +void LLNearbyChat::reloadMessages() { mChatHistory->clear(); @@ -236,15 +231,6 @@ void LLNearbyChat::updateChatHistoryStyle() } } -//static -void LLNearbyChat::processChatHistoryStyleUpdate() -{ - LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); - LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); - if(nearby_chat) - nearby_chat->updateChatHistoryStyle(); -} - void LLNearbyChat::loadHistory() { LLSD do_not_log; diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 47f4de1c6d..62a41c17cb 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -29,13 +29,13 @@ #include "llscrollbar.h" #include "llviewerchat.h" -#include "llfloater.h" +#include "llpanel.h" class LLResizeBar; class LLChatHistory; class LLNearbyChat -: public LLPanel + : public LLPanel { public: LLNearbyChat(const Params& p = LLPanel::getDefaultParams()); @@ -56,12 +56,8 @@ public: /*virtual*/ void setVisible(BOOL visible); - virtual void updateChatHistoryStyle(); - - static void processChatHistoryStyleUpdate(); - void loadHistory(); - + void reloadMessages(); static LLNearbyChat* getInstance(); void removeScreenChat(); diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index b4224e30e6..82c00253e8 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -31,7 +31,7 @@ #include "llappviewer.h" #include "llfloaterreg.h" #include "lltrans.h" - +#include "llimfloatercontainer.h" #include "llfirstuse.h" #include "llnearbychatbar.h" #include "llagent.h" @@ -54,7 +54,7 @@ S32 LLNearbyChatBar::sLastSpecialChatChannel = 0; -const S32 EXPANDED_HEIGHT = 300; +const S32 EXPANDED_HEIGHT = 266; const S32 COLLAPSED_HEIGHT = 60; const S32 EXPANDED_MIN_HEIGHT = 150; @@ -72,7 +72,7 @@ static LLChatTypeTrigger sChatTypeTriggers[] = { }; LLNearbyChatBar::LLNearbyChatBar(const LLSD& key) -: LLFloater(key), +: LLIMConversation(key), mChatBox(NULL), mNearbyChat(NULL), mOutputMonitor(NULL), @@ -116,14 +116,44 @@ BOOL LLNearbyChatBar::postBuild() // Register for font change notifications LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChatBar::onChatFontChange, this, _1)); + // childSetAction("voice_call_btn", boost::bind(&LLNearbyChatBar::onCallButtonClicked, this)); + enableResizeCtrls(true, true, false); - return TRUE; + addToHost(); + + return LLIMConversation::postBuild();; +} + +void LLNearbyChatBar::onCallButtonClicked() +{ + LLAgent::toggleMicrophone(NULL); +} + +void LLNearbyChatBar::enableDisableCallBtn() +{ + // bool btn_enabled = LLAgent::isActionAllowed("speak"); + + getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/); +} + +void LLNearbyChatBar::addToHost() +{ + if (LLIMConversation::isChatMultiTab()) + { + LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + + if (im_box) + { + im_box->addFloater(this, FALSE, LLTabContainer::END); + } + } } // virtual void LLNearbyChatBar::onOpen(const LLSD& key) { + LLIMConversation::onOpen(key); showTranslationCheckbox(LLTranslate::isTranslationConfigured()); } @@ -160,6 +190,12 @@ LLNearbyChatBar* LLNearbyChatBar::getInstance() return LLFloaterReg::getTypedInstance<LLNearbyChatBar>("chat_bar"); } +//static +//LLNearbyChatBar* LLNearbyChatBar::findInstance() +//{ +// return LLFloaterReg::findTypedInstance<LLNearbyChatBar>("chat_bar"); +//} + void LLNearbyChatBar::showHistory() { openFloater(); @@ -178,7 +214,8 @@ void LLNearbyChatBar::showTranslationCheckbox(BOOL show) void LLNearbyChatBar::draw() { displaySpeakingIndicator(); - LLFloater::draw(); + updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); + LLIMConversation::draw(); } std::string LLNearbyChatBar::getCurrentChat() @@ -206,22 +243,24 @@ BOOL LLNearbyChatBar::matchChatTypeTrigger(const std::string& in_str, std::strin U32 in_len = in_str.length(); S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); - for (S32 n = 0; n < cnt; n++) - { - if (in_len > sChatTypeTriggers[n].name.length()) - continue; - - std::string trigger_trunc = sChatTypeTriggers[n].name; - LLStringUtil::truncate(trigger_trunc, in_len); + bool string_was_found = false; - if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) + for (S32 n = 0; n < cnt && !string_was_found; n++) + { + if (in_len <= sChatTypeTriggers[n].name.length()) { - *out_str = sChatTypeTriggers[n].name; - return TRUE; + std::string trigger_trunc = sChatTypeTriggers[n].name; + LLStringUtil::truncate(trigger_trunc, in_len); + + if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) + { + *out_str = sChatTypeTriggers[n].name; + string_was_found = true; + } } } - return FALSE; + return string_was_found; } void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) @@ -421,6 +460,11 @@ void LLNearbyChatBar::onToggleNearbyChatPanel() gSavedSettings.setBOOL("nearbychat_history_visibility", mNearbyChat->getVisible()); } +void LLNearbyChatBar::reloadMessages() +{ + LLNearbyChat::getInstance()->reloadMessages(); +} + void LLNearbyChatBar::setMinimized(BOOL b) { LLNearbyChat* nearby_chat = getChild<LLNearbyChat>("nearby_chat"); @@ -531,20 +575,20 @@ void LLNearbyChatBar::startChat(const char* line) { LLNearbyChatBar* cb = LLNearbyChatBar::getInstance(); - if (!cb ) - return; + if (cb ) + { + cb->setVisible(TRUE); + cb->setFocus(TRUE); + cb->mChatBox->setFocus(TRUE); - cb->setVisible(TRUE); - cb->setFocus(TRUE); - cb->mChatBox->setFocus(TRUE); + if (line) + { + std::string line_string(line); + cb->mChatBox->setText(line_string); + } - if (line) - { - std::string line_string(line); - cb->mChatBox->setText(line_string); + cb->mChatBox->setCursorToEnd(); } - - cb->mChatBox->setCursorToEnd(); } // Exit "chat mode" and do the appropriate focus changes @@ -553,13 +597,13 @@ void LLNearbyChatBar::stopChat() { LLNearbyChatBar* cb = LLNearbyChatBar::getInstance(); - if (!cb) - return; - - cb->mChatBox->setFocus(FALSE); + if (cb) + { + cb->mChatBox->setFocus(FALSE); - // stop typing animation - gAgent.stopTyping(); + // stop typing animation + gAgent.stopTyping(); + } } // If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20. diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index 8547cf0bce..e714c04498 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -27,26 +27,31 @@ #ifndef LL_LLNEARBYCHATBAR_H #define LL_LLNEARBYCHATBAR_H -#include "llfloater.h" +#include "llimconversation.h" #include "llcombobox.h" #include "llgesturemgr.h" #include "llchat.h" +#include "llnearbychat.h" #include "llvoiceclient.h" #include "lloutputmonitorctrl.h" #include "llspeakers.h" -class LLNearbyChatBar : public LLFloater +class LLNearbyChatBar : public LLIMConversation { public: // constructor for inline chat-bars (e.g. hosted in chat history window) LLNearbyChatBar(const LLSD& key); ~LLNearbyChatBar() {} - virtual BOOL postBuild(); + /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); static LLNearbyChatBar* getInstance(); +// static LLNearbyChatBar* findInstance(); + void addToHost(); + + void reloadMessages(); LLLineEditor* getChatBox() { return mChatBox; } virtual void draw(); @@ -83,6 +88,11 @@ protected: void displaySpeakingIndicator(); + void onCallButtonClicked(); + + // set the enable/disable state for the Call button + virtual void enableDisableCallBtn(); + // Which non-zero channel did we last chat on? static S32 sLastSpecialChatChannel; diff --git a/indra/newview/skins/default/xui/en/floater_chat_bar.xml b/indra/newview/skins/default/xui/en/floater_chat_bar.xml index 63992462b3..7688525e13 100644 --- a/indra/newview/skins/default/xui/en/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/en/floater_chat_bar.xml @@ -3,32 +3,151 @@ open_positioning="specified" specified_left="10" specified_bottom="10" - height="60" + background_visible="true" + default_tab_group="1" + height="355" + help_topic="chat_bar" layout="topleft" - legacy_header_height="25" - single_instance="true" - title="NEARBY CHAT" - save_rect="true" - save_visibility="true" - can_close="true" + name="chat_bar" + can_dock="false" can_minimize="true" - help_topic="chat_bar" - min_height="60" - min_width="150" + can_close="true" + visible="false" + width="394" can_resize="true" - default_tab_group="1" - name="chat_bar" - width="300"> + can_tear_off="false" + min_width="250" + min_height="80" + single_instance="true" + title="Nearby chat"> + <floater.string name="call_btn_start">VoicePTT_Off</floater.string> + <floater.string name="call_btn_stop">VoicePTT_On</floater.string> + <floater.string + name="collapse_icon" + value="TabIcon_Open_Off"/> + <floater.string + name="expand_icon" + value="TabIcon_Close_Off"/> + <floater.string + name="tear_off_icon" + value="tearoffbox.tga"/> + <floater.string + name="return_icon" + value="Icon_Dock_Foreground"/> + <view + follows="all" + layout="topleft" + name="contents_view" + top="0" + left="0" + height="355" + width="394"> + <panel + follows="left|top|right" + layout="topleft" + name="toolbar_panel" + top="0" + left="0" + height="35" + width="394"> + <menu_button + menu_filename="menu_im_session_showmodes.xml" + follows="top|left" + height="25" + image_hover_unselected="Toolbar_Left_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Left_Selected" + image_unselected="Toolbar_Left_Off" + layout="topleft" + left="5" + name="view_options_btn" + top="5" + width="31" /> + <button + follows="top|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_pad="4" + name="add_btn" + width="31"> + <commit_callback + function="Chats.add" /> + </button> + <button + follows="top|left" + height="25" + image_hover_unselected="Toolbar_Right_Over" + image_overlay="VoicePTT_Off" + image_selected="Toolbar_Right_Selected" + image_unselected="Toolbar_Right_Off" + layout="topleft" + top="5" + left_pad="4" + name="voice_call_btn" + width="31"> + <commit_callback + function="Chats.add" /> + </button> + <button + follows="right|top" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Icon_Close_Foreground" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left="283" + name="close_btn" + width="31"> + </button> + <button + follows="right|top" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TabIcon_Open_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_pad="5" + name="expand_collapse_btn" + width="31"> + </button> + <button + follows="right|top" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="tearoffbox.tga" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_pad="5" + name="tear_off_btn" + width="31"> + </button> + </panel> <panel - top="20" + top="35" + left="0" class="panel_nearby_chat" follow="all" - width="300" + width="390" height="0" visible="false" filename="panel_nearby_chat.xml" name="nearby_chat" /> - <panel width="300" + <panel + width="390" + height="10" + visible="true" /> + <panel width="394" height="31" left="0" name="bottom_panel" @@ -39,18 +158,15 @@ border_style="line" border_thickness="1" follows="left|right" - height="23" + height="20" label="Click here to chat." layout="topleft" - left_delta="7" - left="0" + left="1" max_length_bytes="1023" name="chat_box" - text_pad_left="5" - text_pad_right="25" tool_tip="Press Enter to say, Ctrl+Enter to shout" top="2" - width="255" /> + width="384" /> <output_monitor auto_update="true" follows="right" @@ -65,6 +181,7 @@ width="20" /> <button follows="right" + visible="false" is_toggle="true" width="20" top="2" @@ -81,4 +198,5 @@ tool_tip="Shows/hides nearby chat log"> </button> </panel> + </view> </floater> diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml index d683116eb8..b415ba780d 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml @@ -1,20 +1,21 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel follows="all" - height="300" + top="0" + bottom_delta="10" help_topic="nearby_chat" layout="topleft" name="nearby_chat" - width="320"> + width="394"> <layout_stack follows="all" - height="295" + height="278" layout="topleft" left="0" name="stack" top="5" orientation="vertical" - width="320"> + width="394"> <layout_panel auto_resize="false" height="26" @@ -23,7 +24,7 @@ name="translate_chat_checkbox_lp" top_delta="0" visible="true" - width="313"> + width="387"> <check_box top="10" control_name="TranslateChat" @@ -33,15 +34,15 @@ layout="topleft" left="5" name="translate_chat_checkbox" - width="300" /> + width="374" /> </layout_panel> <layout_panel auto_resize="true" - height="277" + height="256" left_delta="0" layout="topleft" name="chat_history_lp" - width="318"> + width="394"> <chat_history bg_readonly_color="ChatHistoryBgColor" bg_writeable_color="ChatHistoryBgColor" @@ -49,7 +50,7 @@ layout="topleft" left="5" left_widget_pad="0" - height="272" + height="240" name="chat_history" parse_highlights="true" parse_urls="true" @@ -57,7 +58,7 @@ text_color="ChatHistoryTextColor" text_readonly_color="ChatHistoryTextColor" top="0" - width="313" /> + width="384" /> </layout_panel> </layout_stack> </panel> -- cgit v1.2.3 From fe252836ebfb8a1247b0ae3222056d0543203a44 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 30 May 2012 22:58:22 +0300 Subject: Build fix --- indra/newview/llimconversation.cpp | 2 ++ indra/newview/llnearbychatbar.cpp | 7 ------- indra/newview/llnearbychatbar.h | 2 -- 3 files changed, 2 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 7220ab6a82..f5d84e80c1 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -25,6 +25,8 @@ * $/LicenseInfo$ */ +#include "llviewerprecompiledheaders.h" + #include "llpanelimcontrolpanel.h" #include "lldraghandle.h" diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 82c00253e8..68934be11a 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -116,8 +116,6 @@ BOOL LLNearbyChatBar::postBuild() // Register for font change notifications LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChatBar::onChatFontChange, this, _1)); - // childSetAction("voice_call_btn", boost::bind(&LLNearbyChatBar::onCallButtonClicked, this)); - enableResizeCtrls(true, true, false); addToHost(); @@ -125,11 +123,6 @@ BOOL LLNearbyChatBar::postBuild() return LLIMConversation::postBuild();; } -void LLNearbyChatBar::onCallButtonClicked() -{ - LLAgent::toggleMicrophone(NULL); -} - void LLNearbyChatBar::enableDisableCallBtn() { // bool btn_enabled = LLAgent::isActionAllowed("speak"); diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index e714c04498..b7c4c993c6 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -88,8 +88,6 @@ protected: void displaySpeakingIndicator(); - void onCallButtonClicked(); - // set the enable/disable state for the Call button virtual void enableDisableCallBtn(); -- cgit v1.2.3 From bba0f4f74e56d911df8fc534d83cd4a84993bc8b Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Thu, 31 May 2012 16:37:22 +0300 Subject: CHUI-119 WIP --- indra/newview/CMakeLists.txt | 4 - indra/newview/llagent.cpp | 6 +- indra/newview/llchatitemscontainerctrl.cpp | 6 +- indra/newview/llfloatertranslationsettings.cpp | 4 +- indra/newview/llgesturemgr.cpp | 4 +- indra/newview/llimconversation.cpp | 97 ++- indra/newview/llimconversation.h | 12 +- indra/newview/llimfloater.cpp | 67 +- indra/newview/llimfloater.h | 9 +- indra/newview/llimfloatercontainer.cpp | 2 +- indra/newview/llimview.cpp | 5 +- indra/newview/llnearbychat.cpp | 840 ++++++++++++++++++--- indra/newview/llnearbychat.h | 107 ++- indra/newview/llnearbychatbar.cpp | 709 ----------------- indra/newview/llnearbychatbar.h | 105 --- indra/newview/llnearbychatbarlistener.cpp | 4 +- indra/newview/llnearbychatbarlistener.h | 6 +- indra/newview/llnearbychathandler.cpp | 9 +- indra/newview/llnotificationtiphandler.cpp | 5 +- indra/newview/llpanelimcontrolpanel.cpp | 81 -- indra/newview/llviewerfloaterreg.cpp | 4 +- indra/newview/llviewergesture.cpp | 4 +- indra/newview/llviewerkeyboard.cpp | 10 +- indra/newview/llviewerwindow.cpp | 8 +- .../skins/default/xui/en/floater_chat_bar.xml | 202 ----- .../skins/default/xui/en/floater_im_session.xml | 119 ++- .../default/xui/en/panel_adhoc_control_panel.xml | 95 --- .../default/xui/en/panel_group_control_panel.xml | 60 -- .../skins/default/xui/en/panel_nearby_chat.xml | 19 +- 29 files changed, 1037 insertions(+), 1566 deletions(-) delete mode 100644 indra/newview/llnearbychatbar.cpp delete mode 100644 indra/newview/llnearbychatbar.h delete mode 100644 indra/newview/skins/default/xui/en/floater_chat_bar.xml delete mode 100644 indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml delete mode 100644 indra/newview/skins/default/xui/en/panel_group_control_panel.xml (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 86d30c239f..509f9581d6 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -332,7 +332,6 @@ set(viewer_SOURCE_FILES llnamelistctrl.cpp llnavigationbar.cpp llnearbychat.cpp - llnearbychatbar.cpp llnearbychathandler.cpp llnearbychatbarlistener.cpp llnetmap.cpp @@ -364,7 +363,6 @@ set(viewer_SOURCE_FILES llpanelgroupnotices.cpp llpanelgrouproles.cpp llpanelhome.cpp - llpanelimcontrolpanel.cpp llpanelland.cpp llpanellandaudio.cpp llpanellandmarkinfo.cpp @@ -890,7 +888,6 @@ set(viewer_HEADER_FILES llnamelistctrl.h llnavigationbar.h llnearbychat.h - llnearbychatbar.h llnearbychathandler.h llnearbychatbarlistener.h llnetmap.h @@ -916,7 +913,6 @@ set(viewer_HEADER_FILES llpanelgroupnotices.h llpanelgrouproles.h llpanelhome.h - llpanelimcontrolpanel.h llpanelland.h llpanellandaudio.h llpanellandmarkinfo.h diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 3870a3be2e..0db03289d8 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -54,7 +54,7 @@ #include "llmorphview.h" #include "llmoveview.h" #include "llnavigationbar.h" // to show/hide navigation bar when changing mouse look state -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llnotificationsutil.h" #include "llpaneltopinfobar.h" #include "llparcel.h" @@ -1778,7 +1778,7 @@ void LLAgent::startTyping() { sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START); } - LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE); + LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE); } //----------------------------------------------------------------------------- @@ -1790,7 +1790,7 @@ void LLAgent::stopTyping() { clearRenderState(AGENT_STATE_TYPING); sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); - LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); + LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); } } diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 7477fbd656..477bdb3967 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -35,7 +35,7 @@ #include "llfloaterreg.h" #include "lllocalcliprect.h" #include "lltrans.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llviewercontrol.h" #include "llagentdata.h" @@ -316,12 +316,12 @@ BOOL LLNearbyChatToastPanel::handleMouseUp (S32 x, S32 y, MASK mask) return TRUE; else { - LLNearbyChatBar::getInstance()->showHistory(); + LLNearbyChat::getInstance()->showHistory(); return FALSE; } } - LLNearbyChatBar::getInstance()->showHistory(); + LLNearbyChat::getInstance()->showHistory(); return LLPanel::handleMouseUp(x,y,mask); } diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 1a17183efd..bb01ce5a7e 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -29,7 +29,7 @@ #include "llfloatertranslationsettings.h" // Viewer includes -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "lltranslate.h" #include "llviewercontrol.h" // for gSavedSettings @@ -293,6 +293,6 @@ void LLFloaterTranslationSettings::onBtnOK() gSavedSettings.setString("TranslationService", getSelectedService()); gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey()); gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); - LLNearbyChatBar::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured()); + LLNearbyChat::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured()); closeFloater(false); } diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 66ca76bfb0..26b63bdacb 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -51,7 +51,7 @@ #include "llviewermessage.h" #include "llvoavatarself.h" #include "llviewerstats.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llappearancemgr.h" #include "llgesturelistener.h" @@ -997,7 +997,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) const BOOL animate = FALSE; - LLNearbyChatBar::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); + LLNearbyChat::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); gesture->mCurrentStep++; break; diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index f5d84e80c1..893d8dc83f 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -27,25 +27,27 @@ #include "llviewerprecompiledheaders.h" -#include "llpanelimcontrolpanel.h" +#include "llimconversation.h" #include "lldraghandle.h" #include "llfloaterreg.h" -#include "llimconversation.h" #include "llimfloater.h" #include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container #include "lllayoutstack.h" #include "llnearbychat.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" + +const F32 REFRESH_INTERVAL = 0.2; LLIMConversation::LLIMConversation(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id) - , mControlPanel(NULL) + , LLEventTimer(REFRESH_INTERVAL) , mIsP2PChat(false) , mExpandCollapseBtn(NULL) , mTearOffBtn(NULL) , mCloseBtn(NULL) , mSessionID(session_id) + , mParticipantList(NULL) { mCommitCallbackRegistrar.add("IMSession.Menu.Action", boost::bind(&LLIMConversation::onIMSessionMenuItemClicked, this, _2)); @@ -63,6 +65,15 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id) boost::bind(&LLIMConversation::onIMShowModesMenuItemEnable, this, _2)); } +LLIMConversation::~LLIMConversation() +{ + if (mParticipantList) + { + delete mParticipantList; + mParticipantList = NULL; + } +} + BOOL LLIMConversation::postBuild() { mCloseBtn = getChild<LLButton>("close_btn"); @@ -71,19 +82,12 @@ BOOL LLIMConversation::postBuild() mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this)); - if (mControlPanel) - { - mControlPanel->setSessionId(mSessionID); - mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel")); - - mExpandCollapseBtn->setImageOverlay( - getString(mControlPanel->getParent()->getVisible() ? "collapse_icon" : "expand_icon")); - } - else - { - mExpandCollapseBtn->setEnabled(false); - getChild<LLLayoutPanel>("im_control_panel_holder")->setVisible(false); - } + mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); + mParticipantListPanel->setVisible( + mIsNearbyChat? false : gSavedSettings.getBOOL("IMShowControlPanel")); + mExpandCollapseBtn->setImageOverlay( + getString(mParticipantListPanel->getVisible() ? "collapse_icon" : "expand_icon")); + mExpandCollapseBtn->setEnabled(!mIsP2PChat); mTearOffBtn = getChild<LLButton>("tear_off_btn"); mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); @@ -93,6 +97,8 @@ BOOL LLIMConversation::postBuild() setOpenPositioning(LLFloaterEnums::OPEN_POSITIONING_NONE); } + buildParticipantList(); + if (isChatMultiTab()) { return LLFloater::postBuild(); @@ -104,6 +110,47 @@ BOOL LLIMConversation::postBuild() } +BOOL LLIMConversation::tick() +{ + // Need to resort the participant list if it's in sort by recent speaker order. + if (mParticipantList) + { + mParticipantList->update(); + } + + return false; +} + +void LLIMConversation::buildParticipantList() +{ if (mIsNearbyChat) + { + } + else + { + // for group and Ad-hoc chat we need to include agent into list + if(!mIsP2PChat && !mParticipantList && mSessionID.notNull()) + { + LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false); + } + } +} + +void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata) +{ + // TODO: Check this code when when sort order menu will be added. (EM) + if (true || !mParticipantList) + return; + + std::string chosen_item = userdata.asString(); + + if (chosen_item == "sort_name") + { + mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME); + } + +} + void LLIMConversation::onIMSessionMenuItemClicked(const LLSD& userdata) { std::string item = userdata.asString(); @@ -162,11 +209,11 @@ void LLIMConversation::updateHeaderAndToolbar() } bool is_control_panel_visible = false; - if (mControlPanel) + if (!mIsP2PChat) { // Control panel should be visible only in torn off floaters. is_control_panel_visible = !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel"); - mControlPanel->getParent()->setVisible(is_control_panel_visible); + mParticipantListPanel->setVisible(is_control_panel_visible); } // Display collapse image (<<) if the floater is hosted @@ -215,10 +262,10 @@ void LLIMConversation::processChatHistoryStyleUpdate() } } - LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); - if (nearby_chat_bar) + LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); + if (nearby_chat) { - nearby_chat_bar->reloadMessages(); + nearby_chat->reloadMessages(); } } @@ -240,12 +287,12 @@ void LLIMConversation::onSlide(LLIMConversation* self) } else ///< floater is torn off { - if (self->mControlPanel) + if (!self->mIsP2PChat) { - bool expand = !self->mControlPanel->getParent()->getVisible(); + bool expand = !self->mParticipantListPanel->getVisible(); // Expand/collapse the IM control panel - self->mControlPanel->getParent()->setVisible(expand); + self->mParticipantListPanel->setVisible(expand); gSavedSettings.setBOOL("IMShowControlPanel", expand); diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 501977e061..d31ae0808a 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -28,19 +28,24 @@ #ifndef LL_IMCONVERSATION_H #define LL_IMCONVERSATION_H +#include "lllayoutstack.h" +#include "llparticipantlist.h" #include "lltransientdockablefloater.h" #include "llviewercontrol.h" +#include "lleventtimer.h" class LLPanelChatControlPanel; class LLIMConversation : public LLTransientDockableFloater + , public LLEventTimer { public: LOG_CLASS(LLIMConversation); LLIMConversation(const LLUUID& session_id); + ~LLIMConversation(); // reload all message with new settings of visual modes static void processChatHistoryStyleUpdate(); @@ -75,13 +80,16 @@ protected: // set the enable/disable state for the Call button virtual void enableDisableCallBtn() = 0; -// /* virtual */ void updateTitleButtons(); + void buildParticipantList(); + void onSortMenuItemClicked(const LLSD& userdata); + /*virtual*/ BOOL tick(); - LLPanelChatControlPanel* mControlPanel; bool mIsNearbyChat; bool mIsP2PChat; + LLLayoutPanel* mParticipantListPanel; + LLParticipantList* mParticipantList; LLUUID mSessionID; LLButton* mExpandCollapseBtn; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 5339bcb936..c99da9e9c1 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -44,7 +44,6 @@ //#include "lllayoutstack.h" #include "lllineeditor.h" #include "lllogchat.h" -#include "llpanelimcontrolpanel.h" #include "llscreenchannel.h" #include "llsyswellwindow.h" #include "lltrans.h" @@ -82,29 +81,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) { mIsP2PChat = mSession->isP2PSessionType(); mSessionInitialized = mSession->mSessionInitialized; - mDialog = mSession->mType; - switch (mDialog) - { - case IM_SESSION_CONFERENCE_START: - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); - break; - case IM_SESSION_GROUP_START: - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); - break; - case IM_SESSION_INVITE: - if (gAgent.isInGroup(mSessionID)) - { - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); - } - else - { - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); - } - break; - default: - break; - } } setOverlapsScreenChannel(true); @@ -113,24 +90,6 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) setDocked(true); } -// static -void* LLIMFloater::createPanelGroupControl(void* userdata) -{ - LLIMFloater *self = (LLIMFloater*) userdata; - self->mControlPanel = new LLPanelGroupControlPanel(self->mSessionID); - self->mControlPanel->setXMLFilename("panel_group_control_panel.xml"); - return self->mControlPanel; -} - -// static -void* LLIMFloater::createPanelAdHocControl(void* userdata) -{ - LLIMFloater *self = (LLIMFloater*) userdata; - self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID); - self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml"); - return self->mControlPanel; -} - void LLIMFloater::onFocusLost() { LLIMModel::getInstance()->resetActiveSessionID(); @@ -409,8 +368,10 @@ void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id, } // virtual -void LLIMFloater::draw() +BOOL LLIMFloater::tick() { + BOOL parents_retcode = LLIMConversation::tick(); + if ( mMeTyping ) { // Time out if user hasn't typed for a while. @@ -420,7 +381,7 @@ void LLIMFloater::draw() } } - LLTransientDockableFloater::draw(); + return parents_retcode; } //static @@ -643,16 +604,14 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) if (mSessionID != im_session_id) { mSessionID = im_session_id; - setKey(im_session_id); - if (mControlPanel) - { - mControlPanel->setSessionId(im_session_id); - } + boundVoiceChannel(); mSession = LLIMModel::getInstance()->findIMSession(mSessionID); mIsP2PChat = mSession && mSession->isP2PSessionType(); + + buildParticipantList(); } //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) @@ -841,10 +800,14 @@ void LLIMFloater::setTyping(bool typing) } } - LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if (speaker_mgr) - speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); - + if (!mIsNearbyChat) + { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); + } + } } void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index c7793f73eb..24f28c8aee 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -61,15 +61,15 @@ public: /*virtual*/ void setVisible(BOOL visible); /*virtual*/ BOOL getVisible(); // Check typing timeout timer. - /*virtual*/ void draw(); - - static void* createPanelGroupControl(void* userdata); - static void* createPanelAdHocControl(void* userdata); + /*virtual*/ BOOL tick(); static LLIMFloater* findInstance(const LLUUID& session_id); static LLIMFloater* getInstance(const LLUUID& session_id); static void addToHost(const LLUUID& session_id); + static void* createPanelGroupControl(void* userdata); + static void* createPanelAdHocControl(void* userdata); + // LLFloater overrides /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); @@ -147,7 +147,6 @@ private: static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); void setTyping(bool typing); - void onCallButtonClicked(); // set the enable/disable state for the Call button diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index f72ddef412..3b6240de44 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -31,7 +31,7 @@ #include "llfloaterreg.h" #include "lllayoutstack.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llagent.h" #include "llavatariconctrl.h" diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index c3ac1d32cb..46b1cb5f18 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -907,7 +907,7 @@ const LLUUID& LLIMModel::getOtherParticipantID(const LLUUID& session_id) const LLIMSession* session = findIMSession(session_id); if (!session) { - llwarns << "session " << session_id << "does not exist " << llendl; + llwarns << "session " << session_id << " does not exist " << llendl; return LLUUID::null; } @@ -2483,8 +2483,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess LLChat chat(message); chat.mSourceType = CHAT_SOURCE_SYSTEM; - LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); - LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); + LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); if(nearby_chat) { diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 497690d656..2d7095957e 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -1,8 +1,8 @@ /** * @file LLNearbyChat.cpp - * @brief Nearby chat history scrolling panel implementation + * @brief LLNearbyChat class implementation * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * @@ -25,34 +25,50 @@ */ #include "llviewerprecompiledheaders.h" -#include "llviewercontrol.h" -#include "llviewerwindow.h" -#include "llrootview.h" -//#include "llchatitemscontainerctrl.h" + +#include "message.h" + #include "lliconctrl.h" +#include "llappviewer.h" +#include "llfloaterreg.h" +#include "lltrans.h" +#include "llimfloatercontainer.h" #include "llfloatersidepanelcontainer.h" #include "llfocusmgr.h" #include "lllogchat.h" #include "llresizebar.h" #include "llresizehandle.h" +#include "lldraghandle.h" #include "llmenugl.h" -#include "llviewermenu.h"//for gMenuHolder - +#include "llviewermenu.h" // for gMenuHolder #include "llnearbychathandler.h" #include "llchannelmanager.h" - -#include "llagent.h" // gAgent #include "llchathistory.h" #include "llstylemap.h" - #include "llavatarnamecache.h" - -#include "lldraghandle.h" - -#include "llnearbychatbar.h" #include "llfloaterreg.h" #include "lltrans.h" +#include "llfirstuse.h" +#include "llnearbychat.h" +#include "llagent.h" // gAgent +#include "llgesturemgr.h" +#include "llmultigesture.h" +#include "llkeyboard.h" +#include "llanimationstates.h" +#include "llviewerstats.h" +#include "llcommandhandler.h" +#include "llviewercontrol.h" +#include "llnavigationbar.h" +#include "llwindow.h" +#include "llviewerwindow.h" +#include "llrootview.h" +#include "llviewerchat.h" +#include "lltranslate.h" + +S32 LLNearbyChat::sLastSpecialChatChannel = 0; + + // --- 2 functions in the global namespace :( --- bool isWordsName(const std::string& name) { @@ -88,90 +104,83 @@ std::string appendTime() return timeStr; } -static const S32 RESIZE_BAR_THICKNESS = 3; -static LLRegisterPanelClassWrapper<LLNearbyChat> t_panel_nearby_chat("panel_nearby_chat"); +const S32 EXPANDED_HEIGHT = 266; +const S32 COLLAPSED_HEIGHT = 60; +const S32 EXPANDED_MIN_HEIGHT = 150; -LLNearbyChat::LLNearbyChat(const LLNearbyChat::Params& p) - : LLPanel(p), - mChatHistory(NULL) -{ -} +// legacy callback glue +void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); -BOOL LLNearbyChat::postBuild() -{ - //menu - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; +struct LLChatTypeTrigger { + std::string name; + EChatType type; +}; - enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); - registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); +static LLChatTypeTrigger sChatTypeTriggers[] = { + { "/whisper" , CHAT_TYPE_WHISPER}, + { "/shout" , CHAT_TYPE_SHOUT} +}; - - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(menu) - mPopupMenuHandle = menu->getHandle(); - gSavedSettings.declareS32("nearbychat_showicons_and_names",2,"NearByChat header settings",true); +LLNearbyChat::LLNearbyChat(const LLSD& key) +: LLIMConversation(key), + mChatBox(NULL), + mChatHistory(NULL), + mOutputMonitor(NULL), + mSpeakerMgr(NULL), + mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) +{ + mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); +} - mChatHistory = getChild<LLChatHistory>("chat_history"); +//virtual +BOOL LLNearbyChat::postBuild() +{ + mChatBox = getChild<LLLineEditor>("chat_editor"); - return LLPanel::postBuild(); -} + mChatBox->setCommitCallback(boost::bind(&LLNearbyChat::onChatBoxCommit, this)); + mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this); + mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); + mChatBox->setFocusReceivedCallback(boost::bind(&LLNearbyChat::onChatBoxFocusReceived, this)); + mChatBox->setIgnoreArrowKeys( FALSE ); + mChatBox->setCommitOnFocusLost( FALSE ); + mChatBox->setRevertOnEsc( FALSE ); + mChatBox->setIgnoreTab(TRUE); + mChatBox->setPassDelete(TRUE); + mChatBox->setReplaceNewlinesWithSpaces(FALSE); + mChatBox->setEnableLineHistory(TRUE); + mChatBox->setFont(LLViewerChat::getChatFont()); + mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); + mOutputMonitor->setVisible(FALSE); -void LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args) -{ - LLChat& tmp_chat = const_cast<LLChat&>(chat); + // Register for font change notifications + LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChat::onChatFontChange, this, _1)); - if(tmp_chat.mTimeStr.empty()) - tmp_chat.mTimeStr = appendTime(); + enableResizeCtrls(true, true, false); - if (!chat.mMuted) - { - tmp_chat.mFromName = chat.mFromName; - LLSD chat_args; - if (args) chat_args = args; - chat_args["use_plain_text_chat_history"] = - gSavedSettings.getBOOL("PlainTextChatHistory"); - chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); - chat_args["show_names_for_p2p_conv"] = true; + addToHost(); - mChatHistory->appendMessage(chat, chat_args); - } -} + //for menu + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; -void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) -{ - appendMessage(chat, args); + enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); + registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); - if(archive) + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if(menu) { - mMessageArchive.push_back(chat); - if(mMessageArchive.size()>200) - mMessageArchive.erase(mMessageArchive.begin()); + mPopupMenuHandle = menu->getHandle(); } - // logging - if (!args["do_not_log"].asBoolean() - && gSavedPerAccountSettings.getBOOL("LogNearbyChat")) - { - std::string from_name = chat.mFromName; - - if (chat.mSourceType == CHAT_SOURCE_AGENT) - { - // if the chat is coming from an agent, log the complete name - LLAvatarName av_name; - LLAvatarNameCache::get(chat.mFromID, &av_name); + // obsolete, but may be needed for backward compatibility? + gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); - if (!av_name.mIsDisplayNameDefault) - { - from_name = av_name.getCompleteName(); - } - } + mChatHistory = getChild<LLChatHistory>("chat_history"); - LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText); - } + return LLIMConversation::postBuild();; } void LLNearbyChat::onNearbySpeakers() @@ -189,33 +198,40 @@ bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata) { std::string str = userdata.asString(); if(str == "nearby_people") - onNearbySpeakers(); + onNearbySpeakers(); return false; } -void LLNearbyChat::removeScreenChat() +void LLNearbyChat::getAllowedRect(LLRect& rect) { - LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); - if(chat_channel) - { - chat_channel->removeToastsFromChannel(); - } + rect = gViewerWindow->getWorldViewRectScaled(); } - -void LLNearbyChat::setVisible(BOOL visible) +//////////////////////////////////////////////////////////////////////////////// +// +void LLNearbyChat::onFocusReceived() { - if(visible) - { - removeScreenChat(); - } - - LLPanel::setVisible(visible); + setBackgroundOpaque(true); + LLIMConversation::onFocusReceived(); } +//////////////////////////////////////////////////////////////////////////////// +// +void LLNearbyChat::onFocusLost() +{ + setBackgroundOpaque(false); + LLIMConversation::onFocusLost(); +} -void LLNearbyChat::getAllowedRect(LLRect& rect) +BOOL LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask) { - rect = gViewerWindow->getWorldViewRectScaled(); + //fix for EXT-6625 + //highlight NearbyChat history whenever mouseclick happen in NearbyChat + //setting focus to eidtor will force onFocusLost() call that in its turn will change + //background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. + + if(mChatHistory) + mChatHistory->setFocus(TRUE); + return LLPanel::handleMouseDown(x, y, mask); } void LLNearbyChat::reloadMessages() @@ -265,9 +281,9 @@ void LLNearbyChat::loadHistory() chat.mSourceType = CHAT_SOURCE_AGENT; if (from_id.isNull() && SYSTEM_FROM == from) - { + { chat.mSourceType = CHAT_SOURCE_SYSTEM; - + } else if (from_id.isNull()) { @@ -280,43 +296,117 @@ void LLNearbyChat::loadHistory() } } -//static -LLNearbyChat* LLNearbyChat::getInstance() +void LLNearbyChat::removeScreenChat() { - LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); - return chat_bar->findChild<LLNearbyChat>("nearby_chat"); + LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); + if(chat_channel) + { + chat_channel->removeToastsFromChannel(); + } } -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusReceived() +void LLNearbyChat::setVisible(BOOL visible) { - setBackgroundOpaque(true); - LLPanel::onFocusReceived(); + if(visible) + { + removeScreenChat(); + } + + LLIMConversation::setVisible(visible); } -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusLost() +void LLNearbyChat::onCallButtonClicked() { - setBackgroundOpaque(false); - LLPanel::onFocusLost(); + LLAgent::toggleMicrophone(NULL); } -BOOL LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask) +void LLNearbyChat::enableDisableCallBtn() { - //fix for EXT-6625 - //highlight NearbyChat history whenever mouseclick happen in NearbyChat - //setting focus to eidtor will force onFocusLost() call that in its turn will change - //background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. + // bool btn_enabled = LLAgent::isActionAllowed("speak"); + + getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/); +} + +void LLNearbyChat::addToHost() +{ + if (LLIMConversation::isChatMultiTab()) + { + LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + + if (im_box) + { + im_box->addFloater(this, FALSE, LLTabContainer::END); + } + } +} + +// virtual +void LLNearbyChat::onOpen(const LLSD& key) +{ + LLIMConversation::onOpen(key); + showTranslationCheckbox(LLTranslate::isTranslationConfigured()); +} + +bool LLNearbyChat::applyRectControl() +{ + bool rect_controlled = LLFloater::applyRectControl(); + +/* if (!mNearbyChat->getVisible()) + { + reshape(getRect().getWidth(), getMinHeight()); + enableResizeCtrls(true, true, false); + } + else + {*/ + enableResizeCtrls(true); + setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); +// } - if(mChatHistory) - mChatHistory->setFocus(TRUE); - return LLPanel::handleMouseDown(x, y, mask); + return rect_controlled; +} + +void LLNearbyChat::onChatFontChange(LLFontGL* fontp) +{ + // Update things with the new font whohoo + if (mChatBox) + { + mChatBox->setFont(fontp); + } +} + +//static +LLNearbyChat* LLNearbyChat::getInstance() +{ + return LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar"); +} + +//static +//LLNearbyChat* LLNearbyChat::findInstance() +//{ +// return LLFloaterReg::findTypedInstance<LLNearbyChat>("chat_bar"); +//} + +void LLNearbyChat::showHistory() +{ + openFloater(); + setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); + reshape(getRect().getWidth(), mExpandedHeight); + enableResizeCtrls(true); + storeRectControl(); } -void LLNearbyChat::draw() +void LLNearbyChat::showTranslationCheckbox(BOOL show) { + getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(show); +} + +BOOL LLNearbyChat::tick() +{ + BOOL parents_retcode = LLIMConversation::tick(); + + displaySpeakingIndicator(); + updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); + // *HACK: Update transparency type depending on whether our children have focus. // This is needed because this floater is chrome and thus cannot accept focus, so // the transparency type setting code from LLFloater::setFocus() isn't reached. @@ -325,5 +415,511 @@ void LLNearbyChat::draw() setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE); } - LLPanel::draw(); + return parents_retcode; } + +std::string LLNearbyChat::getCurrentChat() +{ + return mChatBox ? mChatBox->getText() : LLStringUtil::null; +} + +// virtual +BOOL LLNearbyChat::handleKeyHere( KEY key, MASK mask ) +{ + BOOL handled = FALSE; + + if( KEY_RETURN == key && mask == MASK_CONTROL) + { + // shout + sendChat(CHAT_TYPE_SHOUT); + handled = TRUE; + } + + return handled; +} + +BOOL LLNearbyChat::matchChatTypeTrigger(const std::string& in_str, std::string* out_str) +{ + U32 in_len = in_str.length(); + S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); + + bool string_was_found = false; + + for (S32 n = 0; n < cnt && !string_was_found; n++) + { + if (in_len <= sChatTypeTriggers[n].name.length()) + { + std::string trigger_trunc = sChatTypeTriggers[n].name; + LLStringUtil::truncate(trigger_trunc, in_len); + + if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) + { + *out_str = sChatTypeTriggers[n].name; + string_was_found = true; + } + } + } + + return string_was_found; +} + +void LLNearbyChat::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) +{ + LLFirstUse::otherAvatarChatFirst(false); + + LLNearbyChat* self = (LLNearbyChat *)userdata; + + LLWString 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 (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) + { + 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); + } + else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) + { + 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 + self->mChatBox->setCursorToEnd(); + } + + //llinfos << "GESTUREDEBUG " << trigger + // << " len " << length + // << " outlen " << out_str.getLength() + // << llendl; + } +} + +// static +void LLNearbyChat::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) +{ + // stop typing animation + gAgent.stopTyping(); +} + +void LLNearbyChat::onChatBoxFocusReceived() +{ + mChatBox->setEnabled(!gDisconnected); +} + +EChatType LLNearbyChat::processChatTypeTriggers(EChatType type, std::string &str) +{ + U32 length = str.length(); + S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); + + for (S32 n = 0; n < cnt; n++) + { + if (length >= sChatTypeTriggers[n].name.length()) + { + std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length()); + + if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name)) + { + U32 trigger_length = sChatTypeTriggers[n].name.length(); + + // It's to remove space after trigger name + if (length > trigger_length && str[trigger_length] == ' ') + trigger_length++; + + str = str.substr(trigger_length, length); + + if (CHAT_TYPE_NORMAL == type) + return sChatTypeTriggers[n].type; + else + break; + } + } + } + + return type; +} + +void LLNearbyChat::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 + LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); + } + else + { + utf8_revised_text = utf8text; + } + + utf8_revised_text = utf8str_trim(utf8_revised_text); + + type = processChatTypeTriggers(type, 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 LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args) +{ + LLChat& tmp_chat = const_cast<LLChat&>(chat); + + if(tmp_chat.mTimeStr.empty()) + tmp_chat.mTimeStr = appendTime(); + + if (!chat.mMuted) + { + tmp_chat.mFromName = chat.mFromName; + LLSD chat_args; + if (args) chat_args = args; + chat_args["use_plain_text_chat_history"] = + gSavedSettings.getBOOL("PlainTextChatHistory"); + chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); + chat_args["show_names_for_p2p_conv"] = true; + + mChatHistory->appendMessage(chat, chat_args); + } +} + +void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +{ + appendMessage(chat, args); + + if(archive) + { + mMessageArchive.push_back(chat); + if(mMessageArchive.size()>200) + mMessageArchive.erase(mMessageArchive.begin()); + } + + // logging + if (!args["do_not_log"].asBoolean() + && gSavedPerAccountSettings.getBOOL("LogNearbyChat")) + { + std::string from_name = chat.mFromName; + + if (chat.mSourceType == CHAT_SOURCE_AGENT) + { + // if the chat is coming from an agent, log the complete name + LLAvatarName av_name; + LLAvatarNameCache::get(chat.mFromID, &av_name); + + if (!av_name.mIsDisplayNameDefault) + { + from_name = av_name.getCompleteName(); + } + } + + LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText); + } +} + + +void LLNearbyChat::onChatBoxCommit() +{ + if (mChatBox->getText().length() > 0) + { + sendChat(CHAT_TYPE_NORMAL); + } + + gAgent.stopTyping(); +} + +void LLNearbyChat::displaySpeakingIndicator() +{ + LLSpeakerMgr::speaker_list_t speaker_list; + LLUUID id; + + id.setNull(); + mSpeakerMgr->update(TRUE); + mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); + + for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) + { + LLPointer<LLSpeaker> s = *i; + if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) + { + id = s->mID; + break; + } + } + + if (!id.isNull()) + { + mOutputMonitor->setVisible(TRUE); + mOutputMonitor->setSpeakerId(id); + } + else + { + mOutputMonitor->setVisible(FALSE); + } +} + +void LLNearbyChat::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) +{ + sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate); +} + +void LLNearbyChat::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 LLNearbyChat::startChat(const char* line) +{ + LLNearbyChat* cb = LLNearbyChat::getInstance(); + + if (cb ) + { + cb->setVisible(TRUE); + cb->setFocus(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 LLNearbyChat::stopChat() +{ + LLNearbyChat* cb = LLNearbyChat::getInstance(); + + if (cb) + { + 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 LLNearbyChat::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 LLChatCommandHandler : public LLCommandHandler +{ +public: + // not allowed from outside the app + LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } + + // Your code here + bool handle(const LLSD& tokens, const LLSD& query_map, + LLMediaCtrl* web) + { + bool retval = false; + // Need at least 2 tokens to have a valid message. + if (tokens.size() < 2) + { + retval = false; + } + else + { + S32 channel = tokens[0].asInteger(); + // VWR-19499 Restrict function to chat channels greater than 0. + if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG)) + { + retval = true; + // Send unescaped message, see EXT-6353. + std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); + send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); + } + else + { + retval = false; + // Tell us this is an unsupported SLurl. + } + } + return retval; + } +}; + +// Creating the object registers with the dispatcher. +LLChatCommandHandler gChatHandler; diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 62a41c17cb..b38111defa 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -1,8 +1,8 @@ - /** +/** * @file llnearbychat.h - * @brief nearby chat history scrolling panel implementation + * @brief LLNearbyChat class definition * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * @@ -24,9 +24,16 @@ * $/LicenseInfo$ */ -#ifndef LL_LLNEARBYCHAT_H_ -#define LL_LLNEARBYCHAT_H_ +#ifndef LL_LLNEARBYCHAT_H +#define LL_LLNEARBYCHAT_H +#include "llimconversation.h" +#include "llcombobox.h" +#include "llgesturemgr.h" +#include "llchat.h" +#include "llvoiceclient.h" +#include "lloutputmonitorctrl.h" +#include "llspeakers.h" #include "llscrollbar.h" #include "llviewerchat.h" #include "llpanel.h" @@ -35,32 +42,88 @@ class LLResizeBar; class LLChatHistory; class LLNearbyChat - : public LLPanel + : public LLIMConversation { public: - LLNearbyChat(const Params& p = LLPanel::getDefaultParams()); + // constructor for inline chat-bars (e.g. hosted in chat history window) + LLNearbyChat(const LLSD& key); + ~LLNearbyChat() {} - BOOL postBuild (); - - /** @param archive true - to save a message to the chat history log */ - void addMessage (const LLChat& message,bool archive = true, const LLSD &args = LLSD()); - void onNearbyChatContextMenuItemClicked(const LLSD& userdata); - bool onNearbyChatCheckContextMenuItem(const LLSD& userdata); - - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual void draw(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); // focus overrides /*virtual*/ void onFocusLost(); /*virtual*/ void onFocusReceived(); - + /*virtual*/ void setVisible(BOOL visible); - + void loadHistory(); void reloadMessages(); - static LLNearbyChat* getInstance(); void removeScreenChat(); + static LLNearbyChat* getInstance(); + + void addToHost(); + + /** @param archive true - to save a message to the chat history log */ + void addMessage (const LLChat& message,bool archive = true, const LLSD &args = LLSD()); + void onNearbyChatContextMenuItemClicked(const LLSD& userdata); + bool onNearbyChatCheckContextMenuItem(const LLSD& userdata); + + LLLineEditor* getChatBox() { return mChatBox; } + + //virtual void draw(); + + std::string getCurrentChat(); + + virtual BOOL handleKeyHere( KEY key, MASK mask ); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + + 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); + + void showHistory(); + void showTranslationCheckbox(BOOL show); + +protected: + static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); + static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata); + static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); + void onChatBoxFocusReceived(); + + void sendChat( EChatType type ); + void onChatBoxCommit(); + void onChatFontChange(LLFontGL* fontp); + + /* virtual */ bool applyRectControl(); + + void onToggleNearbyChatPanel(); + + static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); + EChatType processChatTypeTriggers(EChatType type, std::string &str); + + void displaySpeakingIndicator(); + + void onCallButtonClicked(); + + // set the enable/disable state for the Call button + virtual void enableDisableCallBtn(); + + // Which non-zero channel did we last chat on? + static S32 sLastSpecialChatChannel; + + LLLineEditor* mChatBox; + LLOutputMonitorCtrl* mOutputMonitor; + LLLocalSpeakerMgr* mSpeakerMgr; + + S32 mExpandedHeight; + + /*virtual*/ BOOL tick(); + private: void getAllowedRect (LLRect& rect); @@ -68,14 +131,10 @@ private: void appendMessage(const LLChat& chat, const LLSD &args = 0); void onNearbySpeakers (); - -private: LLHandle<LLView> mPopupMenuHandle; + std::vector<LLChat> mMessageArchive; LLChatHistory* mChatHistory; - std::vector<LLChat> mMessageArchive; }; #endif - - diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp deleted file mode 100644 index 68934be11a..0000000000 --- a/indra/newview/llnearbychatbar.cpp +++ /dev/null @@ -1,709 +0,0 @@ -/** - * @file llnearbychatbar.cpp - * @brief LLNearbyChatBar class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "message.h" - -#include "llappviewer.h" -#include "llfloaterreg.h" -#include "lltrans.h" -#include "llimfloatercontainer.h" -#include "llfirstuse.h" -#include "llnearbychatbar.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" -#include "llnavigationbar.h" -#include "llwindow.h" -#include "llviewerwindow.h" -#include "llrootview.h" -#include "llviewerchat.h" -#include "llnearbychat.h" -#include "lltranslate.h" - -#include "llresizehandle.h" - -S32 LLNearbyChatBar::sLastSpecialChatChannel = 0; - -const S32 EXPANDED_HEIGHT = 266; -const S32 COLLAPSED_HEIGHT = 60; -const S32 EXPANDED_MIN_HEIGHT = 150; - -// legacy callback glue -void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); - -struct LLChatTypeTrigger { - std::string name; - EChatType type; -}; - -static LLChatTypeTrigger sChatTypeTriggers[] = { - { "/whisper" , CHAT_TYPE_WHISPER}, - { "/shout" , CHAT_TYPE_SHOUT} -}; - -LLNearbyChatBar::LLNearbyChatBar(const LLSD& key) -: LLIMConversation(key), - mChatBox(NULL), - mNearbyChat(NULL), - mOutputMonitor(NULL), - mSpeakerMgr(NULL), - mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) -{ - mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); -} - -//virtual -BOOL LLNearbyChatBar::postBuild() -{ - mChatBox = getChild<LLLineEditor>("chat_box"); - - mChatBox->setCommitCallback(boost::bind(&LLNearbyChatBar::onChatBoxCommit, this)); - mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this); - mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); - mChatBox->setFocusReceivedCallback(boost::bind(&LLNearbyChatBar::onChatBoxFocusReceived, this)); - - mChatBox->setIgnoreArrowKeys( FALSE ); - mChatBox->setCommitOnFocusLost( FALSE ); - mChatBox->setRevertOnEsc( FALSE ); - mChatBox->setIgnoreTab(TRUE); - mChatBox->setPassDelete(TRUE); - mChatBox->setReplaceNewlinesWithSpaces(FALSE); - mChatBox->setEnableLineHistory(TRUE); - mChatBox->setFont(LLViewerChat::getChatFont()); - - mNearbyChat = getChildView("nearby_chat"); - - LLUICtrl* show_btn = getChild<LLUICtrl>("show_nearby_chat"); - show_btn->setCommitCallback(boost::bind(&LLNearbyChatBar::onToggleNearbyChatPanel, this)); - - mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); - mOutputMonitor->setVisible(FALSE); - - gSavedSettings.declareBOOL("nearbychat_history_visibility", mNearbyChat->getVisible(), "Visibility state of nearby chat history", TRUE); - - mNearbyChat->setVisible(gSavedSettings.getBOOL("nearbychat_history_visibility")); - - // Register for font change notifications - LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChatBar::onChatFontChange, this, _1)); - - enableResizeCtrls(true, true, false); - - addToHost(); - - return LLIMConversation::postBuild();; -} - -void LLNearbyChatBar::enableDisableCallBtn() -{ - // bool btn_enabled = LLAgent::isActionAllowed("speak"); - - getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/); -} - -void LLNearbyChatBar::addToHost() -{ - if (LLIMConversation::isChatMultiTab()) - { - LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); - - if (im_box) - { - im_box->addFloater(this, FALSE, LLTabContainer::END); - } - } -} - -// virtual -void LLNearbyChatBar::onOpen(const LLSD& key) -{ - LLIMConversation::onOpen(key); - showTranslationCheckbox(LLTranslate::isTranslationConfigured()); -} - -bool LLNearbyChatBar::applyRectControl() -{ - bool rect_controlled = LLFloater::applyRectControl(); - - if (!mNearbyChat->getVisible()) - { - reshape(getRect().getWidth(), getMinHeight()); - enableResizeCtrls(true, true, false); - } - else - { - enableResizeCtrls(true); - setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); - } - - return rect_controlled; -} - -void LLNearbyChatBar::onChatFontChange(LLFontGL* fontp) -{ - // Update things with the new font whohoo - if (mChatBox) - { - mChatBox->setFont(fontp); - } -} - -//static -LLNearbyChatBar* LLNearbyChatBar::getInstance() -{ - return LLFloaterReg::getTypedInstance<LLNearbyChatBar>("chat_bar"); -} - -//static -//LLNearbyChatBar* LLNearbyChatBar::findInstance() -//{ -// return LLFloaterReg::findTypedInstance<LLNearbyChatBar>("chat_bar"); -//} - -void LLNearbyChatBar::showHistory() -{ - openFloater(); - - if (!getChildView("nearby_chat")->getVisible()) - { - onToggleNearbyChatPanel(); - } -} - -void LLNearbyChatBar::showTranslationCheckbox(BOOL show) -{ - getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(show); -} - -void LLNearbyChatBar::draw() -{ - displaySpeakingIndicator(); - updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); - LLIMConversation::draw(); -} - -std::string LLNearbyChatBar::getCurrentChat() -{ - return mChatBox ? mChatBox->getText() : LLStringUtil::null; -} - -// virtual -BOOL LLNearbyChatBar::handleKeyHere( KEY key, MASK mask ) -{ - BOOL handled = FALSE; - - if( KEY_RETURN == key && mask == MASK_CONTROL) - { - // shout - sendChat(CHAT_TYPE_SHOUT); - handled = TRUE; - } - - return handled; -} - -BOOL LLNearbyChatBar::matchChatTypeTrigger(const std::string& in_str, std::string* out_str) -{ - U32 in_len = in_str.length(); - S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); - - bool string_was_found = false; - - for (S32 n = 0; n < cnt && !string_was_found; n++) - { - if (in_len <= sChatTypeTriggers[n].name.length()) - { - std::string trigger_trunc = sChatTypeTriggers[n].name; - LLStringUtil::truncate(trigger_trunc, in_len); - - if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) - { - *out_str = sChatTypeTriggers[n].name; - string_was_found = true; - } - } - } - - return string_was_found; -} - -void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) -{ - LLFirstUse::otherAvatarChatFirst(false); - - LLNearbyChatBar* self = (LLNearbyChatBar *)userdata; - - LLWString 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 (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) - { - 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); - } - else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) - { - 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 - self->mChatBox->setCursorToEnd(); - } - - //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::onChatBoxFocusReceived() -{ - mChatBox->setEnabled(!gDisconnected); -} - -EChatType LLNearbyChatBar::processChatTypeTriggers(EChatType type, std::string &str) -{ - U32 length = str.length(); - S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); - - for (S32 n = 0; n < cnt; n++) - { - if (length >= sChatTypeTriggers[n].name.length()) - { - std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length()); - - if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name)) - { - U32 trigger_length = sChatTypeTriggers[n].name.length(); - - // It's to remove space after trigger name - if (length > trigger_length && str[trigger_length] == ' ') - trigger_length++; - - str = str.substr(trigger_length, length); - - if (CHAT_TYPE_NORMAL == type) - return sChatTypeTriggers[n].type; - else - break; - } - } - } - - return type; -} - -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 - LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); - } - else - { - utf8_revised_text = utf8text; - } - - utf8_revised_text = utf8str_trim(utf8_revised_text); - - type = processChatTypeTriggers(type, 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::onToggleNearbyChatPanel() -{ - LLView* nearby_chat = getChildView("nearby_chat"); - - if (nearby_chat->getVisible()) - { - if (!isMinimized()) - { - mExpandedHeight = getRect().getHeight(); - } - setResizeLimits(getMinWidth(), COLLAPSED_HEIGHT); - nearby_chat->setVisible(FALSE); - reshape(getRect().getWidth(), COLLAPSED_HEIGHT); - enableResizeCtrls(true, true, false); - storeRectControl(); - } - else - { - nearby_chat->setVisible(TRUE); - setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); - reshape(getRect().getWidth(), mExpandedHeight); - enableResizeCtrls(true); - storeRectControl(); - } - - gSavedSettings.setBOOL("nearbychat_history_visibility", mNearbyChat->getVisible()); -} - -void LLNearbyChatBar::reloadMessages() -{ - LLNearbyChat::getInstance()->reloadMessages(); -} - -void LLNearbyChatBar::setMinimized(BOOL b) -{ - LLNearbyChat* nearby_chat = getChild<LLNearbyChat>("nearby_chat"); - // when unminimizing with nearby chat visible, go ahead and kill off screen chats - if (!b && nearby_chat->getVisible()) - { - nearby_chat->removeScreenChat(); - } - LLFloater::setMinimized(b); -} - -void LLNearbyChatBar::onChatBoxCommit() -{ - if (mChatBox->getText().length() > 0) - { - sendChat(CHAT_TYPE_NORMAL); - } - - gAgent.stopTyping(); -} - -void LLNearbyChatBar::displaySpeakingIndicator() -{ - LLSpeakerMgr::speaker_list_t speaker_list; - LLUUID id; - - id.setNull(); - mSpeakerMgr->update(TRUE); - mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); - - for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) - { - LLPointer<LLSpeaker> s = *i; - if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) - { - id = s->mID; - break; - } - } - - if (!id.isNull()) - { - mOutputMonitor->setVisible(TRUE); - mOutputMonitor->setSpeakerId(id); - } - else - { - mOutputMonitor->setVisible(FALSE); - } -} - -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) -{ - LLNearbyChatBar* cb = LLNearbyChatBar::getInstance(); - - if (cb ) - { - cb->setVisible(TRUE); - cb->setFocus(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() -{ - LLNearbyChatBar* cb = LLNearbyChatBar::getInstance(); - - if (cb) - { - 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 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 LLChatCommandHandler : public LLCommandHandler -{ -public: - // not allowed from outside the app - LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } - - // Your code here - bool handle(const LLSD& tokens, const LLSD& query_map, - LLMediaCtrl* web) - { - bool retval = false; - // Need at least 2 tokens to have a valid message. - if (tokens.size() < 2) - { - retval = false; - } - else - { - S32 channel = tokens[0].asInteger(); - // VWR-19499 Restrict function to chat channels greater than 0. - if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG)) - { - retval = true; - // Send unescaped message, see EXT-6353. - std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); - send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); - } - else - { - retval = false; - // Tell us this is an unsupported SLurl. - } - } - return retval; - } -}; - -// Creating the object registers with the dispatcher. -LLChatCommandHandler gChatHandler; - - diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h deleted file mode 100644 index b7c4c993c6..0000000000 --- a/indra/newview/llnearbychatbar.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file llnearbychatbar.h - * @brief LLNearbyChatBar class definition - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLNEARBYCHATBAR_H -#define LL_LLNEARBYCHATBAR_H - -#include "llimconversation.h" -#include "llcombobox.h" -#include "llgesturemgr.h" -#include "llchat.h" -#include "llnearbychat.h" -#include "llvoiceclient.h" -#include "lloutputmonitorctrl.h" -#include "llspeakers.h" - -class LLNearbyChatBar : public LLIMConversation -{ -public: - // constructor for inline chat-bars (e.g. hosted in chat history window) - LLNearbyChatBar(const LLSD& key); - ~LLNearbyChatBar() {} - - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onOpen(const LLSD& key); - - static LLNearbyChatBar* getInstance(); -// static LLNearbyChatBar* findInstance(); - - void addToHost(); - - void reloadMessages(); - LLLineEditor* getChatBox() { return mChatBox; } - - virtual void draw(); - - std::string getCurrentChat(); - virtual BOOL handleKeyHere( KEY key, MASK mask ); - - 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); - - void showHistory(); - void showTranslationCheckbox(BOOL show); - /*virtual*/void setMinimized(BOOL b); - -protected: - static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); - static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata); - static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); - void onChatBoxFocusReceived(); - - void sendChat( EChatType type ); - void onChatBoxCommit(); - void onChatFontChange(LLFontGL* fontp); - - /* virtual */ bool applyRectControl(); - - void onToggleNearbyChatPanel(); - - static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); - EChatType processChatTypeTriggers(EChatType type, std::string &str); - - void displaySpeakingIndicator(); - - // set the enable/disable state for the Call button - virtual void enableDisableCallBtn(); - - // Which non-zero channel did we last chat on? - static S32 sLastSpecialChatChannel; - - LLLineEditor* mChatBox; - LLView* mNearbyChat; - LLOutputMonitorCtrl* mOutputMonitor; - LLLocalSpeakerMgr* mSpeakerMgr; - - S32 mExpandedHeight; -}; - -#endif diff --git a/indra/newview/llnearbychatbarlistener.cpp b/indra/newview/llnearbychatbarlistener.cpp index a63e1fb76e..61815d1864 100644 --- a/indra/newview/llnearbychatbarlistener.cpp +++ b/indra/newview/llnearbychatbarlistener.cpp @@ -29,14 +29,14 @@ #include "llviewerprecompiledheaders.h" #include "llnearbychatbarlistener.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llagent.h" #include "llchat.h" -LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChatBar & chatbar) +LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChat & chatbar) : LLEventAPI("LLChatBar", "LLChatBar listener to (e.g.) sendChat, etc."), mChatbar(chatbar) diff --git a/indra/newview/llnearbychatbarlistener.h b/indra/newview/llnearbychatbarlistener.h index 9af9bc1f7b..0537275424 100644 --- a/indra/newview/llnearbychatbarlistener.h +++ b/indra/newview/llnearbychatbarlistener.h @@ -33,17 +33,17 @@ #include "lleventapi.h" class LLSD; -class LLNearbyChatBar; +class LLNearbyChat; class LLNearbyChatBarListener : public LLEventAPI { public: - LLNearbyChatBarListener(LLNearbyChatBar & chatbar); + LLNearbyChatBarListener(LLNearbyChat & chatbar); private: void sendChat(LLSD const & chat_data) const; - LLNearbyChatBar & mChatbar; + LLNearbyChat & mChatbar; }; #endif // LL_LLNEARBYCHATBARLISTENER_H diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index f26cc85019..e91a3fc334 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -40,7 +40,7 @@ #include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance #include "llviewerwindow.h"//for screen channel position -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llrootview.h" #include "lllayoutstack.h" @@ -487,9 +487,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, if(chat_msg.mText.empty()) return;//don't process empty messages - LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); - - LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); + LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); // Build notification data LLSD chat; @@ -558,8 +556,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, sChatWatcher->post(chat); - if( !chat_bar->isMinimized() - && nearby_chat->isInVisibleChain() + if( nearby_chat->isInVisibleChain() || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT && gSavedSettings.getBOOL("UseChatBubbles") ) || mChannel.isDead() diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index a1d5db2e27..507c6686fd 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -29,7 +29,7 @@ #include "llfloaterreg.h" #include "llnearbychat.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llnotificationhandler.h" #include "llnotifications.h" #include "lltoastnotifypanel.h" @@ -86,8 +86,7 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) // don't show toast if Nearby Chat is opened LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); - if (!nearby_chat_bar->isMinimized() && nearby_chat_bar->getVisible() && nearby_chat->getVisible()) + if (!nearby_chat->isMinimized() && nearby_chat->getVisible()) { return false; } diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index bc4097cd93..389baa86cd 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -41,85 +41,4 @@ #include "llspeakers.h" #include "lltrans.h" -LLPanelChatControlPanel::~LLPanelChatControlPanel() -{ -} -BOOL LLPanelChatControlPanel::postBuild() -{ - return TRUE; -} - -void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id) -{ - //Method is called twice for AdHoc and Group chat. Second time when server init reply received - mSessionId = session_id; -} - - -LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id): -mParticipantList(NULL) -{ -} - -BOOL LLPanelGroupControlPanel::postBuild() -{ - - return LLPanelChatControlPanel::postBuild(); -} - -LLPanelGroupControlPanel::~LLPanelGroupControlPanel() -{ - delete mParticipantList; - mParticipantList = NULL; -} - -// virtual -void LLPanelGroupControlPanel::draw() -{ - // Need to resort the participant list if it's in sort by recent speaker order. - if (mParticipantList) - mParticipantList->update(); - LLPanelChatControlPanel::draw(); -} - - -void LLPanelGroupControlPanel::onSortMenuItemClicked(const LLSD& userdata) -{ - // TODO: Check this code when when sort order menu will be added. (EM) - if (false && !mParticipantList) - return; - - std::string chosen_item = userdata.asString(); - - if (chosen_item == "sort_name") - { - mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME); - } - -} - -void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id) -{ - LLPanelChatControlPanel::setSessionId(session_id); - - mGroupID = session_id; - - // for group and Ad-hoc chat we need to include agent into list - if(!mParticipantList) - { - LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id); - mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false); - } -} - - -LLPanelAdHocControlPanel::LLPanelAdHocControlPanel(const LLUUID& session_id):LLPanelGroupControlPanel(session_id) -{ -} - -BOOL LLPanelAdHocControlPanel::postBuild() -{ - //We don't need LLPanelGroupControlPanel::postBuild() to be executed as there is no group_info_btn at AdHoc chat - return LLPanelChatControlPanel::postBuild(); -} diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 5ced32a9ab..df1962f5fe 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -134,7 +134,6 @@ #include "llscriptfloater.h" #include "llfloatermodelpreview.h" #include "llcommandhandler.h" -#include "llnearbychatbar.h" // *NOTE: Please add files in alphabetical order to keep merges easy. @@ -187,8 +186,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>); LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>); - LLFloaterReg::add("chat_bar", "floater_chat_bar.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChatBar>); - LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>); LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>); @@ -211,6 +208,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHelpBrowser>); LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>); + LLFloaterReg::add("chat_bar", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>); LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloater>); LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloaterContainer>); LLFloaterReg::add("im_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMWellWindow>); diff --git a/indra/newview/llviewergesture.cpp b/indra/newview/llviewergesture.cpp index a32a78cbf9..c7d37e102e 100644 --- a/indra/newview/llviewergesture.cpp +++ b/indra/newview/llviewergesture.cpp @@ -40,7 +40,7 @@ #include "llviewermessage.h" // send_guid_sound_trigger #include "llviewernetwork.h" #include "llagent.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" // Globals LLViewerGestureList gGestureList; @@ -130,7 +130,7 @@ void LLViewerGesture::doTrigger( BOOL send_chat ) { // Don't play nodding animation, since that might not blend // with the gesture animation. - LLNearbyChatBar::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); + LLNearbyChat::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); } } diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 1aa9fd8a45..385d3cd29a 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -31,7 +31,7 @@ #include "llmath.h" #include "llagent.h" #include "llagentcamera.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llviewercontrol.h" #include "llfocusmgr.h" #include "llmorphview.h" @@ -534,7 +534,7 @@ void stop_moving( EKeystate s ) void start_chat( EKeystate s ) { // start chat - LLNearbyChatBar::startChat(NULL); + LLNearbyChat::startChat(NULL); } void start_gesture( EKeystate s ) @@ -543,15 +543,15 @@ void start_gesture( EKeystate s ) if (KEYSTATE_UP == s && ! (focus_ctrlp && focus_ctrlp->acceptsTextInput())) { - if (LLNearbyChatBar::getInstance()->getCurrentChat().empty()) + if (LLNearbyChat::getInstance()->getCurrentChat().empty()) { // No existing chat in chat editor, insert '/' - LLNearbyChatBar::startChat("/"); + LLNearbyChat::startChat("/"); } else { // Don't overwrite existing text in chat editor - LLNearbyChatBar::startChat(NULL); + LLNearbyChat::startChat(NULL); } } } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 32f693b009..5b8cf52298 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -185,7 +185,7 @@ #include "llviewerjoystick.h" #include "llviewernetwork.h" #include "llpostprocess.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llagentui.h" #include "llwearablelist.h" @@ -2482,7 +2482,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) // Traverses up the hierarchy if( keyboard_focus ) { - LLNearbyChatBar* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChatBar>("chat_bar"); + LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("chat_bar"); if (nearby_chat) { @@ -2549,11 +2549,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) { - LLLineEditor* chat_editor = LLFloaterReg::getTypedInstance<LLNearbyChatBar>("chat_bar")->getChatBox(); + LLLineEditor* chat_editor = LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar")->getChatBox(); if (chat_editor) { // passing NULL here, character will be added later when it is handled by character handler. - LLNearbyChatBar::getInstance()->startChat(NULL); + LLNearbyChat::getInstance()->startChat(NULL); return TRUE; } } diff --git a/indra/newview/skins/default/xui/en/floater_chat_bar.xml b/indra/newview/skins/default/xui/en/floater_chat_bar.xml deleted file mode 100644 index 7688525e13..0000000000 --- a/indra/newview/skins/default/xui/en/floater_chat_bar.xml +++ /dev/null @@ -1,202 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - open_positioning="specified" - specified_left="10" - specified_bottom="10" - background_visible="true" - default_tab_group="1" - height="355" - help_topic="chat_bar" - layout="topleft" - name="chat_bar" - can_dock="false" - can_minimize="true" - can_close="true" - visible="false" - width="394" - can_resize="true" - can_tear_off="false" - min_width="250" - min_height="80" - single_instance="true" - title="Nearby chat"> - <floater.string name="call_btn_start">VoicePTT_Off</floater.string> - <floater.string name="call_btn_stop">VoicePTT_On</floater.string> - <floater.string - name="collapse_icon" - value="TabIcon_Open_Off"/> - <floater.string - name="expand_icon" - value="TabIcon_Close_Off"/> - <floater.string - name="tear_off_icon" - value="tearoffbox.tga"/> - <floater.string - name="return_icon" - value="Icon_Dock_Foreground"/> - <view - follows="all" - layout="topleft" - name="contents_view" - top="0" - left="0" - height="355" - width="394"> - <panel - follows="left|top|right" - layout="topleft" - name="toolbar_panel" - top="0" - left="0" - height="35" - width="394"> - <menu_button - menu_filename="menu_im_session_showmodes.xml" - follows="top|left" - height="25" - image_hover_unselected="Toolbar_Left_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Left_Selected" - image_unselected="Toolbar_Left_Off" - layout="topleft" - left="5" - name="view_options_btn" - top="5" - width="31" /> - <button - follows="top|left" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - top="5" - left_pad="4" - name="add_btn" - width="31"> - <commit_callback - function="Chats.add" /> - </button> - <button - follows="top|left" - height="25" - image_hover_unselected="Toolbar_Right_Over" - image_overlay="VoicePTT_Off" - image_selected="Toolbar_Right_Selected" - image_unselected="Toolbar_Right_Off" - layout="topleft" - top="5" - left_pad="4" - name="voice_call_btn" - width="31"> - <commit_callback - function="Chats.add" /> - </button> - <button - follows="right|top" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Icon_Close_Foreground" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - top="5" - left="283" - name="close_btn" - width="31"> - </button> - <button - follows="right|top" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="TabIcon_Open_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - top="5" - left_pad="5" - name="expand_collapse_btn" - width="31"> - </button> - <button - follows="right|top" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="tearoffbox.tga" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - top="5" - left_pad="5" - name="tear_off_btn" - width="31"> - </button> - </panel> - <panel - top="35" - left="0" - class="panel_nearby_chat" - follow="all" - width="390" - height="0" - visible="false" - filename="panel_nearby_chat.xml" - name="nearby_chat" /> - <panel - width="390" - height="10" - visible="true" /> - <panel width="394" - height="31" - left="0" - name="bottom_panel" - bottom="-1" - follows="left|right|bottom" - tab_group="1"> - <line_editor - border_style="line" - border_thickness="1" - follows="left|right" - height="20" - label="Click here to chat." - layout="topleft" - left="1" - max_length_bytes="1023" - name="chat_box" - tool_tip="Press Enter to say, Ctrl+Enter to shout" - top="2" - width="384" /> - <output_monitor - auto_update="true" - follows="right" - draw_border="false" - height="16" - layout="topleft" - left_pad="-24" - mouse_opaque="true" - name="chat_zone_indicator" - top="6" - visible="true" - width="20" /> - <button - follows="right" - visible="false" - is_toggle="true" - width="20" - top="2" - layout="topleft" - left_pad="12" - image_disabled="ComboButton_UpOff" - image_unselected="ComboButton_UpOff" - image_selected="ComboButton_On" - image_pressed="ComboButton_UpSelected" - image_pressed_selected="ComboButton_Selected" - height="23" - chrome="true" - name="show_nearby_chat" - tool_tip="Shows/hides nearby chat log"> - </button> - </panel> - </view> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index a332bb5b12..c5cacab9f4 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -138,18 +138,24 @@ top_pad="0" left="0"> <layout_panel - name="im_control_panel_holder" + name="speakers_list_panel" min_width="115" width="150" height="310" auto_resize="false"> - <panel - name="panel_im_control_panel" - layout="topleft" - height="310" - width="150" - follows="all"/> - </layout_panel> + <avatar_list + color="DkGray2" + follows="all" + height="100" + ignore_online_status="true" + layout="topleft" + name="speakers_list" + opaque="false" + show_info_btn="true" + show_profile_btn="false" + show_speaking_indicator="false" + width="145" /> + </layout_panel> <layout_panel default_tab_group="3" left="0" @@ -158,27 +164,82 @@ height="200" width="254" user_resize="true"> - <chat_history - font="SansSerifSmall" - follows="all" - height="170" - name="chat_history" - parse_highlights="true" - parse_urls="true" - left="1" - width="249"> - </chat_history> - <line_editor - bottom="0" - follows="left|right|bottom" - font="SansSerifSmall" - height="20" - label="To" - layout="bottomleft" - name="chat_editor" - tab_group="3" - width="249"> - </line_editor> + <layout_stack + animate="true" + default_tab_group="2" + follows="all" + height="200" + width="254" + layout="topleft" + orientation="vertical" + name="chat_area" + tab_group="1" + left_pad="0" + top="0"> + <layout_panel + auto_resize="false" + height="26" + layout="topleft" + left_delta="0" + name="translate_chat_checkbox_lp" + top_delta="0" + visible="true" + width="230"> + <check_box + top="10" + control_name="TranslateChat" + enabled="true" + height="16" + label="Translate chat" + layout="topleft" + left="5" + name="translate_chat_checkbox" + width="230" /> + </layout_panel> + <layout_panel + auto_resize="false" + height="170" + layout="topleft" + left_delta="0" + name="translate_chat_checkbox_lp" + top_delta="0" + visible="true" + width="230"> + <chat_history + font="SansSerifSmall" + follows="all" + height="170" + name="chat_history" + parse_highlights="true" + parse_urls="true" + left="1" + width="229"> + </chat_history> + <line_editor + bottom="0" + follows="left|right|bottom" + font="SansSerifSmall" + height="20" + label="To" + layout="bottomleft" + name="chat_editor" + tab_group="3" + width="230"> + </line_editor> + <output_monitor + auto_update="true" + follows="right" + draw_border="false" + height="16" + layout="topleft" + left_pad="-24" + mouse_opaque="true" + name="chat_zone_indicator" + top="6" + visible="true" + width="20" /> + </layout_panel> + </layout_stack> </layout_panel> </layout_stack> </view> diff --git a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml deleted file mode 100644 index d68fa6ca6c..0000000000 --- a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml +++ /dev/null @@ -1,95 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - border="false" - follows="all" - height="215" - name="panel_im_control_panel" - width="150"> - <layout_stack - mouse_opaque="false" - border_size="0" - clip="false" - follows="all" - height="215" - layout="topleft" - left="3" - name="vertical_stack" - orientation="vertical" - top="0" - width="147"> - <layout_panel - auto_resize="true" - follows="top|left" - height="130" - layout="topleft" - left="0" - min_height="0" - mouse_opaque="false" - width="147" - top="0" - name="speakers_list_panel"> - <avatar_list - color="DkGray2" - follows="all" - height="130" - ignore_online_status="true" - layout="topleft" - name="speakers_list" - opaque="false" - show_info_btn="true" - show_profile_btn="false" - show_speaking_indicator="false" - width="147" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="25" - layout="topleft" - min_height="25" - width="130" - name="call_btn_panel" - visible="false"> - <button - follows="all" - height="20" - label="Call" - name="call_btn" - width="130" - top="0" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="25" - layout="topleft" - min_height="25" - width="130" - name="end_call_btn_panel" - visible="false"> - <button - follows="all" - height="20" - label="Leave Call" - name="end_call_btn" - top="0"/> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="25" - layout="topleft" - min_height="25" - width="130" - name="voice_ctrls_btn_panel" - visible="false"> - <button - follows="all" - height="20" - label="Voice Controls" - name="voice_ctrls_btn" - top="0" - use_ellipses="true" /> - </layout_panel> - </layout_stack> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml deleted file mode 100644 index a5295ebe01..0000000000 --- a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml +++ /dev/null @@ -1,60 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - border="false" - follows="all" - height="238" - name="panel_im_control_panel" - width="150"> - <layout_stack - mouse_opaque="false" - border_size="0" - clip="false" - follows="all" - height="238" - layout="topleft" - left="5" - name="vertical_stack" - orientation="vertical" - top="0" - width="145"> - <layout_panel - auto_resize="true" - follows="top|left" - height="100" - layout="topleft" - min_height="0" - mouse_opaque="false" - width="145" - top="0" - name="speakers_list_panel"> - <avatar_list - color="DkGray2" - follows="all" - height="100" - ignore_online_status="true" - layout="topleft" - name="speakers_list" - opaque="false" - show_info_btn="true" - show_profile_btn="false" - show_speaking_indicator="false" - width="145" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|left|right" - height="28" - layout="topleft" - min_height="28" - width="130" - name="voice_ctrls_btn_panel" - visible="false"> - <button - follows="all" - height="23" - label="Open Voice Controls" - name="voice_ctrls_btn" - use_ellipses="true" /> - </layout_panel> - </layout_stack> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml index b415ba780d..4de56b424e 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml @@ -6,16 +6,17 @@ help_topic="nearby_chat" layout="topleft" name="nearby_chat" - width="394"> + width="242" + height="169"> <layout_stack follows="all" - height="278" + height="164" layout="topleft" left="0" name="stack" top="5" orientation="vertical" - width="394"> + width="242"> <layout_panel auto_resize="false" height="26" @@ -24,7 +25,7 @@ name="translate_chat_checkbox_lp" top_delta="0" visible="true" - width="387"> + width="230"> <check_box top="10" control_name="TranslateChat" @@ -34,15 +35,15 @@ layout="topleft" left="5" name="translate_chat_checkbox" - width="374" /> + width="230" /> </layout_panel> <layout_panel auto_resize="true" - height="256" + height="138" left_delta="0" layout="topleft" name="chat_history_lp" - width="394"> + width="242"> <chat_history bg_readonly_color="ChatHistoryBgColor" bg_writeable_color="ChatHistoryBgColor" @@ -50,7 +51,7 @@ layout="topleft" left="5" left_widget_pad="0" - height="240" + height="138" name="chat_history" parse_highlights="true" parse_urls="true" @@ -58,7 +59,7 @@ text_color="ChatHistoryTextColor" text_readonly_color="ChatHistoryTextColor" top="0" - width="384" /> + width="237" /> </layout_panel> </layout_stack> </panel> -- cgit v1.2.3 From b7b612500132acf05e82f1482460ffa9312fcc4a Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 1 Jun 2012 14:57:51 +0300 Subject: CHUI-119 FIXED Bug fixed. Clean up a code --- indra/newview/llnearbychat.cpp | 7 +- indra/newview/llstartup.cpp | 9 --- .../skins/default/xui/en/floater_im_session.xml | 88 +++++++++++++--------- 3 files changed, 58 insertions(+), 46 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 2d7095957e..4ac72858d3 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -68,7 +68,6 @@ S32 LLNearbyChat::sLastSpecialChatChannel = 0; - // --- 2 functions in the global namespace :( --- bool isWordsName(const std::string& name) { @@ -179,8 +178,12 @@ BOOL LLNearbyChat::postBuild() gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); mChatHistory = getChild<LLChatHistory>("chat_history"); + if (gSavedPerAccountSettings.getBOOL("LogShowHistory")) + { + loadHistory(); + } - return LLIMConversation::postBuild();; + return LLIMConversation::postBuild(); } void LLNearbyChat::onNearbySpeakers() diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 0ac8c1fe39..2f13ba5ab1 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1376,15 +1376,6 @@ bool idle_startup() LLVoiceClient::getInstance()->updateSettings(); display_startup(); - //gCacheName is required for nearby chat history loading - //so I just moved nearby history loading a few states further - if (gSavedPerAccountSettings.getBOOL("LogShowHistory")) - { - LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - if (nearby_chat) nearby_chat->loadHistory(); - } - display_startup(); - // *Note: this is where gWorldMap used to be initialized. // register null callbacks for audio until the audio system is initialized diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index c5cacab9f4..beeb4eea9b 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -70,8 +70,6 @@ left_pad="4" name="add_btn" width="31"> - <commit_callback - function="Chats.add" /> </button> <button follows="top|left" @@ -85,8 +83,6 @@ left_pad="4" name="voice_call_btn" width="31"> - <commit_callback - function="Chats.add" /> </button> <button follows="right|top" @@ -136,9 +132,12 @@ name="im_panels" tab_group="1" top_pad="0" - left="0"> + left="0" + auto_resize="true" + user_resize="true"> <layout_panel name="speakers_list_panel" + follows="all" min_width="115" width="150" height="310" @@ -146,7 +145,7 @@ <avatar_list color="DkGray2" follows="all" - height="100" + height="310" ignore_online_status="true" layout="topleft" name="speakers_list" @@ -154,28 +153,44 @@ show_info_btn="true" show_profile_btn="false" show_speaking_indicator="false" - width="145" /> + width="150" /> </layout_panel> <layout_panel default_tab_group="3" left="0" tab_group="2" + follows="all" top="0" - height="200" - width="254" - user_resize="true"> + height="310" + width="244" + layout="topleft" + user_resize="true" + auto_resize="true" + visible="true" + name="left_part_holder"> + <panel + name="trnsAndChat_panel" + follows="all" + layout="topleft" + visible="true" + height="275" + width="244"> <layout_stack animate="true" default_tab_group="2" follows="all" - height="200" - width="254" + height="275" + width="244" layout="topleft" + visible="true" orientation="vertical" - name="chat_area" + name="translate_and_chat_stack" tab_group="1" + auto_resize="true" + user_resize="true" left_pad="0" - top="0"> + top="0" + left="0"> <layout_panel auto_resize="false" height="26" @@ -197,49 +212,52 @@ width="230" /> </layout_panel> <layout_panel - auto_resize="false" - height="170" + height="248" + width="234" layout="topleft" + follows="all" left_delta="0" - name="translate_chat_checkbox_lp" top_delta="0" + bottom="0" visible="true" - width="230"> + user_resize="true" + auto_resize="true" + name="chat_holder"> <chat_history font="SansSerifSmall" follows="all" - height="170" + visible="true" + height="240" name="chat_history" parse_highlights="true" parse_urls="true" left="1" width="229"> - </chat_history> + </chat_history> + </layout_panel> + </layout_stack> + </panel> + <panel width="228" + height="31" + left="4" + right="4" + name="bottom_panel" + bottom="-1" + follows="left|right|bottom" + tab_group="1"> <line_editor bottom="0" follows="left|right|bottom" font="SansSerifSmall" + visible="true" height="20" label="To" layout="bottomleft" name="chat_editor" tab_group="3" - width="230"> + width="240"> </line_editor> - <output_monitor - auto_update="true" - follows="right" - draw_border="false" - height="16" - layout="topleft" - left_pad="-24" - mouse_opaque="true" - name="chat_zone_indicator" - top="6" - visible="true" - width="20" /> - </layout_panel> - </layout_stack> + </panel> </layout_panel> </layout_stack> </view> -- cgit v1.2.3 From 30a6da68bcee5b871fd0a18dab703fe20271d83c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 1 Jun 2012 16:36:58 +0300 Subject: Build fix --- indra/newview/llimconversation.cpp | 4 ++-- indra/newview/llnearbychat.cpp | 4 ---- indra/newview/llnearbychat.h | 2 -- 3 files changed, 2 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 893d8dc83f..d8c7c63e9e 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -37,7 +37,7 @@ #include "llnearbychat.h" #include "llnearbychat.h" -const F32 REFRESH_INTERVAL = 0.2; +const F32 REFRESH_INTERVAL = 0.2f; LLIMConversation::LLIMConversation(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id) @@ -127,7 +127,7 @@ void LLIMConversation::buildParticipantList() } else { - // for group and Ad-hoc chat we need to include agent into list + // for group and ad-hoc chat we need to include agent into list if(!mIsP2PChat && !mParticipantList && mSessionID.notNull()) { LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 4ac72858d3..8b54c6ce53 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -318,10 +318,6 @@ void LLNearbyChat::setVisible(BOOL visible) LLIMConversation::setVisible(visible); } -void LLNearbyChat::onCallButtonClicked() -{ - LLAgent::toggleMicrophone(NULL); -} void LLNearbyChat::enableDisableCallBtn() { diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index b38111defa..bc0e54de15 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -108,8 +108,6 @@ protected: void displaySpeakingIndicator(); - void onCallButtonClicked(); - // set the enable/disable state for the Call button virtual void enableDisableCallBtn(); -- cgit v1.2.3 From 164e1073952060cf88a163945d6745934db62620 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 5 Jun 2012 18:20:01 +0300 Subject: CHUI-103 Added square brackets to a messages from Second Life in the plain text mode; changed the default colors of user's messages --- indra/newview/llchathistory.cpp | 8 ++++++++ indra/newview/skins/default/colors.xml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index c514261b60..cfc70a1b0e 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -693,6 +693,7 @@ void LLChatHistory::clear() void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LLStyle::Params& input_append_params) { bool use_plain_text_chat_history = args["use_plain_text_chat_history"].asBoolean(); + bool square_brackets = false; // square brackets necessary for a system messages llassert(mEditor); if (!mEditor) @@ -781,6 +782,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL // show timestamps and names in the compact mode if (use_plain_text_chat_history) { + square_brackets = chat.mFromName == SYSTEM_FROM; + LLStyle::Params timestamp_style(style_params); // timestams showing @@ -942,6 +945,11 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL message = chat.mFromName + message; } + if (square_brackets) + { + message = "[" + message + "]"; + } + mEditor->appendText(message, prependNewLineState, style_params); prependNewLineState = false; } diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index b616e2327b..5205988d5d 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -766,7 +766,7 @@ reference="LtGray" /> <color name="UserChatColor" - reference="White" /> + reference="Yellow" /> <color name="llOwnerSayChatColor" reference="LtYellow" /> -- cgit v1.2.3 From d11f542ffefdc5db845028d5a260b5b0ad12dea6 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Thu, 7 Jun 2012 00:59:05 +0300 Subject: CHUI-120 WIP Added starting ad hoc conference in the same floater as P2P chat, after adding more participants. - Added a parameter to LLAvatarActions::startConference() and LLIMMgr::addSession() to pass the uuid of a P2P IM floater which should be used to start a new conference in it. - In LLChicletBar::sessionRemoved() we don't close the IM floater if it is going to be re-used for a new conference. --- indra/newview/llavataractions.cpp | 4 +- indra/newview/llavataractions.h | 4 +- indra/newview/llchicletbar.cpp | 8 +- indra/newview/llimfloater.cpp | 158 +++++++++++---------- indra/newview/llimfloater.h | 10 +- indra/newview/llimview.cpp | 15 +- indra/newview/llimview.h | 4 +- indra/newview/llnearbychat.cpp | 1 + indra/newview/llpanelpeoplemenus.cpp | 2 +- indra/newview/llstartup.cpp | 1 - .../skins/default/xui/en/floater_im_session.xml | 6 +- 11 files changed, 117 insertions(+), 96 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index aa626a9a30..53b87faf66 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -285,7 +285,7 @@ bool LLAvatarActions::canCall() } // static -void LLAvatarActions::startConference(const uuid_vec_t& ids) +void LLAvatarActions::startConference(const uuid_vec_t& ids, const LLUUID& floater_id) { // *HACK: Copy into dynamic array LLDynamicArray<LLUUID> id_array; @@ -294,7 +294,7 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids) id_array.push_back(*it); } const std::string title = LLTrans::getString("conference-title"); - LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array); + LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array, false, floater_id); if (session_id != LLUUID::null) { LLIMFloater::show(session_id); diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index e5dad74fc8..0a69ad86a3 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -86,9 +86,9 @@ public: static void startAdhocCall(const uuid_vec_t& ids); /** - * Start conference chat with the given avatars. + * Start conference chat with the given avatars in a specific IM floater. */ - static void startConference(const uuid_vec_t& ids); + static void startConference(const uuid_vec_t& ids, const LLUUID& floater_id = LLUUID::null); /** * Show avatar profile. diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index f1bc51fbe7..8701b602ce 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -125,10 +125,12 @@ void LLChicletBar::sessionRemoved(const LLUUID& session_id) if(getChicletPanel()) { // IM floater should be closed when session removed and associated chiclet closed - LLIMFloater* iMfloater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); - if (iMfloater != NULL) + LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); + if (im_floater != NULL && !im_floater->getStartConferenceInSameFloater()) { - iMfloater->closeFloater(); + // Close the IM floater only if we are not planning to close the P2P chat + // and start a new conference in the same floater. + im_floater->closeFloater(); } getChicletPanel()->removeChiclet(session_id); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index c99da9e9c1..f04fecca26 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -71,18 +71,12 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mTypingTimer(), mTypingTimeoutTimer(), mPositioned(false), - mSessionInitialized(false) + mSessionInitialized(false), + mStartConferenceInSameFloater(false) { mIsNearbyChat = false; + initIMSession(session_id); - mSession = LLIMModel::getInstance()->findIMSession(mSessionID); - - if (mSession) - { - mIsP2PChat = mSession->isP2PSessionType(); - mSessionInitialized = mSession->mSessionInitialized; - mDialog = mSession->mType; - } setOverlapsScreenChannel(true); LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); @@ -112,6 +106,29 @@ void LLIMFloater::onFocusReceived() // virtual void LLIMFloater::onClose(bool app_quitting) { + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( + mSessionID); + + if (session == NULL) + { + llwarns << "Empty session." << llendl; + return; + } + + bool is_call_with_chat = session->isGroupSessionType() + || session->isAdHocSessionType() || session->isP2PSessionType(); + + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + + if (is_call_with_chat && voice_channel != NULL + && voice_channel->isActive()) + { + LLSD payload; + payload["session_id"] = mSessionID; + LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); + return; + } + setTyping(false); // The source of much argument and design thrashing @@ -211,8 +228,24 @@ LLIMFloater::~LLIMFloater() LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); } -//virtual -BOOL LLIMFloater::postBuild() +void LLIMFloater::initIMSession(const LLUUID& session_id) +{ + // Change the floater key to bind it to a new session. + setKey(session_id); + + mSessionID = session_id; + mSession = LLIMModel::getInstance()->findIMSession(mSessionID); + + if (mSession) + { + mIsP2PChat = mSession->isP2PSessionType(); + mSessionInitialized = mSession->mSessionInitialized; + + mDialog = mSession->mType; + } +} + +void LLIMFloater::initIMFloater() { const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID); @@ -223,6 +256,34 @@ BOOL LLIMFloater::postBuild() boundVoiceChannel(); + // Show control panel in torn off floaters only. + mParticipantListPanel->setVisible(!getHost() && gSavedSettings.getBOOL("IMShowControlPanel")); + + // Disable input editor if session cannot accept text + if ( mSession && !mSession->mTextIMPossible ) + { + mInputEditor->setEnabled(FALSE); + mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label")); + } + + if (mIsP2PChat) + { + // look up display name for window title + LLAvatarNameCache::get(mSession->mOtherParticipantID, + boost::bind(&LLIMFloater::onAvatarNameCache, + this, _1, _2)); + } + else + { + std::string session_name(LLIMModel::instance().getName(mSessionID)); + updateSessionName(session_name, session_name); + } +} + +//virtual +BOOL LLIMFloater::postBuild() +{ + LLIMConversation::postBuild(); mInputEditor = getChild<LLLineEditor>("chat_editor"); mInputEditor->setMaxTextLength(1023); @@ -248,26 +309,6 @@ BOOL LLIMFloater::postBuild() mTypingStart = LLTrans::getString("IM_typing_start_string"); - // Disable input editor if session cannot accept text - if ( mSession && !mSession->mTextIMPossible ) - { - mInputEditor->setEnabled(FALSE); - mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label")); - } - - if (mIsP2PChat) - { - // look up display name for window title - LLAvatarNameCache::get(mSession->mOtherParticipantID, - boost::bind(&LLIMFloater::onAvatarNameCache, - this, _1, _2)); - } - else - { - std::string session_name(LLIMModel::instance().getName(mSessionID)); - updateSessionName(session_name, session_name); - } - childSetAction("voice_call_btn", boost::bind(&LLIMFloater::onCallButtonClicked, this)); LLVoiceClient::getInstance()->addObserver(this); @@ -275,7 +316,9 @@ BOOL LLIMFloater::postBuild() //*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla" //see LLFloaterIMPanel for how it is done (IB) - return LLIMConversation::postBuild(); + initIMFloater(); + + return TRUE; } void LLIMFloater::boundVoiceChannel() @@ -603,17 +646,15 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) //will be different only for an ad-hoc im session if (mSessionID != im_session_id) { - mSessionID = im_session_id; - setKey(im_session_id); + initIMSession(im_session_id); boundVoiceChannel(); - mSession = LLIMModel::getInstance()->findIMSession(mSessionID); - mIsP2PChat = mSession && mSession->isP2PSessionType(); - buildParticipantList(); } - + + initIMFloater(); + //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) //need to send delayed messaged collected while waiting for session initialization @@ -965,7 +1006,8 @@ BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop) BOOL LLIMFloater::isInviteAllowed() const { return ((IM_SESSION_CONFERENCE_START == mDialog) - || (IM_SESSION_INVITE == mDialog)); + || (IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) + || mIsP2PChat); } class LLSessionInviteResponder: public LLHTTPClient::Responder @@ -1107,14 +1149,6 @@ void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD& } // static -void LLIMFloater::initIMFloater() -{ - // This is called on viewer start up - // init chat window type before user changed it in preferences - isChatMultiTab(); -} - -//static void LLIMFloater::sRemoveTypingIndicator(const LLSD& data) { LLUUID session_id = data["session_id"]; @@ -1139,7 +1173,6 @@ void LLIMFloater::onIMChicletCreated( const LLUUID& session_id ) { LLIMFloater::addToHost(session_id); } - void LLIMFloater::addToHost(const LLUUID& session_id) { if (LLIMConversation::isChatMultiTab()) @@ -1157,32 +1190,3 @@ void LLIMFloater::addToHost(const LLUUID& session_id) } } } - -void LLIMFloater::onClickCloseBtn() -{ - - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - mSessionID); - - if (session == NULL) - { - llwarns << "Empty session." << llendl; - return; - } - - bool is_call_with_chat = session->isGroupSessionType() - || session->isAdHocSessionType() || session->isP2PSessionType(); - - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - - if (is_call_with_chat && voice_channel != NULL - && voice_channel->isActive()) - { - LLSD payload; - payload["session_id"] = mSessionID; - LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); - return; - } - - LLFloater::onClickCloseBtn(); -} diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 24f28c8aee..b97d4ab90c 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -56,6 +56,9 @@ public: virtual ~LLIMFloater(); + void initIMSession(const LLUUID& session_id); + void initIMFloater(); + // LLView overrides /*virtual*/ BOOL postBuild(); /*virtual*/ void setVisible(BOOL visible); @@ -117,14 +120,11 @@ public: std::string& tooltip_msg); - static void initIMFloater(); - //used as a callback on receiving new IM message static void sRemoveTypingIndicator(const LLSD& data); static void onIMChicletCreated(const LLUUID& session_id); -protected: - /* virtual */ void onClickCloseBtn(); + bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; } private: // process focus events to set a currently active session @@ -186,6 +186,8 @@ private: bool mSessionInitialized; LLSD mQueuedMsgsForInit; + bool mStartConferenceInSameFloater; + // connection to voice channel state change signal boost::signals2::connection mVoiceChannelStateChangeConnection; }; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 46b1cb5f18..0d2b1f06b5 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2591,7 +2591,8 @@ LLUUID LLIMMgr::addSession( const std::string& name, EInstantMessage dialog, const LLUUID& other_participant_id, - const LLDynamicArray<LLUUID>& ids, bool voice) + const LLDynamicArray<LLUUID>& ids, bool voice, + const LLUUID& floater_id) { if (0 == ids.getLength()) { @@ -2606,6 +2607,18 @@ LLUUID LLIMMgr::addSession( LLUUID session_id = computeSessionID(dialog,other_participant_id); + if (floater_id.notNull()) + { + LLIMFloater* im_floater = LLIMFloater::findInstance(floater_id); + if (im_floater && im_floater->getStartConferenceInSameFloater()) + { + // The IM floater should be initialized with a new session_id + // so that it is found by that id when creating a chiclet in LLIMFloater::onIMChicletCreated, + // and a new floater is not created. + im_floater->initIMSession(session_id); + } + } + bool new_session = !LLIMModel::getInstance()->findIMSession(session_id); //works only for outgoing ad-hoc sessions diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 9d19af4b62..58a2ac5162 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -347,10 +347,12 @@ public: // Adds a session using a specific group of starting agents // the dialog type is assumed correct. Returns the uuid of the session. + // A session can be added to a floater specified by floater_id. LLUUID addSession(const std::string& name, EInstantMessage dialog, const LLUUID& other_participant_id, - const LLDynamicArray<LLUUID>& ids, bool voice = false); + const LLDynamicArray<LLUUID>& ids, bool voice = false, + const LLUUID& floater_id = LLUUID::null); /** * Creates a P2P session with the requisite handle for responding to voice calls. diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 8b54c6ce53..e35dbf21d4 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -130,6 +130,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& key) mSpeakerMgr(NULL), mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) { + mIsNearbyChat = true; mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); } diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index c84790d839..ac2109dda4 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -81,7 +81,7 @@ LLContextMenu* NearbyMenu::createMenu() // Set up for multi-selected People // registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs)); // *TODO: unimplemented - registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startConference, mUUIDs)); + registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startConference, mUUIDs, LLUUID::null)); registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs)); registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this)); registrar.add("Avatar.RemoveFriend",boost::bind(&LLAvatarActions::removeFriendsDialog, mUUIDs)); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 2f13ba5ab1..320a602916 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2153,7 +2153,6 @@ bool idle_startup() LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); - LLIMFloater::initIMFloater(); display_startup(); return TRUE; diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index beeb4eea9b..fc5b6b10af 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -69,8 +69,7 @@ top="5" left_pad="4" name="add_btn" - width="31"> - </button> + width="31"/> <button follows="top|left" height="25" @@ -82,8 +81,7 @@ top="5" left_pad="4" name="voice_call_btn" - width="31"> - </button> + width="31"/> <button follows="right|top" height="25" -- cgit v1.2.3 From 85e553638e51994824683497bd9ccc964c7cc1fc Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 6 Jun 2012 19:37:59 -0700 Subject: CHUI-137 : Implement temporary conversations list (not working yet) --- indra/newview/llfolderviewitem.cpp | 2 +- indra/newview/llimfloatercontainer.cpp | 79 +++++++++++++++++++++++++++++++++ indra/newview/llimfloatercontainer.h | 81 ++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 43d3675d17..126de95551 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -287,7 +287,7 @@ void LLFolderViewItem::refreshFromListener() setCreationDate(creation_date); dirtyFilter(); } - if (mRoot->useLabelSuffix()) + if (mRoot && mRoot->useLabelSuffix()) { mLabelStyle = mListener->getLabelStyle(); mLabelSuffix = mListener->getLabelSuffix(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 3b6240de44..134d345148 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -71,6 +71,8 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsStack = getChild<LLLayoutStack>("conversations_stack"); mConversationsPane = getChild<LLLayoutPanel>("conversations_layout_panel"); mMessagesPane = getChild<LLLayoutPanel>("messages_layout_panel"); + + mConversationsListPanel = getChild<LLPanel>("conversations_list_panel"); mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this)); @@ -112,6 +114,22 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); + // CHUI-137 + llinfos << "Merov debug : addFloater, title = " << floaterp->getTitle() << llendl; + // Create a conversation item + LLConversationItem item(floaterp->getTitle()); + // Add it to the list + mConversationsItems.push_back(item); + // Create a widget from it + LLFolderViewItem* widget = createConversationItemWidget(&item); + // Add it to the list of widgets + mConversationsWidgets.push_back(widget); + // Add it to the UI + widget->setVisible(TRUE); + mConversationsListPanel->addChild(widget); + // Reposition it... + // CHUI-137 : end + LLView* floater_contents = floaterp->getChild<LLView>("contents_view"); // we don't show the header when the floater is hosted, @@ -150,6 +168,8 @@ void LLIMFloaterContainer::removeFloater(LLFloater* floaterp) { LLMultiFloater::removeFloater(floaterp); + llinfos << "Merov debug : removeFloater, title = " << floaterp->getTitle() << llendl; + LLRect contents_rect = floaterp->getRect(); // reduce the floater contents height by header height @@ -313,4 +333,63 @@ void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); } +// CHUI-137 : Temp implementation of conversations list +LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) +{ + LLFolderViewItem::Params params; + + params.name = item->getDisplayName(); + //params.icon = bridge->getIcon(); + //params.icon_open = bridge->getOpenIcon(); + + //params.creation_date = bridge->getCreationDate(); + //params.root = mFolderRoot; + params.listener = item; + params.rect = LLRect (0, 0, 0, 0); + params.tool_tip = params.name; + + return LLUICtrlFactory::create<LLFolderViewItem>(params); +} + +// Conversation items +LLConversationItem::LLConversationItem(std::string name) : + mName(name), + mUUID(LLUUID::null) +{ + if (name == "") + mName = "Nearby Chat"; +} + +// Virtual action callbacks +void LLConversationItem::performAction(LLInventoryModel* model, std::string action) +{ + llinfos << "Merov debug : performAction, title = " << mName << ", action = " << action << llendl; +} + +void LLConversationItem::openItem( void ) +{ + llinfos << "Merov debug : openItem, title = " << mName << llendl; +} + +void LLConversationItem::closeItem( void ) +{ + llinfos << "Merov debug : closeItem, title = " << mName << llendl; +} + +void LLConversationItem::previewItem( void ) +{ + llinfos << "Merov debug : previewItem, title = " << mName << llendl; +} + +void LLConversationItem::selectItem(void) +{ + llinfos << "Merov debug : selectItem, title = " << mName << llendl; +} + +void LLConversationItem::showProperties(void) +{ + llinfos << "Merov debug : showProperties, title = " << mName << llendl; +} + + // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 92938ff405..5cfdb41ad3 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -35,11 +35,85 @@ #include "llavatarpropertiesprocessor.h" #include "llgroupmgr.h" +#include "llfolderviewitem.h" +#include "llfoldervieweventlistener.h" + class LLButton; class LLLayoutPanel; class LLLayoutStack; class LLTabContainer; +// CHUI-137 : Temporary implementation of conversations list +class LLConversationItem; + +typedef std::list<LLConversationItem> conversations_items_list_t; +typedef std::list<LLFolderViewItem*> conversations_widgets_list_t; + +// Conversation items: we hold a list of those and create an LLFolderViewItem widget for each that we tuck +// into the mConversationsListPanel. +class LLConversationItem : public LLFolderViewEventListener +{ +public: + LLConversationItem(std::string name); + virtual ~LLConversationItem() {} + + // Stub those things we won't really be using in this conversation context + virtual const std::string& getName() const { return mName; } + virtual const std::string& getDisplayName() const { return mName; } + virtual const LLUUID& getUUID() const { return mUUID; } + virtual time_t getCreationDate() const { return 0; } + virtual PermissionMask getPermissionMask() const { return PERM_ALL; } + virtual LLFolderType::EType getPreferredType() const { return LLFolderType::FT_NONE; } + virtual LLPointer<LLUIImage> getIcon() const { return NULL; } + virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } + virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } + virtual std::string getLabelSuffix() const { return LLStringUtil::null; } + virtual BOOL isItemRenameable() const { return FALSE; } + virtual BOOL renameItem(const std::string& new_name) { return FALSE; } + virtual BOOL isItemMovable( void ) const { return FALSE; } + virtual BOOL isItemRemovable( void ) const { return FALSE; } + virtual BOOL isItemInTrash( void) const { return FALSE; } + virtual BOOL removeItem() { return FALSE; } + virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) { } + virtual void move( LLFolderViewEventListener* parent_listener ) { } + virtual BOOL isItemCopyable() const { return FALSE; } + virtual BOOL copyToClipboard() const { return FALSE; } + virtual void cutToClipboard() { } + virtual BOOL isClipboardPasteable() const { return FALSE; } + virtual void pasteFromClipboard() { } + virtual void pasteLinkFromClipboard() { } + virtual void buildContextMenu(LLMenuGL& menu, U32 flags) { } + virtual BOOL isUpToDate() const { return TRUE; } + virtual BOOL hasChildren() const { return FALSE; } + virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; } + virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } + + // The action callbacks (or so we think...) + virtual void performAction(LLInventoryModel* model, std::string action); + virtual void openItem( void ); + virtual void closeItem( void ); + virtual void previewItem( void ); + virtual void selectItem(void); + virtual void showProperties(void); + + // This method should be called when a drag begins. returns TRUE + // if the drag can begin, otherwise FALSE. + virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const { return FALSE; } + + // This method will be called to determine if a drop can be + // performed, and will set drop to TRUE if a drop is + // requested. Returns TRUE if a drop is possible/happened, + // otherwise FALSE. + virtual BOOL dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + std::string& tooltip_msg) { return FALSE; } +private: + std::string mName; + LLUUID mUUID; +}; + // CHUI-137 : End + class LLIMFloaterContainer : public LLMultiFloater { public: @@ -64,6 +138,8 @@ public: virtual void setMinimized(BOOL b); void collapseMessagesPane(bool collapse); + + LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; @@ -84,6 +160,11 @@ private: LLLayoutPanel* mMessagesPane; LLLayoutPanel* mConversationsPane; LLLayoutStack* mConversationsStack; + + // CHUI-137 : Data + LLPanel* mConversationsListPanel; // The widget we add list item to (title of each conversation) + conversations_items_list_t mConversationsItems; + conversations_widgets_list_t mConversationsWidgets; }; #endif // LL_LLIMFLOATERCONTAINER_H -- cgit v1.2.3 From 8353a1ab4d9dab891535b766329c5d92323fe3b6 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Fri, 8 Jun 2012 01:08:56 +0300 Subject: CHUI-120 WIP Added avatar picker that allows to add other users to an existing chat if they don't participate in it already. --- indra/newview/llimfloater.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++ indra/newview/llimfloater.h | 4 +++ 2 files changed, 73 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index f04fecca26..f49375798d 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -33,12 +33,14 @@ #include "llagent.h" #include "llappviewer.h" +#include "llavataractions.h" #include "llavatarnamecache.h" #include "llbutton.h" #include "llchannelmanager.h" #include "llchiclet.h" #include "llchicletbar.h" #include "llfloaterreg.h" +#include "llfloateravatarpicker.h" #include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container #include "llinventoryfunctions.h" //#include "lllayoutstack.h" @@ -309,6 +311,7 @@ BOOL LLIMFloater::postBuild() mTypingStart = LLTrans::getString("IM_typing_start_string"); + childSetAction("add_btn", boost::bind(&LLIMFloater::onAddButtonClicked, this)); childSetAction("voice_call_btn", boost::bind(&LLIMFloater::onCallButtonClicked, this)); LLVoiceClient::getInstance()->addObserver(this); @@ -321,6 +324,72 @@ BOOL LLIMFloater::postBuild() return TRUE; } +void LLIMFloater::onAddButtonClicked() +{ + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::onAvatarPicked, this, _1, _2), TRUE, TRUE); + if (!picker) + { + return; + } + + // Need to disable 'ok' button when selected users are already in conversation. + picker->setOkBtnEnableCb(boost::bind(&LLIMFloater::canAddSelectedToChat, this, _1)); + LLFloater* root_floater = gFloaterView->getParentFloater(this); + if (root_floater) + { + root_floater->addDependentFloater(picker); + } +} + +void LLIMFloater::onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names) +{ + if (mIsP2PChat) + { + mStartConferenceInSameFloater = true; + onClose(false); + + uuid_vec_t temp_ids; + temp_ids.push_back(mOtherParticipantUUID); + temp_ids.insert(temp_ids.end(), ids.begin(), ids.end()); + + LLAvatarActions::startConference(temp_ids, mSessionID); + } + else + { + inviteToSession(ids); + } +} + +bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) +{ + if (!mSession + || mDialog == IM_SESSION_GROUP_START + || mDialog == IM_SESSION_INVITE && gAgent.isInGroup(mSessionID)) + { + return false; + } + + for (uuid_vec_t::const_iterator id = uuids.begin(); + id != uuids.end(); ++id) + { + if (*id == mOtherParticipantUUID) + { + return false; + } + + for (uuid_vec_t::const_iterator target_id = mSession->mInitialTargetIDs.begin(); + target_id != mSession->mInitialTargetIDs.end(); ++target_id) + { + if (*id == *target_id) + { + return false; + } + } + } + + return true; +} + void LLIMFloater::boundVoiceChannel() { LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index b97d4ab90c..b5822db8dd 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -147,6 +147,10 @@ private: static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); void setTyping(bool typing); + void onAddButtonClicked(); + void onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names); + bool canAddSelectedToChat(const uuid_vec_t& uuids); + void onCallButtonClicked(); // set the enable/disable state for the Call button -- cgit v1.2.3 From 9b92235291382deac15b860efa281f625d2173dd Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Fri, 8 Jun 2012 01:08:58 +0300 Subject: CHUI-120 WIP Added conversations participants drag and drop from avatar lists to IM floaters. - Added new drag and drop type DAD_PERSON and source SOURCE_PEOPLE to avoid highliting the toolbars when using SOURCE_VIEWER. - Disabled calling card drop support as it is considered obsolete. --- indra/llcommon/llassettype.cpp | 1 + indra/llcommon/llassettype.h | 3 ++ indra/llcommon/stdenums.h | 3 +- indra/llinventory/llinventorytype.cpp | 3 +- indra/llinventory/llinventorytype.h | 3 +- indra/newview/llavatarlistitem.cpp | 58 +++++++++++++++++++++ indra/newview/llavatarlistitem.h | 3 ++ indra/newview/llimconversation.cpp | 12 ++--- indra/newview/llimfloater.cpp | 97 +++++++++++------------------------ indra/newview/llimfloater.h | 12 ++--- indra/newview/lltoolbarview.cpp | 2 +- indra/newview/lltooldraganddrop.cpp | 2 +- indra/newview/lltooldraganddrop.h | 3 +- indra/newview/llviewerassettype.cpp | 2 + 14 files changed, 120 insertions(+), 84 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 5e566d6c7c..5ae2df3994 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -95,6 +95,7 @@ LLAssetDictionary::LLAssetDictionary() addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "sym folder link", false, false, true)); addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false)); addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false)); + addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false)); addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE)); }; diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index d538accbf7..69b01731e5 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -112,6 +112,9 @@ public: AT_WIDGET = 40, // UI Widget: this is *not* an inventory asset type, only a viewer side asset (e.g. button, other ui items...) + AT_PERSON = 45, + // A user uuid which is not an inventory asset type, used in viewer only for adding a person to a chat via drag and drop. + AT_MESH = 49, // Mesh data in our proprietary SLM format diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h index 40b3364b36..efcbe76795 100644 --- a/indra/llcommon/stdenums.h +++ b/indra/llcommon/stdenums.h @@ -51,7 +51,8 @@ enum EDragAndDropType DAD_LINK = 14, DAD_MESH = 15, DAD_WIDGET = 16, - DAD_COUNT = 17, // number of types in this enum + DAD_PERSON = 17, + DAD_COUNT = 18, // number of types in this enum }; // Reasons for drags to be denied. diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index 8282d79b67..8807b36117 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -85,6 +85,7 @@ LLInventoryDictionary::LLInventoryDictionary() addEntry(LLInventoryType::IT_GESTURE, new InventoryEntry("gesture", "gesture", 1, LLAssetType::AT_GESTURE)); addEntry(LLInventoryType::IT_MESH, new InventoryEntry("mesh", "mesh", 1, LLAssetType::AT_MESH)); addEntry(LLInventoryType::IT_WIDGET, new InventoryEntry("widget", "widget", 1, LLAssetType::AT_WIDGET)); + addEntry(LLInventoryType::IT_PERSON, new InventoryEntry("person", "person", 1, LLAssetType::AT_PERSON)); } @@ -140,7 +141,7 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] = LLInventoryType::IT_NONE, // 42 AT_NONE LLInventoryType::IT_NONE, // 43 AT_NONE LLInventoryType::IT_NONE, // 44 AT_NONE - LLInventoryType::IT_NONE, // 45 AT_NONE + LLInventoryType::IT_PERSON, // 45 AT_PERSON LLInventoryType::IT_NONE, // 46 AT_NONE LLInventoryType::IT_NONE, // 47 AT_NONE LLInventoryType::IT_NONE, // 48 AT_NONE diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h index 4d1e0db040..645ebab234 100644 --- a/indra/llinventory/llinventorytype.h +++ b/indra/llinventory/llinventorytype.h @@ -63,7 +63,8 @@ public: IT_GESTURE = 20, IT_MESH = 22, IT_WIDGET = 23, - IT_COUNT = 24, + IT_PERSON = 24, + IT_COUNT = 25, IT_NONE = -1 }; diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 30eecfe323..e670d3ea04 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -31,6 +31,7 @@ #include "llavatarlistitem.h" #include "llbutton.h" +#include "llclipboard.h" #include "llfloaterreg.h" #include "lltextutil.h" @@ -38,6 +39,7 @@ #include "llavatarnamecache.h" #include "llavatariconctrl.h" #include "lloutputmonitorctrl.h" +#include "lltooldraganddrop.h" bool LLAvatarListItem::sStaticInitialized = false; S32 LLAvatarListItem::sLeftPadding = 0; @@ -334,6 +336,62 @@ BOOL LLAvatarListItem::handleDoubleClick(S32 x, S32 y, MASK mask) return LLPanel::handleDoubleClick(x, y, mask); } +BOOL LLAvatarListItem::handleMouseDown(S32 x, S32 y, MASK mask) +{ + if (LLUICtrl::handleMouseDown(x, y, mask)) + { + return TRUE; + } + + gFocusMgr.setMouseCapture(this); + + S32 screen_x; + S32 screen_y; + localPointToScreen(x, y, &screen_x, &screen_y); + LLToolDragAndDrop::getInstance()->setDragStart(screen_x, screen_y); + + return TRUE; +} + +BOOL LLAvatarListItem::handleMouseUp( S32 x, S32 y, MASK mask ) +{ + if (LLUICtrl::childrenHandleMouseUp(x, y, mask)) + { + return TRUE; + } + + if(hasMouseCapture()) + { + gFocusMgr.setMouseCapture(NULL); + } + return TRUE; +} + +BOOL LLAvatarListItem::handleHover(S32 x, S32 y, MASK mask) +{ + bool handled = hasMouseCapture(); + if(handled) + { + S32 screen_x; + S32 screen_y; + localPointToScreen(x, y, &screen_x, &screen_y); + + if(LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y)) + { + // First, create the global drag and drop object + std::vector<EDragAndDropType> types; + uuid_vec_t cargo_ids; + types.push_back(DAD_PERSON); + cargo_ids.push_back(mAvatarId); + gClipboard.setSourceObject(mAvatarId, LLAssetType::AT_PERSON); + LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_PEOPLE; + LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, src); + } + } + + return handled; +} + void LLAvatarListItem::setValue( const LLSD& value ) { if (!value.isMap()) return;; diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index c95ac39696..28a50870d4 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -112,6 +112,9 @@ public: void onProfileBtnClick(); /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); protected: /** diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index d8c7c63e9e..ec2a9196d4 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -83,8 +83,10 @@ BOOL LLIMConversation::postBuild() mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this)); mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); - mParticipantListPanel->setVisible( - mIsNearbyChat? false : gSavedSettings.getBOOL("IMShowControlPanel")); + + // Show the participants list in torn off floaters only. + mParticipantListPanel->setVisible(gSavedSettings.getBOOL("IMShowControlPanel") + && !mIsNearbyChat); // *TODO: temporarily disabled for Nearby chat mExpandCollapseBtn->setImageOverlay( getString(mParticipantListPanel->getVisible() ? "collapse_icon" : "expand_icon")); mExpandCollapseBtn->setEnabled(!mIsP2PChat); @@ -209,12 +211,10 @@ void LLIMConversation::updateHeaderAndToolbar() } bool is_control_panel_visible = false; - if (!mIsP2PChat) - { // Control panel should be visible only in torn off floaters. is_control_panel_visible = !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel"); - mParticipantListPanel->setVisible(is_control_panel_visible); - } + mParticipantListPanel->setVisible(!mIsP2PChat && is_control_panel_visible + && !mIsNearbyChat); // *TODO: temporarily disabled for Nearby chat // Display collapse image (<<) if the floater is hosted // or if it is torn off but has an open control panel. diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index f49375798d..6a510c4df1 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -986,90 +986,55 @@ void LLIMFloater::processSessionUpdate(const LLSD& session_update) } } -BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, EDragAndDropType cargo_type, - void *cargo_data, EAcceptance *accept, - std::string& tooltip_msg) +// virtual +BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) { - if (mDialog == IM_NOTHING_SPECIAL) - { - LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, - cargo_type, cargo_data, accept); - } - - // handle case for dropping calling cards (and folders of calling cards) onto invitation panel for invites - else if (isInviteAllowed()) + if (cargo_type == DAD_PERSON) { - *accept = ACCEPT_NO; - - if (cargo_type == DAD_CALLINGCARD) + if (dropPerson(static_cast<LLInventoryObject*>(cargo_data), drop)) { - if (dropCallingCard((LLInventoryItem*) cargo_data, drop)) - { - *accept = ACCEPT_YES_MULTI; - } + *accept = ACCEPT_YES_MULTI; } - else if (cargo_type == DAD_CATEGORY) + else { - if (dropCategory((LLInventoryCategory*) cargo_data, drop)) - { - *accept = ACCEPT_YES_MULTI; - } + *accept = ACCEPT_NO; } } return TRUE; } -BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop) +bool LLIMFloater::dropPerson(LLInventoryObject* item, bool drop) { - BOOL rv = isInviteAllowed(); - if (rv && item && item->getCreatorUUID().notNull()) + bool res = item && item->getUUID().notNull(); + if(res) { - if (drop) - { - uuid_vec_t ids; - ids.push_back(item->getCreatorUUID()); - inviteToSession(ids); - } - } - else - { - // set to false if creator uuid is null. - rv = FALSE; - } - return rv; -} + uuid_vec_t ids; + ids.push_back(item->getUUID()); -BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop) -{ - BOOL rv = isInviteAllowed(); - if (rv && category) - { - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLUniqueBuddyCollector buddies; - gInventory.collectDescendentsIf(category->getUUID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - buddies); - S32 count = items.count(); - if (count == 0) - { - rv = FALSE; - } - else if (drop) + res = canAddSelectedToChat(ids); + if(res && drop) { - uuid_vec_t ids; - ids.reserve(count); - for (S32 i = 0; i < count; ++i) + if (mIsP2PChat) { - ids.push_back(items.get(i)->getCreatorUUID()); + mStartConferenceInSameFloater = true; + onClose(false); + + ids.push_back(mOtherParticipantUUID); + + LLAvatarActions::startConference(ids, mSessionID); + } + else + { + inviteToSession(ids); } - inviteToSession(ids); } } - return rv; + + return res; } BOOL LLIMFloater::isInviteAllowed() const diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index b5822db8dd..b02f779637 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -114,10 +114,11 @@ public: void processAgentListUpdates(const LLSD& body); void processSessionUpdate(const LLSD& session_update); - BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, EDragAndDropType cargo_type, - void *cargo_data, EAcceptance *accept, - std::string& tooltip_msg); + /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); //used as a callback on receiving new IM message @@ -137,8 +138,7 @@ private: // For display name lookups for IM window titles void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); - BOOL dropCallingCard(LLInventoryItem* item, BOOL drop); - BOOL dropCategory(LLInventoryCategory* category, BOOL drop); + bool dropPerson(LLInventoryObject* item, bool drop); BOOL isInviteAllowed() const; BOOL inviteToSession(const uuid_vec_t& agent_ids); diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp index eccb2cf2f1..e71cf66a96 100644 --- a/indra/newview/lltoolbarview.cpp +++ b/indra/newview/lltoolbarview.cpp @@ -603,7 +603,7 @@ BOOL LLToolBarView::handleDragTool( S32 x, S32 y, const LLUUID& uuid, LLAssetTyp BOOL LLToolBarView::handleDropTool( void* cargo_data, S32 x, S32 y, LLToolBar* toolbar) { BOOL handled = FALSE; - LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; + LLInventoryObject* inv_item = static_cast<LLInventoryObject*>(cargo_data); LLAssetType::EType type = inv_item->getType(); if (type == LLAssetType::AT_WIDGET) diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index c7ab934f9e..ee79a53f43 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -2526,7 +2526,7 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory( item = (LLViewerInventoryItem*)preview->getDragItem(); } } - else if(mSource == SOURCE_VIEWER) + else if(mSource == SOURCE_VIEWER || mSource == SOURCE_PEOPLE) { item = (LLViewerInventoryItem*)gClipboard.getSourceObject(); } diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 245c2a23e6..44980ffdb3 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -67,7 +67,8 @@ public: SOURCE_WORLD, SOURCE_NOTECARD, SOURCE_LIBRARY, - SOURCE_VIEWER + SOURCE_VIEWER, + SOURCE_PEOPLE }; void beginDrag(EDragAndDropType type, diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp index a4b1c2155f..08ba5a5f25 100644 --- a/indra/newview/llviewerassettype.cpp +++ b/indra/newview/llviewerassettype.cpp @@ -83,6 +83,8 @@ LLViewerAssetDictionary::LLViewerAssetDictionary() addEntry(LLViewerAssetType::AT_WIDGET, new ViewerAssetEntry(DAD_WIDGET)); + addEntry(LLViewerAssetType::AT_PERSON, new ViewerAssetEntry(DAD_PERSON)); + addEntry(LLViewerAssetType::AT_NONE, new ViewerAssetEntry(DAD_NONE)); }; -- cgit v1.2.3 From f7f85dd0dda563a9fb49ed65b193a9ea98da9ba2 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Fri, 8 Jun 2012 01:09:00 +0300 Subject: CHUI-122 FIX Add button enabled only for P2P and ad hoc IM sessions. --- indra/newview/llimfloater.cpp | 7 ++++++- indra/newview/skins/default/xui/en/floater_im_session.xml | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 6a510c4df1..dcd19b5856 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -311,7 +311,12 @@ BOOL LLIMFloater::postBuild() mTypingStart = LLTrans::getString("IM_typing_start_string"); - childSetAction("add_btn", boost::bind(&LLIMFloater::onAddButtonClicked, this)); + LLButton* add_btn = getChild<LLButton>("add_btn"); + + // Allow to add chat participants depending on the session type + add_btn->setEnabled(isInviteAllowed()); + add_btn->setClickedCallback(boost::bind(&LLIMFloater::onAddButtonClicked, this)); + childSetAction("voice_call_btn", boost::bind(&LLIMFloater::onCallButtonClicked, this)); LLVoiceClient::getInstance()->addObserver(this); diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index fc5b6b10af..21fc2d25d4 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -59,6 +59,7 @@ top="5" width="31" /> <button + enabled="false" follows="top|left" height="25" image_hover_unselected="Toolbar_Middle_Over" -- cgit v1.2.3 From 33adfe09474c58075d58feff1fc34e24503d3e80 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 8 Jun 2012 19:51:56 +0300 Subject: CHUI-103 FIXED Added a square brackets to system messages; changed a default color for user messages --- indra/newview/llchathistory.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index cfc70a1b0e..dcd6d25888 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -737,7 +737,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL LLViewerChat::getChatColor(chat,txt_color); LLFontGL* fontp = LLViewerChat::getChatFont(); std::string font_name = LLFontGL::nameFromFont(fontp); - std::string font_size = LLFontGL::sizeFromFont(fontp); + std::string font_size = LLFontGL::sizeFromFont(fontp); + LLStyle::Params style_params; style_params.color(txt_color); style_params.readonly_color(txt_color); @@ -773,8 +774,9 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL // We graying out chat history by graying out messages that contains full date in a time string if (message_from_log) { - style_params.color(LLColor4::grey); - style_params.readonly_color(LLColor4::grey); + txt_color = LLColor4::grey; + style_params.color(txt_color); + style_params.readonly_color(txt_color); } bool prependNewLineState = mEditor->getText().size() != 0; @@ -786,7 +788,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL LLStyle::Params timestamp_style(style_params); - // timestams showing + // out of the timestamp if (args["show_time"].asBoolean()) { if (!message_from_log) @@ -799,6 +801,13 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL prependNewLineState = false; } + // out the opening square bracket (if need) + if (square_brackets) + { + mEditor->appendText("[", prependNewLineState, style_params); + prependNewLineState = false; + } + // names showing if (args["show_names_for_p2p_conv"].asBoolean() && utf8str_trim(chat.mFromName).size() != 0) { @@ -947,7 +956,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (square_brackets) { - message = "[" + message + "]"; + message += "]"; } mEditor->appendText(message, prependNewLineState, style_params); -- cgit v1.2.3 From 3f7ecef1968b9087ba7c885a2dd6213120dfa547 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 8 Jun 2012 11:31:50 -0700 Subject: CHUI-137 : Fix crasher in item drawing --- indra/newview/llfolderviewitem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 126de95551..73715c78df 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -864,8 +864,8 @@ void LLFolderViewItem::draw() const S32 FOCUS_LEFT = 1; const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - const BOOL in_inventory = getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getRootFolderID()); - const BOOL in_library = getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getLibraryRootFolderID()); + const BOOL in_inventory = getListener() && getListener()->getUUID().notNull() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getRootFolderID()); + const BOOL in_library = getListener() && getListener()->getUUID().notNull() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getLibraryRootFolderID()); //--------------------------------------------------------------------------------// // Draw open folder arrow -- cgit v1.2.3 From 18077965146922efb6541734bc3f7307efb4f586 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 8 Jun 2012 12:15:36 -0700 Subject: Fix post merge build issue: take clipboard changes into account --- indra/newview/llavatarlistitem.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index e670d3ea04..7ba63bc4a2 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -383,7 +383,6 @@ BOOL LLAvatarListItem::handleHover(S32 x, S32 y, MASK mask) uuid_vec_t cargo_ids; types.push_back(DAD_PERSON); cargo_ids.push_back(mAvatarId); - gClipboard.setSourceObject(mAvatarId, LLAssetType::AT_PERSON); LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_PEOPLE; LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, src); } -- cgit v1.2.3 From 1aba6c119ef05a4cfd91325c8455dc8c60098746 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 8 Jun 2012 17:26:13 -0700 Subject: CHUI-137 : Implement conversation list, temporary solution: add but doesn't take out items from the list --- indra/newview/llfolderviewitem.cpp | 32 +++++++++++++++++++++----------- indra/newview/llimfloatercontainer.cpp | 15 +++++++++------ indra/newview/llimfloatercontainer.h | 4 ++-- 3 files changed, 32 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 73715c78df..0800e0baa2 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -377,7 +377,10 @@ void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus) { - getRoot()->setSelection(selection, openitem, take_keyboard_focus); + if (getRoot()) + { + getRoot()->setSelection(selection, openitem, take_keyboard_focus); + } } // helper function to change the selection from the root. @@ -754,7 +757,10 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) } else { - getRoot()->setShowSelectionContext(FALSE); + if (getRoot()) + { + getRoot()->setShowSelectionContext(FALSE); + } gViewerWindow->setCursor(UI_CURSOR_ARROW); // let parent handle this then... return FALSE; @@ -797,7 +803,10 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) if( hasMouseCapture() ) { - getRoot()->setShowSelectionContext(FALSE); + if (getRoot()) + { + getRoot()->setShowSelectionContext(FALSE); + } gFocusMgr.setMouseCapture( NULL ); } return TRUE; @@ -864,8 +873,9 @@ void LLFolderViewItem::draw() const S32 FOCUS_LEFT = 1; const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - const BOOL in_inventory = getListener() && getListener()->getUUID().notNull() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getRootFolderID()); - const BOOL in_library = getListener() && getListener()->getUUID().notNull() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getLibraryRootFolderID()); + const LLUUID uuid = (getListener() ? getListener()->getUUID() : LLUUID::null); + const BOOL in_inventory = (uuid.notNull() ? gInventory.isObjectDescendentOf(uuid, gInventory.getRootFolderID()) : FALSE); + const BOOL in_library = (uuid.notNull() ? gInventory.isObjectDescendentOf(uuid, gInventory.getLibraryRootFolderID()) : FALSE); //--------------------------------------------------------------------------------// // Draw open folder arrow @@ -885,8 +895,8 @@ void LLFolderViewItem::draw() //--------------------------------------------------------------------------------// // Draw highlight for selected items // - const BOOL show_context = getRoot()->getShowSelectionContext(); - const BOOL filled = show_context || (getRoot()->getParentPanel()->hasFocus()); // If we have keyboard focus, draw selection filled + const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); + const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled const S32 focus_top = getRect().getHeight(); const S32 focus_bottom = getRect().getHeight() - mItemHeight; const bool folder_open = (getRect().getHeight() > mItemHeight + 4); @@ -897,8 +907,8 @@ void LLFolderViewItem::draw() if (!mIsCurSelection) { // do time-based fade of extra objects - F32 fade_time = getRoot()->getSelectionFadeElapsedTime(); - if (getRoot()->getShowSingleSelection()) + F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); + if (getRoot() && getRoot()->getShowSingleSelection()) { // fading out bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); @@ -1009,7 +1019,7 @@ void LLFolderViewItem::draw() //--------------------------------------------------------------------------------// // Highlight filtered text // - if (getRoot()->getDebugFilters()) + if (getRoot() && getRoot()->getDebugFilters()) { if (!getFiltered() && !possibly_has_children) { @@ -1070,7 +1080,7 @@ void LLFolderViewItem::draw() if (mStringMatchOffset != std::string::npos) { // don't draw backgrounds for zero-length strings - S32 filter_string_length = getRoot()->getFilterSubString().size(); + S32 filter_string_length = (getRoot() ? getRoot()->getFilterSubString().size() : 0); if (filter_string_length > 0) { std::string combined_string = mLabel + mLabelSuffix; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 134d345148..cd19105860 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -115,19 +115,22 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); // CHUI-137 - llinfos << "Merov debug : addFloater, title = " << floaterp->getTitle() << llendl; // Create a conversation item - LLConversationItem item(floaterp->getTitle()); - // Add it to the list + LLConversationItem* item = new LLConversationItem(floaterp->getTitle()); mConversationsItems.push_back(item); // Create a widget from it - LLFolderViewItem* widget = createConversationItemWidget(&item); - // Add it to the list of widgets + LLFolderViewItem* widget = createConversationItemWidget(item); mConversationsWidgets.push_back(widget); // Add it to the UI widget->setVisible(TRUE); mConversationsListPanel->addChild(widget); - // Reposition it... + LLRect panel_rect = mConversationsListPanel->getRect(); + S32 item_height = 16; + S32 index = mConversationsWidgets.size() - 1; + widget->setRect(LLRect(0, + panel_rect.getHeight() - item_height*index, + panel_rect.getWidth(), + panel_rect.getHeight() - item_height*(index+1))); // CHUI-137 : end LLView* floater_contents = floaterp->getChild<LLView>("contents_view"); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 5cfdb41ad3..d04ac873fa 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -46,7 +46,7 @@ class LLTabContainer; // CHUI-137 : Temporary implementation of conversations list class LLConversationItem; -typedef std::list<LLConversationItem> conversations_items_list_t; +typedef std::list<LLConversationItem*> conversations_items_list_t; typedef std::list<LLFolderViewItem*> conversations_widgets_list_t; // Conversation items: we hold a list of those and create an LLFolderViewItem widget for each that we tuck @@ -110,7 +110,7 @@ public: std::string& tooltip_msg) { return FALSE; } private: std::string mName; - LLUUID mUUID; + const LLUUID mUUID; }; // CHUI-137 : End -- cgit v1.2.3 From e286330365576e67fa9b59166f6019e89f09f3cf Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 8 Jun 2012 17:58:15 -0700 Subject: CHUI-137 : Fix build error after merge --- indra/newview/llimfloatercontainer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index d04ac873fa..84b1c864cc 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -78,7 +78,7 @@ public: virtual void move( LLFolderViewEventListener* parent_listener ) { } virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL copyToClipboard() const { return FALSE; } - virtual void cutToClipboard() { } + virtual BOOL cutToClipboard() const { return FALSE; } virtual BOOL isClipboardPasteable() const { return FALSE; } virtual void pasteFromClipboard() { } virtual void pasteLinkFromClipboard() { } -- cgit v1.2.3 From ec726c3a3ecbefd34008cd735f455c7947b67246 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 11 Jun 2012 17:04:58 +0300 Subject: CHUI-119 WIP Fixed some bugs --- indra/newview/llstartup.cpp | 6 +++++- indra/newview/skins/default/xui/en/floater_im_session.xml | 7 +++---- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 320a602916..65fd6d7019 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -63,7 +63,7 @@ #include "llmemorystream.h" #include "llmessageconfig.h" #include "llmoveview.h" -#include "llnearbychat.h" +#include "llimfloatercontainer.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llteleporthistory.h" @@ -1376,6 +1376,10 @@ bool idle_startup() LLVoiceClient::getInstance()->updateSettings(); display_startup(); + // create a container's instance for start a controlling conversation windows + // by the voice's events + LLIMFloaterContainer::getInstance(); + // *Note: this is where gWorldMap used to be initialized. // register null callbacks for audio until the audio system is initialized diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 21fc2d25d4..e5e005e36f 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -236,10 +236,9 @@ </layout_panel> </layout_stack> </panel> - <panel width="228" + <panel width="225" height="31" - left="4" - right="4" + left="4" name="bottom_panel" bottom="-1" follows="left|right|bottom" @@ -254,7 +253,7 @@ layout="bottomleft" name="chat_editor" tab_group="3" - width="240"> + width="220"> </line_editor> </panel> </layout_panel> -- cgit v1.2.3 From db67c21f901800d27c9dd2ea2ce6134dc3bd33f1 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 11 Jun 2012 17:25:17 -0700 Subject: CHUI-137 : Implemented switch conversation in the conversation list --- indra/newview/llfolderviewitem.cpp | 4 ++++ indra/newview/llimfloatercontainer.cpp | 20 +++++++++++++------- indra/newview/llimfloatercontainer.h | 5 ++++- 3 files changed, 21 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index d7d5195c14..8ae779326c 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -387,6 +387,10 @@ void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, { getRoot()->setSelection(selection, openitem, take_keyboard_focus); } + else if (mListener) + { + mListener->selectItem(); + } } // helper function to change the selection from the root. diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index cd19105860..9c6cee6cb5 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -85,6 +85,7 @@ BOOL LLIMFloaterContainer::postBuild() void LLIMFloaterContainer::onOpen(const LLSD& key) { + llinfos << "Merov debug : onOpen, key = " << key.asUUID() << llendl; LLMultiFloater::onOpen(key); /* if (key.isDefined()) @@ -114,9 +115,11 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); + LLUUID session_id = floaterp->getKey(); + // CHUI-137 // Create a conversation item - LLConversationItem* item = new LLConversationItem(floaterp->getTitle()); + LLConversationItem* item = new LLConversationItem(floaterp->getTitle(),session_id, floaterp, this); mConversationsItems.push_back(item); // Create a widget from it LLFolderViewItem* widget = createConversationItemWidget(item); @@ -139,8 +142,6 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, // so reshape floater contents to occupy the header space floater_contents->setShape(floaterp->getRect()); - LLUUID session_id = floaterp->getKey(); - LLIconCtrl* icon = 0; if(gAgent.isInGroup(session_id, TRUE)) @@ -164,6 +165,8 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, session_id)); } mTabContainer->setTabImage(floaterp, icon); + + llinfos << "Merov debug : addFloater, title = " << floaterp->getTitle() << ", uuid = " << session_id << llendl; } // virtual @@ -171,7 +174,7 @@ void LLIMFloaterContainer::removeFloater(LLFloater* floaterp) { LLMultiFloater::removeFloater(floaterp); - llinfos << "Merov debug : removeFloater, title = " << floaterp->getTitle() << llendl; + llinfos << "Merov debug : removeFloater, title = " << floaterp->getTitle() << ", uuid = " << floaterp->getKey() << llendl; LLRect contents_rect = floaterp->getRect(); @@ -355,9 +358,11 @@ LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversat } // Conversation items -LLConversationItem::LLConversationItem(std::string name) : +LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp) : mName(name), - mUUID(LLUUID::null) + mUUID(uuid), + mFloater(floaterp), + mContainer(containerp) { if (name == "") mName = "Nearby Chat"; @@ -386,7 +391,8 @@ void LLConversationItem::previewItem( void ) void LLConversationItem::selectItem(void) { - llinfos << "Merov debug : selectItem, title = " << mName << llendl; + llinfos << "Merov debug : selectItem, title = " << mName << ", uuid = " << mUUID << llendl; + mContainer->selectFloater(mFloater); } void LLConversationItem::showProperties(void) diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 84b1c864cc..afb65671ae 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -45,6 +45,7 @@ class LLTabContainer; // CHUI-137 : Temporary implementation of conversations list class LLConversationItem; +class LLIMFloaterContainer; typedef std::list<LLConversationItem*> conversations_items_list_t; typedef std::list<LLFolderViewItem*> conversations_widgets_list_t; @@ -54,7 +55,7 @@ typedef std::list<LLFolderViewItem*> conversations_widgets_list_t; class LLConversationItem : public LLFolderViewEventListener { public: - LLConversationItem(std::string name); + LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp); virtual ~LLConversationItem() {} // Stub those things we won't really be using in this conversation context @@ -111,6 +112,8 @@ public: private: std::string mName; const LLUUID mUUID; + LLFloater* mFloater; + LLIMFloaterContainer* mContainer; }; // CHUI-137 : End -- cgit v1.2.3 From 0e2f5c2ebad0a19e9c5e151a4ac3ae7321f2f296 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 11 Jun 2012 22:12:43 -0700 Subject: CHUI-137 : Implemented tear off and close of conversation in the list --- indra/newview/llimfloatercontainer.cpp | 56 ++++++++++++++++++++++------------ indra/newview/llimfloatercontainer.h | 8 ++--- 2 files changed, 41 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 9c6cee6cb5..9084c07cc7 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -85,7 +85,6 @@ BOOL LLIMFloaterContainer::postBuild() void LLIMFloaterContainer::onOpen(const LLSD& key) { - llinfos << "Merov debug : onOpen, key = " << key.asUUID() << llendl; LLMultiFloater::onOpen(key); /* if (key.isDefined()) @@ -120,10 +119,10 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, // CHUI-137 // Create a conversation item LLConversationItem* item = new LLConversationItem(floaterp->getTitle(),session_id, floaterp, this); - mConversationsItems.push_back(item); + mConversationsItems[session_id] = item; // Create a widget from it LLFolderViewItem* widget = createConversationItemWidget(item); - mConversationsWidgets.push_back(widget); + mConversationsWidgets[session_id] = widget; // Add it to the UI widget->setVisible(TRUE); mConversationsListPanel->addChild(widget); @@ -165,8 +164,6 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, session_id)); } mTabContainer->setTabImage(floaterp, icon); - - llinfos << "Merov debug : addFloater, title = " << floaterp->getTitle() << ", uuid = " << session_id << llendl; } // virtual @@ -174,8 +171,34 @@ void LLIMFloaterContainer::removeFloater(LLFloater* floaterp) { LLMultiFloater::removeFloater(floaterp); - llinfos << "Merov debug : removeFloater, title = " << floaterp->getTitle() << ", uuid = " << floaterp->getKey() << llendl; - + // CHUI-137 : Clean up the conversations list + LLUUID session_id = floaterp->getKey(); + // Delete the widget and the associated conversation item + // Note : since the mConversationsItems is a listener to the widget, deleting the widget also + // delete its listener + conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(session_id); + if (widget_it != mConversationsWidgets.end()) + { + LLFolderViewItem* widget = widget_it->second; + delete widget; + } + // Suppress the conversation items and widgets from their respective maps + mConversationsItems.erase(session_id); + mConversationsWidgets.erase(session_id); + // Reposition the leftover conversation items + LLRect panel_rect = mConversationsListPanel->getRect(); + S32 item_height = 16; + int index = 0; + for (widget_it = mConversationsWidgets.begin(); widget_it != mConversationsWidgets.end(); ++widget_it, ++index) + { + LLFolderViewItem* widget = widget_it->second; + widget->setRect(LLRect(0, + panel_rect.getHeight() - item_height*index, + panel_rect.getWidth(), + panel_rect.getHeight() - item_height*(index+1))); + } + // CHUI-137 + LLRect contents_rect = floaterp->getRect(); // reduce the floater contents height by header height @@ -364,41 +387,36 @@ LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLF mFloater(floaterp), mContainer(containerp) { + // Hack: the nearby chat has no name so we catch that and impose one if (name == "") mName = "Nearby Chat"; } // Virtual action callbacks +void LLConversationItem::selectItem(void) +{ + // Select the conversation floater that is being selected + mContainer->selectFloater(mFloater); +} + void LLConversationItem::performAction(LLInventoryModel* model, std::string action) { - llinfos << "Merov debug : performAction, title = " << mName << ", action = " << action << llendl; } void LLConversationItem::openItem( void ) { - llinfos << "Merov debug : openItem, title = " << mName << llendl; } void LLConversationItem::closeItem( void ) { - llinfos << "Merov debug : closeItem, title = " << mName << llendl; } void LLConversationItem::previewItem( void ) { - llinfos << "Merov debug : previewItem, title = " << mName << llendl; -} - -void LLConversationItem::selectItem(void) -{ - llinfos << "Merov debug : selectItem, title = " << mName << ", uuid = " << mUUID << llendl; - mContainer->selectFloater(mFloater); } void LLConversationItem::showProperties(void) { - llinfos << "Merov debug : showProperties, title = " << mName << llendl; } - // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index afb65671ae..3df5a07df8 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -47,8 +47,8 @@ class LLTabContainer; class LLConversationItem; class LLIMFloaterContainer; -typedef std::list<LLConversationItem*> conversations_items_list_t; -typedef std::list<LLFolderViewItem*> conversations_widgets_list_t; +typedef std::map<LLUUID, LLConversationItem*> conversations_items_map; +typedef std::map<LLUUID, LLFolderViewItem*> conversations_widgets_map; // Conversation items: we hold a list of those and create an LLFolderViewItem widget for each that we tuck // into the mConversationsListPanel. @@ -166,8 +166,8 @@ private: // CHUI-137 : Data LLPanel* mConversationsListPanel; // The widget we add list item to (title of each conversation) - conversations_items_list_t mConversationsItems; - conversations_widgets_list_t mConversationsWidgets; + conversations_items_map mConversationsItems; + conversations_widgets_map mConversationsWidgets; }; #endif // LL_LLIMFLOATERCONTAINER_H -- cgit v1.2.3 From 9993fa550ab3716e583a6d5699f27974c3a95eb9 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 12 Jun 2012 21:56:00 +0300 Subject: CHUI-119 WIP Suppressed of the warnings (XML corrected); fixed the torn-off button's states --- indra/newview/llimconversation.cpp | 40 +++++++++------------- indra/newview/llnearbychat.cpp | 14 ++++---- .../skins/default/xui/en/floater_im_session.xml | 9 +++-- 3 files changed, 28 insertions(+), 35 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index c2621938e1..99b28255cd 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -85,11 +85,11 @@ BOOL LLIMConversation::postBuild() mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); // Show the participants list in torn off floaters only. - mParticipantListPanel->setVisible(gSavedSettings.getBOOL("IMShowControlPanel") - && !mIsNearbyChat); // *TODO: temporarily disabled for Nearby chat - mExpandCollapseBtn->setImageOverlay( - getString(mParticipantListPanel->getVisible() ? "collapse_icon" : "expand_icon")); - mExpandCollapseBtn->setEnabled(!mIsP2PChat); +// mParticipantListPanel->setVisible(gSavedSettings.getBOOL("IMShowControlPanel") +// && !mIsNearbyChat); // *TODO: temporarily disabled for Nearby chat +// mExpandCollapseBtn->setImageOverlay( +// getString(mParticipantListPanel->getVisible() ? "collapse_icon" : "expand_icon")); +// mExpandCollapseBtn->setEnabled(!mIsP2PChat); mTearOffBtn = getChild<LLButton>("tear_off_btn"); mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); @@ -210,30 +210,22 @@ void LLIMConversation::updateHeaderAndToolbar() } } - bool is_control_panel_visible = false; - // Control panel should be visible only in torn off floaters. - is_control_panel_visible = !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel"); - mParticipantListPanel->setVisible(!mIsP2PChat && is_control_panel_visible - && !mIsNearbyChat); // *TODO: temporarily disabled for Nearby chat + // Participant list should be visible only in torn off floaters. + bool is_participant_list_visible = + !is_hosted + && gSavedSettings.getBOOL("IMShowControlPanel") + && !mIsP2PChat + && !mIsNearbyChat; // *TODO: temporarily disabled for Nearby chat + + mParticipantListPanel->setVisible(is_participant_list_visible); // Display collapse image (<<) if the floater is hosted // or if it is torn off but has an open control panel. - bool is_expanded = is_hosted || is_control_panel_visible; + bool is_expanded = is_hosted || is_participant_list_visible; mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); - if (session) - { - // The button (>>) should be disabled for torn off P2P conversations. - mExpandCollapseBtn->setEnabled(is_hosted || !session->isP2PSessionType()); - } - else - { - if (!mIsNearbyChat) - { - llwarns << "IM session not found." << llendl; - } - } + // The button (>>) should be disabled for torn off P2P conversations. + mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat && !mIsNearbyChat); if (mDragHandle) { diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index e35dbf21d4..2f5a3a8767 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -126,7 +126,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& key) : LLIMConversation(key), mChatBox(NULL), mChatHistory(NULL), - mOutputMonitor(NULL), + //mOutputMonitor(NULL), mSpeakerMgr(NULL), mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) { @@ -152,8 +152,8 @@ BOOL LLNearbyChat::postBuild() mChatBox->setEnableLineHistory(TRUE); mChatBox->setFont(LLViewerChat::getChatFont()); - mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); - mOutputMonitor->setVisible(FALSE); +// mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); +// mOutputMonitor->setVisible(FALSE); // Register for font change notifications LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChat::onChatFontChange, this, _1)); @@ -184,6 +184,8 @@ BOOL LLNearbyChat::postBuild() loadHistory(); } + setTitle(getString("NearbyChatTitle")); + return LLIMConversation::postBuild(); } @@ -718,12 +720,12 @@ void LLNearbyChat::displaySpeakingIndicator() if (!id.isNull()) { - mOutputMonitor->setVisible(TRUE); - mOutputMonitor->setSpeakerId(id); + //mOutputMonitor->setVisible(TRUE); + //mOutputMonitor->setSpeakerId(id); } else { - mOutputMonitor->setVisible(FALSE); + //mOutputMonitor->setVisible(FALSE); } } diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index e5e005e36f..a4695b8c09 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -15,6 +15,9 @@ can_tear_off="false" min_width="250" min_height="190"> + <floater.string + name="NearbyChatTitle" + value="Nearby Chat"/> <floater.string name="call_btn_start">VoicePTT_Off</floater.string> <floater.string name="call_btn_stop">VoicePTT_On</floater.string> <floater.string @@ -131,9 +134,7 @@ name="im_panels" tab_group="1" top_pad="0" - left="0" - auto_resize="true" - user_resize="true"> + left="0"> <layout_panel name="speakers_list_panel" follows="all" @@ -185,8 +186,6 @@ orientation="vertical" name="translate_and_chat_stack" tab_group="1" - auto_resize="true" - user_resize="true" left_pad="0" top="0" left="0"> -- cgit v1.2.3 From b50349ab8490c9b48e9cf89b8de186b528d90e60 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Wed, 13 Jun 2012 19:26:17 +0300 Subject: CHUI-120 WIP Fix for crash after closing the chat floater. --- indra/newview/llimconversation.cpp | 4 ++++ indra/newview/llimfloater.cpp | 4 ++++ indra/newview/llnearbychat.cpp | 4 ++++ 3 files changed, 12 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 99b28255cd..b45fc63825 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -114,6 +114,10 @@ BOOL LLIMConversation::postBuild() BOOL LLIMConversation::tick() { + // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater + // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy(). + if (isDead()) return false; + // Need to resort the participant list if it's in sort by recent speaker order. if (mParticipantList) { diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index dcd19b5856..3458e740e7 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -487,6 +487,10 @@ void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id, // virtual BOOL LLIMFloater::tick() { + // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater + // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy(). + if (isDead()) return false; + BOOL parents_retcode = LLIMConversation::tick(); if ( mMeTyping ) diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 2f5a3a8767..cd181ce865 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -404,6 +404,10 @@ void LLNearbyChat::showTranslationCheckbox(BOOL show) BOOL LLNearbyChat::tick() { + // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater + // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy(). + if (isDead()) return false; + BOOL parents_retcode = LLIMConversation::tick(); displaySpeakingIndicator(); -- cgit v1.2.3 From 569146f27c7350ca2245f1fa7bc4cb9c16a428ea Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Wed, 13 Jun 2012 21:21:19 +0300 Subject: CHUI-120 WIP Modified chat participants drag and drop not to use LLClipboard. --- indra/newview/llavatarlistitem.cpp | 1 - indra/newview/llimfloater.cpp | 8 +-- indra/newview/llimfloater.h | 2 +- indra/newview/lltooldraganddrop.cpp | 97 ++++++++++++++++++++++++++----------- 4 files changed, 73 insertions(+), 35 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 7ba63bc4a2..7b5229b5e6 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -31,7 +31,6 @@ #include "llavatarlistitem.h" #include "llbutton.h" -#include "llclipboard.h" #include "llfloaterreg.h" #include "lltextutil.h" diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 3458e740e7..7c6de01c96 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -1004,7 +1004,7 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, { if (cargo_type == DAD_PERSON) { - if (dropPerson(static_cast<LLInventoryObject*>(cargo_data), drop)) + if (dropPerson(static_cast<LLUUID*>(cargo_data), drop)) { *accept = ACCEPT_YES_MULTI; } @@ -1016,13 +1016,13 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, return TRUE; } -bool LLIMFloater::dropPerson(LLInventoryObject* item, bool drop) +bool LLIMFloater::dropPerson(LLUUID* person_id, bool drop) { - bool res = item && item->getUUID().notNull(); + bool res = person_id && person_id->notNull(); if(res) { uuid_vec_t ids; - ids.push_back(item->getUUID()); + ids.push_back(*person_id); res = canAddSelectedToChat(ids); if(res && drop) diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index b02f779637..d74b13b88d 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -138,7 +138,7 @@ private: // For display name lookups for IM window titles void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); - bool dropPerson(LLInventoryObject* item, bool drop); + bool dropPerson(LLUUID* person_id, bool drop); BOOL isInviteAllowed() const; BOOL inviteToSession(const uuid_vec_t& agent_ids); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 296ded6831..86708b46d5 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -58,7 +58,6 @@ #include "llviewerwindow.h" #include "llvoavatarself.h" #include "llworld.h" -#include "llclipboard.h" // syntactic sugar #define callMemberFunction(object,ptrToMember) ((object).*(ptrToMember)) @@ -654,33 +653,41 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, sOperationId++; } + // For people drag and drop we don't need an actual inventory object, + // instead we need the current cargo id, which should be a person id. + bool is_uuid_dragged = (mSource == SOURCE_PEOPLE); + if (top_view) { handled = TRUE; for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) { - LLInventoryObject* cargo = locateInventory(item, cat); + S32 local_x, local_y; + top_view->screenPointToLocal( x, y, &local_x, &local_y ); + EAcceptance item_acceptance = ACCEPT_NO; + LLInventoryObject* cargo = locateInventory(item, cat); if (cargo) { - S32 local_x, local_y; - top_view->screenPointToLocal( x, y, &local_x, &local_y ); - EAcceptance item_acceptance = ACCEPT_NO; handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, mCargoTypes[mCurItemIndex], (void*)cargo, &item_acceptance, mToolTipMsg); - if (handled) - { - // use sort order to determine priority of acceptance - *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance); - } } - else + else if (is_uuid_dragged) { - return; + handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, + mCargoTypes[mCurItemIndex], + (void*)&mCargoIDs[mCurItemIndex], + &item_acceptance, + mToolTipMsg); + } + if (handled) + { + // use sort order to determine priority of acceptance + *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance); } } @@ -697,20 +704,27 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) { - LLInventoryObject* cargo = locateInventory(item, cat); + S32 local_x, local_y; + EAcceptance item_acceptance; + top_view->screenPointToLocal( x, y, &local_x, &local_y ); + LLInventoryObject* cargo = locateInventory(item, cat); if (cargo) { - S32 local_x, local_y; - - EAcceptance item_acceptance; - top_view->screenPointToLocal( x, y, &local_x, &local_y ); handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, TRUE, mCargoTypes[mCurItemIndex], (void*)cargo, &item_acceptance, mToolTipMsg); } + else if (is_uuid_dragged) + { + handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, + mCargoTypes[mCurItemIndex], + (void*)&mCargoIDs[mCurItemIndex], + &item_acceptance, + mToolTipMsg); + } } } if (handled) @@ -727,17 +741,27 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) { + EAcceptance item_acceptance = ACCEPT_NO; + LLInventoryObject* cargo = locateInventory(item, cat); // fix for EXT-3191 - if (NULL == cargo) return; - - EAcceptance item_acceptance = ACCEPT_NO; - handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, - mCargoTypes[mCurItemIndex], - (void*)cargo, - &item_acceptance, - mToolTipMsg); + if (cargo) + { + handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, + mCargoTypes[mCurItemIndex], + (void*)cargo, + &item_acceptance, + mToolTipMsg); + } + else if (is_uuid_dragged) + { + handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, + mCargoTypes[mCurItemIndex], + (void*)&mCargoIDs[mCurItemIndex], + &item_acceptance, + mToolTipMsg); + } if (handled) { // use sort order to determine priority of acceptance @@ -757,17 +781,25 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) { - LLInventoryObject* cargo = locateInventory(item, cat); + EAcceptance item_acceptance; + LLInventoryObject* cargo = locateInventory(item, cat); if (cargo) { - EAcceptance item_acceptance; handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE, mCargoTypes[mCurItemIndex], (void*)cargo, &item_acceptance, mToolTipMsg); } + else if (is_uuid_dragged) + { + handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE, + mCargoTypes[mCurItemIndex], + (void*)&mCargoIDs[mCurItemIndex], + &item_acceptance, + mToolTipMsg); + } } } @@ -2495,7 +2527,13 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory( { item = NULL; cat = NULL; - if(mCargoIDs.empty()) return NULL; + + if (mCargoIDs.empty() + || (mSource == SOURCE_PEOPLE)) ///< There is no inventory item for people drag and drop. + { + return NULL; + } + if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY)) { // The object should be in user inventory. @@ -2527,10 +2565,11 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory( item = (LLViewerInventoryItem*)preview->getDragItem(); } } - else if(mSource == SOURCE_VIEWER || mSource == SOURCE_PEOPLE) + else if(mSource == SOURCE_VIEWER) { item = (LLViewerInventoryItem*)gToolBarView->getDragItem(); } + if(item) return item; if(cat) return cat; return NULL; -- cgit v1.2.3 From b01ab3b9b2d55a8536894a049354b87bb1d71cdb Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 13 Jun 2012 13:52:26 -0700 Subject: EXP-137 : Comments cleanup --- indra/newview/llimfloatercontainer.cpp | 19 ++++++++++--------- indra/newview/llimfloatercontainer.h | 23 ++++++++++++----------- 2 files changed, 22 insertions(+), 20 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 9084c07cc7..77bb103bda 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -116,7 +116,7 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, LLUUID session_id = floaterp->getKey(); - // CHUI-137 + // CHUI-137 : Temporary implementation of conversations list // Create a conversation item LLConversationItem* item = new LLConversationItem(floaterp->getTitle(),session_id, floaterp, this); mConversationsItems[session_id] = item; @@ -171,11 +171,12 @@ void LLIMFloaterContainer::removeFloater(LLFloater* floaterp) { LLMultiFloater::removeFloater(floaterp); - // CHUI-137 : Clean up the conversations list + // CHUI-137 : Temporary implementation of conversations list + // Clean up the conversations list LLUUID session_id = floaterp->getKey(); // Delete the widget and the associated conversation item - // Note : since the mConversationsItems is a listener to the widget, deleting the widget also - // delete its listener + // Note : since the mConversationsItems is also the listener to the widget, deleting + // the widget will also delete its listener conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(session_id); if (widget_it != mConversationsWidgets.end()) { @@ -197,7 +198,7 @@ void LLIMFloaterContainer::removeFloater(LLFloater* floaterp) panel_rect.getWidth(), panel_rect.getHeight() - item_height*(index+1))); } - // CHUI-137 + // CHUI-137 : end LLRect contents_rect = floaterp->getRect(); @@ -362,7 +363,7 @@ void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); } -// CHUI-137 : Temp implementation of conversations list +// CHUI-137 : Temporary implementation of conversations list LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) { LLFolderViewItem::Params params; @@ -370,7 +371,6 @@ LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversat params.name = item->getDisplayName(); //params.icon = bridge->getIcon(); //params.icon_open = bridge->getOpenIcon(); - //params.creation_date = bridge->getCreationDate(); //params.root = mFolderRoot; params.listener = item; @@ -387,7 +387,8 @@ LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLF mFloater(floaterp), mContainer(containerp) { - // Hack: the nearby chat has no name so we catch that and impose one + // Hack: the nearby chat has no name so we catch that case and impose one + // Of course, we won't be doing this in the final code if (name == "") mName = "Nearby Chat"; } @@ -395,7 +396,7 @@ LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLF // Virtual action callbacks void LLConversationItem::selectItem(void) { - // Select the conversation floater that is being selected + // Switch to the conversation floater that is being selected mContainer->selectFloater(mFloater); } diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 3df5a07df8..23927239a5 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -42,16 +42,16 @@ class LLButton; class LLLayoutPanel; class LLLayoutStack; class LLTabContainer; +class LLIMFloaterContainer; // CHUI-137 : Temporary implementation of conversations list class LLConversationItem; -class LLIMFloaterContainer; typedef std::map<LLUUID, LLConversationItem*> conversations_items_map; typedef std::map<LLUUID, LLFolderViewItem*> conversations_widgets_map; -// Conversation items: we hold a list of those and create an LLFolderViewItem widget for each that we tuck -// into the mConversationsListPanel. +// Conversation items: we hold a list of those and create an LLFolderViewItem widget for each +// that we tuck into the mConversationsListPanel. class LLConversationItem : public LLFolderViewEventListener { public: @@ -89,7 +89,7 @@ public: virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; } virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } - // The action callbacks (or so we think...) + // The action callbacks virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem( void ); virtual void closeItem( void ); @@ -97,14 +97,14 @@ public: virtual void selectItem(void); virtual void showProperties(void); - // This method should be called when a drag begins. returns TRUE - // if the drag can begin, otherwise FALSE. + // This method should be called when a drag begins. + // Returns TRUE if the drag can begin, FALSE otherwise. virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const { return FALSE; } // This method will be called to determine if a drop can be // performed, and will set drop to TRUE if a drop is - // requested. Returns TRUE if a drop is possible/happened, - // otherwise FALSE. + // requested. + // Returns TRUE if a drop is possible/happened, FALSE otherwise. virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, @@ -115,7 +115,7 @@ private: LLFloater* mFloater; LLIMFloaterContainer* mContainer; }; - // CHUI-137 : End +// CHUI-137 : End class LLIMFloaterContainer : public LLMultiFloater { @@ -164,8 +164,9 @@ private: LLLayoutPanel* mConversationsPane; LLLayoutStack* mConversationsStack; - // CHUI-137 : Data - LLPanel* mConversationsListPanel; // The widget we add list item to (title of each conversation) + // CHUI-137 : Temporary implementation of conversations list + // Conversation list data + LLPanel* mConversationsListPanel; // This is the widget we add items to (i.e. clickable title for each conversation) conversations_items_map mConversationsItems; conversations_widgets_map mConversationsWidgets; }; -- cgit v1.2.3 From d34746b596bad717f7d0c10e263700738a06aa43 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Thu, 14 Jun 2012 17:37:16 +0300 Subject: CHUI-144 FIXED Residents picker added to Conversations panel + button. --- indra/newview/llimfloatercontainer.cpp | 26 ++++++++++++++++++++++++++ indra/newview/llimfloatercontainer.h | 3 +++ 2 files changed, 29 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 3b6240de44..71b69dfbc8 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -34,8 +34,10 @@ #include "llnearbychat.h" #include "llagent.h" +#include "llavataractions.h" #include "llavatariconctrl.h" #include "llgroupiconctrl.h" +#include "llfloateravatarpicker.h" #include "llimview.h" #include "lltransientfloatermgr.h" #include "llviewercontrol.h" @@ -75,6 +77,8 @@ BOOL LLIMFloaterContainer::postBuild() mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this)); + childSetAction("add_btn", boost::bind(&LLIMFloaterContainer::onAddButtonClicked, this)); + collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); @@ -313,4 +317,26 @@ void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); } +void LLIMFloaterContainer::onAddButtonClicked() +{ + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloaterContainer::onAvatarPicked, this, _1), TRUE, TRUE); + LLFloater* root_floater = gFloaterView->getParentFloater(this); + if (picker && root_floater) + { + root_floater->addDependentFloater(picker); + } +} + +void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) +{ + if (ids.size() == 1) + { + LLAvatarActions::startIM(ids.back()); + } + else + { + LLAvatarActions::startConference(ids); + } +} + // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 92938ff405..7b395fb18f 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -80,6 +80,9 @@ private: void updateState(bool collapse, S32 delta_width); + void onAddButtonClicked(); + void onAvatarPicked(const uuid_vec_t& ids); + LLButton* mExpandCollapseBtn; LLLayoutPanel* mMessagesPane; LLLayoutPanel* mConversationsPane; -- cgit v1.2.3 From 51a39b5ac6465238178363f3ec3143dae4f73919 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 14 Jun 2012 20:00:41 +0300 Subject: CHUI-199 WIP Modified the nearby chat for using floater_im_session.xml; merging LLNearbyChatBar with LLNearbyChat; clean up code; supressed a double creation of LLNearbyChat --- indra/newview/llimconversation.cpp | 14 ++++---------- indra/newview/llimfloater.cpp | 5 ++++- indra/newview/llimfloater.h | 3 --- indra/newview/llnearbychat.cpp | 4 +--- indra/newview/llnearbychathandler.cpp | 1 - indra/newview/llviewerfloaterreg.cpp | 2 +- 6 files changed, 10 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index b45fc63825..3e2b208874 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -35,7 +35,6 @@ #include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container #include "lllayoutstack.h" #include "llnearbychat.h" -#include "llnearbychat.h" const F32 REFRESH_INTERVAL = 0.2f; @@ -84,13 +83,6 @@ BOOL LLIMConversation::postBuild() mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); - // Show the participants list in torn off floaters only. -// mParticipantListPanel->setVisible(gSavedSettings.getBOOL("IMShowControlPanel") -// && !mIsNearbyChat); // *TODO: temporarily disabled for Nearby chat -// mExpandCollapseBtn->setImageOverlay( -// getString(mParticipantListPanel->getVisible() ? "collapse_icon" : "expand_icon")); -// mExpandCollapseBtn->setEnabled(!mIsP2PChat); - mTearOffBtn = getChild<LLButton>("tear_off_btn"); mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); @@ -144,9 +136,11 @@ void LLIMConversation::buildParticipantList() void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata) { - // TODO: Check this code when when sort order menu will be added. (EM) - if (true || !mParticipantList) + // TODO: Check this code when sort order menu will be added. (EM) + if (!mParticipantList) + { return; + } std::string chosen_item = userdata.asString(); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 7c6de01c96..30a9c29ec6 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -489,7 +489,10 @@ BOOL LLIMFloater::tick() { // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy(). - if (isDead()) return false; + if (isDead()) + { + return false; + } BOOL parents_retcode = LLIMConversation::tick(); diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index d74b13b88d..333340c696 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -70,9 +70,6 @@ public: static LLIMFloater* getInstance(const LLUUID& session_id); static void addToHost(const LLUUID& session_id); - static void* createPanelGroupControl(void* userdata); - static void* createPanelAdHocControl(void* userdata); - // LLFloater overrides /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index cd181ce865..fbaf451412 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -408,8 +408,6 @@ BOOL LLNearbyChat::tick() // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy(). if (isDead()) return false; - BOOL parents_retcode = LLIMConversation::tick(); - displaySpeakingIndicator(); updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); @@ -421,7 +419,7 @@ BOOL LLNearbyChat::tick() setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE); } - return parents_retcode; + return LLIMConversation::tick(); } std::string LLNearbyChat::getCurrentChat() diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index e91a3fc334..c97e3585e1 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -555,7 +555,6 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, // Send event on to LLEventStream sChatWatcher->post(chat); - if( nearby_chat->isInVisibleChain() || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT && gSavedSettings.getBOOL("UseChatBubbles") ) diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index df1962f5fe..bf12b08321 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -186,6 +186,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>); LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>); + LLFloaterReg::add("chat_bar", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>); LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>); LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>); @@ -208,7 +209,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHelpBrowser>); LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>); - LLFloaterReg::add("chat_bar", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>); LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloater>); LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloaterContainer>); LLFloaterReg::add("im_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMWellWindow>); -- cgit v1.2.3 From c238027dd9917b1633ff5f16911fbdbe437f9a55 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 14 Jun 2012 16:47:43 -0700 Subject: CHUI-139 : Use the Chat toolbar button to open and close the conversations multi floater. Force Nearby Conversation if floater is empty. --- indra/newview/app_settings/commands.xml | 6 +++--- indra/newview/llimfloatercontainer.cpp | 13 +++++++++++-- indra/newview/skins/default/xui/en/strings.xml | 2 ++ 3 files changed, 16 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 73df064ab2..51211a8ce5 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -46,11 +46,11 @@ available_in_toybox="true" icon="Command_Chat_Icon" label_ref="Command_Chat_Label" - tooltip_ref="Command_Chat_Tooltip" + tooltip_ref="Command_Conversations_Tooltip" execute_function="Floater.ToggleOrBringToFront" - execute_parameters="chat_bar" + execute_parameters="im_container" is_running_function="Floater.IsOpen" - is_running_parameters="chat_bar" + is_running_parameters="im_container" /> <command name="compass" available_in_toybox="false" diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 77bb103bda..c01a167169 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" +#include "llimfloater.h" #include "llimfloatercontainer.h" #include "llfloaterreg.h" @@ -86,7 +87,15 @@ BOOL LLIMFloaterContainer::postBuild() void LLIMFloaterContainer::onOpen(const LLSD& key) { LLMultiFloater::onOpen(key); -/* + if (getFloaterCount() == 0) + { + // If there's *no* conversation open so far, we force the opening of the nearby chat conversation + // *TODO: find a way to move this to XML as a default panel or something like that + LLSD name("chat_bar"); + LLSD key(""); + LLFloaterReg::toggleInstanceOrBringToFront(name,key); + } + /* if (key.isDefined()) { LLIMFloater* im_floater = LLIMFloater::findInstance(key.asUUID()); @@ -95,7 +104,7 @@ void LLIMFloaterContainer::onOpen(const LLSD& key) im_floater->openFloater(); } } -*/ + */ } // virtual diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 0a2fc13aff..7790a382d9 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3692,6 +3692,7 @@ Try enclosing path to the editor with double quotes. <string name="Command_Avatar_Label">Avatar</string> <string name="Command_Build_Label">Build</string> <string name="Command_Chat_Label">Chat</string> + <string name="Command_Conversations_Label">Conversations</string> <string name="Command_Compass_Label">Compass</string> <string name="Command_Destinations_Label">Destinations</string> <string name="Command_Gestures_Label">Gestures</string> @@ -3718,6 +3719,7 @@ Try enclosing path to the editor with double quotes. <string name="Command_Avatar_Tooltip">Choose a complete avatar</string> <string name="Command_Build_Tooltip">Building objects and reshaping terrain</string> <string name="Command_Chat_Tooltip">Chat with people nearby using text</string> + <string name="Command_Conversations_Tooltip">Converse with everyone</string> <string name="Command_Compass_Tooltip">Compass</string> <string name="Command_Destinations_Tooltip">Destinations of interest</string> <string name="Command_Gestures_Tooltip">Gestures for your avatar</string> -- cgit v1.2.3 From 9940ca5ae7698e89c0587733f7ab922027c8ddcc Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 15 Jun 2012 09:44:27 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose llfolderview refactornig --- indra/llinventory/llinventory.cpp | 31 +- indra/llinventory/llinventory.h | 5 +- indra/llxuixml/llinitparam.h | 88 ++-- indra/newview/llavataractions.cpp | 27 +- indra/newview/llfloateroutbox.cpp | 13 +- indra/newview/llfolderview.cpp | 398 ++------------- indra/newview/llfolderview.h | 56 +-- indra/newview/llfoldervieweventlistener.h | 245 ++++++++- indra/newview/llfolderviewitem.cpp | 554 ++++++--------------- indra/newview/llfolderviewitem.h | 238 ++++----- indra/newview/llfriendcard.cpp | 4 +- indra/newview/llinventorybridge.cpp | 335 ++++++++----- indra/newview/llinventorybridge.h | 67 +-- indra/newview/llinventoryfilter.cpp | 181 +++---- indra/newview/llinventoryfilter.h | 145 ++++-- indra/newview/llinventorypanel.cpp | 234 ++++++--- indra/newview/llinventorypanel.h | 54 +- indra/newview/llpanellandmarks.cpp | 57 +-- indra/newview/llpanelmaininventory.cpp | 45 +- indra/newview/llpanelmarketplaceinbox.cpp | 12 +- indra/newview/llpanelmarketplaceinboxinventory.cpp | 5 +- indra/newview/llpanelmarketplaceinboxinventory.h | 4 +- .../newview/llpanelmarketplaceoutboxinventory.cpp | 2 +- indra/newview/llpanelobjectinventory.cpp | 26 +- indra/newview/llpaneloutfitedit.cpp | 30 +- indra/newview/llplacesinventorybridge.cpp | 43 +- indra/newview/llplacesinventorypanel.cpp | 3 +- indra/newview/llsidepanelappearance.cpp | 2 +- indra/newview/llsidepanelinventory.cpp | 7 +- indra/newview/llsidepanelinventory.h | 1 + indra/newview/lltexturectrl.cpp | 4 +- indra/newview/llviewerinventory.cpp | 23 +- indra/newview/llviewerinventory.h | 12 +- indra/newview/llviewermessage.cpp | 20 +- 34 files changed, 1456 insertions(+), 1515 deletions(-) (limited to 'indra') diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index fbf23bc3f0..784e20ad46 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -275,6 +275,18 @@ void LLInventoryObject::correctInventoryName(std::string& name) LLStringUtil::truncate(name, DB_INV_ITEM_NAME_STR_LEN); } +time_t LLInventoryObject::getCreationDate() const +{ + return mCreationDate; +} + +void LLInventoryObject::setCreationDate(time_t creation_date_utc) +{ + mCreationDate = creation_date_utc; +} + + + ///---------------------------------------------------------------------------- /// Class LLInventoryItem @@ -297,9 +309,10 @@ LLInventoryItem::LLInventoryItem(const LLUUID& uuid, mDescription(desc), mSaleInfo(sale_info), mInventoryType(inv_type), - mFlags(flags), - mCreationDate(creation_date_utc) + mFlags(flags) { + mCreationDate = creation_date_utc; + LLStringUtil::replaceNonstandardASCII(mDescription, ' '); LLStringUtil::replaceChar(mDescription, '|', ' '); mPermissions.initMasks(inv_type); @@ -312,9 +325,9 @@ LLInventoryItem::LLInventoryItem() : mDescription(), mSaleInfo(), mInventoryType(LLInventoryType::IT_NONE), - mFlags(0), - mCreationDate(0) + mFlags(0) { + mCreationDate = 0; } LLInventoryItem::LLInventoryItem(const LLInventoryItem* other) : @@ -379,11 +392,6 @@ const std::string& LLInventoryItem::getDescription() const return mDescription; } -time_t LLInventoryItem::getCreationDate() const -{ - return mCreationDate; -} - U32 LLInventoryItem::getCRC32() const { // *FIX: Not a real crc - more of a checksum. @@ -440,11 +448,6 @@ void LLInventoryItem::setFlags(U32 flags) mFlags = flags; } -void LLInventoryItem::setCreationDate(time_t creation_date_utc) -{ - mCreationDate = creation_date_utc; -} - // Currently only used in the Viewer to handle calling cards // where the creator is actually used to store the target. void LLInventoryItem::setCreator(const LLUUID& creator) diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index a5cfe59bda..dc9a09e9d6 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -75,6 +75,7 @@ public: virtual LLAssetType::EType getType() const; LLAssetType::EType getActualType() const; // bypasses indirection for linked items BOOL getIsLinkType() const; + virtual time_t getCreationDate() const; //-------------------------------------------------------------------- // Mutators @@ -85,6 +86,7 @@ public: virtual void rename(const std::string& new_name); void setParent(const LLUUID& new_parent); void setType(LLAssetType::EType type); + virtual void setCreationDate(time_t creation_date_utc); // only stored for items private: // in place correction for inventory name string @@ -113,6 +115,7 @@ protected: LLUUID mParentUUID; // Parent category. Root categories have LLUUID::NULL. LLAssetType::EType mType; std::string mName; + time_t mCreationDate; // seconds from 1/1/1970, UTC }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -178,7 +181,6 @@ public: void setPermissions(const LLPermissions& perm); void setInventoryType(LLInventoryType::EType inv_type); void setFlags(U32 flags); - void setCreationDate(time_t creation_date_utc); void setCreator(const LLUUID& creator); // only used for calling cards // Check for changes in permissions masks and sale info @@ -224,7 +226,6 @@ protected: LLSaleInfo mSaleInfo; LLInventoryType::EType mInventoryType; U32 mFlags; - time_t mCreationDate; // seconds from 1/1/1970, UTC }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index ce59401e87..d44ccac6e4 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -212,7 +212,7 @@ namespace LLInitParam {} ParamValue(const default_value_t& other) - : T(other), + : T(other), mValidated(false) {} @@ -632,38 +632,38 @@ namespace LLInitParam class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed }; - //TODO: implement in terms of owned_ptr - template<typename T> + //TODO: implement in terms of owned_ptr + template<typename T> class LazyValue - { + { public: LazyValue() - : mPtr(NULL) - {} + : mPtr(NULL) + {} ~LazyValue() - { - delete mPtr; - } + { + delete mPtr; + } LazyValue(const T& value) - { + { mPtr = new T(value); } LazyValue(const LazyValue& other) : mPtr(NULL) - { + { *this = other; - } + } LazyValue& operator = (const LazyValue& other) { if (!other.mPtr) - { + { delete mPtr; - mPtr = NULL; - } + mPtr = NULL; + } else { if (!mPtr) @@ -674,9 +674,9 @@ namespace LLInitParam { *mPtr = *(other.mPtr); } - } - return *this; } + return *this; + } bool operator==(const LazyValue& other) const { @@ -684,13 +684,13 @@ namespace LLInitParam return *mPtr == *other.mPtr; } - bool empty() const - { - return mPtr == NULL; - } + bool empty() const + { + return mPtr == NULL; + } - void set(const T& other) - { + void set(const T& other) + { if (!mPtr) { mPtr = new T(other); @@ -701,36 +701,36 @@ namespace LLInitParam } } - const T& get() const - { + const T& get() const + { return *ensureInstance(); - } + } - T& get() - { + T& get() + { return *ensureInstance(); } operator const T&() const { return get(); - } + } - private: - // lazily allocate an instance of T - T* ensureInstance() const + private: + // lazily allocate an instance of T + T* ensureInstance() const + { + if (mPtr == NULL) { - if (mPtr == NULL) - { - mPtr = new T(); - } - return mPtr; - } + mPtr = new T(); + } + return mPtr; + } - private: + private: - mutable T* mPtr; - }; + mutable T* mPtr; + }; // root class of all parameter blocks @@ -2492,10 +2492,10 @@ namespace LLInitParam } EValueAge; typedef ParamValue<T> derived_t; - typedef CustomParamValue<T> self_t; - typedef Block<derived_t> block_t; + typedef CustomParamValue<T> self_t; + typedef Block<derived_t> block_t; typedef T default_value_t; - typedef T value_t; + typedef T value_t; typedef void baseblock_base_class_t; diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index aa626a9a30..1d5543cd20 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -711,23 +711,30 @@ namespace action_give_inventory //static std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs() { - std::set<LLUUID> inventory_selected_uuids; + std::set<LLFolderViewItem*> inventory_selected; LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel(); if (active_panel) { - inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList(); + inventory_selected= active_panel->getRootFolder()->getSelectionList(); } - if (inventory_selected_uuids.empty()) + if (inventory_selected.empty()) { LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); if (sidepanel_inventory) { - inventory_selected_uuids = sidepanel_inventory->getInboxSelectionList(); + inventory_selected= sidepanel_inventory->getInboxSelectionList(); } } + std::set<LLUUID> inventory_selected_uuids; + for (std::set<LLFolderViewItem*>::iterator it = inventory_selected.begin(), end_it = inventory_selected.end(); + it != end_it; + ++it) + { + inventory_selected_uuids.insert((*it)->getListener()->getUUID()); + } return inventory_selected_uuids; } @@ -758,15 +765,15 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL // check selection in the panel LLFolderView* root_folder = inv_panel->getRootFolder(); - const std::set<LLUUID> inventory_selected_uuids = root_folder->getSelectionList(); - if (inventory_selected_uuids.empty()) return false; // nothing selected + const std::set<LLFolderViewItem*> inventory_selected = root_folder->getSelectionList(); + if (inventory_selected.empty()) return false; // nothing selected bool can_share = true; - std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); - const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end(); + std::set<LLFolderViewItem*>::const_iterator it = inventory_selected.begin(); + const std::set<LLFolderViewItem*>::const_iterator it_end = inventory_selected.end(); for (; it != it_end; ++it) { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); + LLViewerInventoryCategory* inv_cat = gInventory.getCategory((*it)->getListener()->getUUID()); // any category can be offered. if (inv_cat) { @@ -774,7 +781,7 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL } // check if inventory item can be given - LLFolderViewItem* item = root_folder->getItemByID(*it); + LLFolderViewItem* item = *it; if (!item) return false; LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getListener()); if (bridge && bridge->canShare()) diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index c55970ad69..ba0f51b467 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -250,7 +250,8 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId) mOutboxInventoryPanel->setShape(inventory_placeholder_rect); // Set the sort order newest to oldest - mOutboxInventoryPanel->setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME); + + mOutboxInventoryPanel->getViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME); mOutboxInventoryPanel->getFilter()->markDefault(); fetchOutboxContents(); @@ -386,7 +387,7 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, // Determine if the mouse is inside the inventory panel itself or just within the floater bool pointInInventoryPanel = false; bool pointInInventoryPanelChild = false; - LLFolderView * root_folder = mOutboxInventoryPanel->getRootFolder(); + LLFolderView* root_folder = mOutboxInventoryPanel->getRootFolder(); if (mOutboxInventoryPanel->getVisible()) { S32 inv_x, inv_y; @@ -443,10 +444,10 @@ void LLFloaterOutbox::onOutboxChanged() { llassert(!mOutboxId.isNull()); - if (mOutboxInventoryPanel) - { - mOutboxInventoryPanel->requestSort(); - } + //if (mOutboxInventoryPanel) + //{ + // mOutboxInventoryPanel->requestSort(); + //} fetchOutboxContents(); diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index f375443e38..ffef4ef69a 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -26,6 +26,7 @@ #include "llviewerprecompiledheaders.h" +#include "llfolderview.h" #include "llfolderview.h" #include "llcallbacklist.h" @@ -94,42 +95,6 @@ enum { F32 LLFolderView::sAutoOpenTime = 1.f; -void delete_selected_item(void* user_data); -void copy_selected_item(void* user_data); -void open_selected_items(void* user_data); -void properties_selected_items(void* user_data); -void paste_items(void* user_data); - - -//--------------------------------------------------------------------------- - -// Tells all folders in a folderview to sort their items -// (and only their items, not folders) by a certain function. -class LLSetItemSortFunction : public LLFolderViewFunctor -{ -public: - LLSetItemSortFunction(U32 ordering) - : mSortOrder(ordering) {} - virtual ~LLSetItemSortFunction() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - - U32 mSortOrder; -}; - - -// Set the sort order. -void LLSetItemSortFunction::doFolder(LLFolderViewFolder* folder) -{ - folder->setItemSortOrder(mSortOrder); -} - -// Do nothing. -void LLSetItemSortFunction::doItem(LLFolderViewItem* item) -{ - return; -} - //--------------------------------------------------------------------------- // Tells all folders in a folderview to close themselves @@ -154,7 +119,6 @@ public: }; -// Set the sort order. void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder) { folder->setOpenArrangeRecursively(mOpen); @@ -173,7 +137,6 @@ LLFolderView::Params::Params() use_label_suffix("use_label_suffix"), allow_multiselect("allow_multiselect", true), show_empty_message("show_empty_message", true), - show_load_status("show_load_status", true), use_ellipses("use_ellipses", false) { folder_indentation = -4; @@ -183,7 +146,6 @@ LLFolderView::Params::Params() // Default constructor LLFolderView::LLFolderView(const Params& p) : LLFolderViewFolder(p), - mRunningHeight(0), mScrollContainer( NULL ), mPopupMenuHandle(), mAllowMultiSelect(p.allow_multiselect), @@ -210,17 +172,15 @@ LLFolderView::LLFolderView(const Params& p) mParentPanel(p.parent_panel), mUseEllipses(p.use_ellipses), mDraggingOverItem(NULL), - mStatusTextBox(NULL) + mStatusTextBox(NULL), + mViewModel(p.view_model) { mRoot = this; - mShowLoadStatus = p.show_load_status(); - LLRect rect = p.rect; LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); setRect( rect ); reshape(rect.getWidth(), rect.getHeight()); - mIsOpen = TRUE; // this view is always open. mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); mAutoOpenCandidate = NULL; mAutoOpenTimer.stop(); @@ -305,8 +265,6 @@ LLFolderView::~LLFolderView( void ) mItems.clear(); mFolders.clear(); - mItemMap.clear(); - delete mFilter; mFilter = NULL; } @@ -316,27 +274,6 @@ BOOL LLFolderView::canFocusChildren() const return FALSE; } -static LLFastTimer::DeclareTimer FTM_SORT("Sort Inventory"); - -void LLFolderView::setSortOrder(U32 order) -{ - if (order != mSortOrder) - { - LLFastTimer t(FTM_SORT); - - mSortOrder = order; - - sortBy(order); - arrangeAll(); - } -} - - -U32 LLFolderView::getSortOrder() const -{ - return mSortOrder; -} - BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { // enforce sort order of My Inventory followed by Library @@ -348,7 +285,6 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { mFolders.insert(mFolders.begin(), folder); } - folder->setShowLoadStatus(mShowLoadStatus); folder->setOrigin(0, 0); folder->reshape(getRect().getWidth(), 0); folder->setVisible(FALSE); @@ -375,128 +311,32 @@ void LLFolderView::openTopLevelFolders() } } -void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) -{ - // call base class to do proper recursion - LLFolderViewFolder::setOpenArrangeRecursively(openitem, recurse); - // make sure root folder is always open - mIsOpen = TRUE; -} - -static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); - // This view grows and shrinks to enclose all of its children items and folders. +// mItemHeight = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; +// *width should be 0 +// conform show folder state works S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation ) { - if (getListener()->getUUID().notNull()) - { - if (mNeedsSort) - { - mFolders.sort(mSortFunction); - mItems.sort(mSortFunction); - mNeedsSort = false; - } - } - - LLFastTimer t2(FTM_ARRANGE); - - filter_generation = mFilter->getMinRequiredGeneration(); mMinWidth = 0; + S32 target_height; - mHasVisibleChildren = hasFilteredDescendants(filter_generation); - // arrange always finishes, so optimistically set the arrange generation to the most current - mLastArrangeGeneration = getRoot()->getArrangeGeneration(); - - LLInventoryFilter::EFolderShow show_folder_state = - getRoot()->getFilter()->getShowFolderState(); - - S32 total_width = LEFT_PAD; - S32 running_height = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; - S32 target_height = running_height; - S32 parent_item_height = getRect().getHeight(); - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - LLFolderViewFolder* folderp = (*fit); - if (getDebugFilters()) - { - folderp->setVisible(TRUE); - } - else - { - folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders? - (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter - } - - if (folderp->getVisible()) - { - S32 child_height = 0; - S32 child_width = 0; - S32 child_top = parent_item_height - running_height; - - target_height += folderp->arrange( &child_width, &child_height, filter_generation ); - - mMinWidth = llmax(mMinWidth, child_width); - total_width = llmax( total_width, child_width ); - running_height += child_height; - folderp->setOrigin( ICON_PAD, child_top - (*fit)->getRect().getHeight() ); - } - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - LLFolderViewItem* itemp = (*iit); - itemp->setVisible(itemp->getFiltered(filter_generation)); - - if (itemp->getVisible()) - { - S32 child_width = 0; - S32 child_height = 0; - S32 child_top = parent_item_height - running_height; - - target_height += itemp->arrange( &child_width, &child_height, filter_generation ); - itemp->reshape(itemp->getRect().getWidth(), child_height); - - mMinWidth = llmax(mMinWidth, child_width); - total_width = llmax( total_width, child_width ); - running_height += child_height; - itemp->setOrigin( ICON_PAD, child_top - itemp->getRect().getHeight() ); - } - } - - if(!mHasVisibleChildren)// is there any filtered items ? - { - //Nope. We need to display status textbox, let's reserve some place for it - running_height = mStatusTextBox->getTextPixelHeight(); - target_height = running_height; - } + LLFolderViewFolder::arrange(&mMinWidth, &target_height, mFilter->getFirstSuccessGeneration()); - mRunningHeight = running_height; LLRect scroll_rect = mScrollContainer->getContentWindowRect(); - reshape( llmax(scroll_rect.getWidth(), total_width), running_height ); + reshape( llmax(scroll_rect.getWidth(), mMinWidth), mCurHeight ); LLRect new_scroll_rect = mScrollContainer->getContentWindowRect(); if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) { - reshape( llmax(scroll_rect.getWidth(), total_width), running_height ); + reshape( llmax(scroll_rect.getWidth(), mMinWidth), mCurHeight ); } // move item renamer text field to item's new position updateRenamerPosition(); - mTargetHeight = (F32)target_height; return llround(mTargetHeight); } -const std::string LLFolderView::getFilterSubString(BOOL trim) -{ - return mFilter->getFilterSubString(trim); -} - static LLFastTimer::DeclareTimer FTM_FILTER("Filter Inventory"); void LLFolderView::filter( LLInventoryFilter& filter ) @@ -525,7 +365,7 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) scroll_rect = mScrollContainer->getContentWindowRect(); } width = llmax(mMinWidth, scroll_rect.getWidth()); - height = llmax(mRunningHeight, scroll_rect.getHeight()); + height = llmax(mCurHeight, scroll_rect.getHeight()); // Restrict width within scroll container's width if (mUseEllipses && mScrollContainer) @@ -623,30 +463,6 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, return rv; } -void LLFolderView::setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus) -{ - LLFolderViewItem* itemp = getItemByID(obj_id); - if(itemp && itemp->getListener()) - { - itemp->arrangeAndSet(TRUE, take_keyboard_focus); - mSelectThisID.setNull(); - return; - } - else - { - // save the desired item to be selected later (if/when ready) - mSelectThisID = obj_id; - } -} - -void LLFolderView::updateSelection() -{ - if (mSelectThisID.notNull()) - { - setSelectionByID(mSelectThisID, false); - } -} - BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) { BOOL rv = FALSE; @@ -697,9 +513,6 @@ void LLFolderView::sanitizeSelection() // and we want to preserve context LLFolderViewItem* original_selected_item = getCurSelectedItem(); - // Cache "Show all folders" filter setting - BOOL show_all_folders = (getRoot()->getFilter()->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS); - std::vector<LLFolderViewItem*> items_to_remove; selected_items_t::iterator item_iter; for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) @@ -710,20 +523,11 @@ void LLFolderView::sanitizeSelection() BOOL visible = item->potentiallyVisible(); // initialize from filter state for this item // modify with parent open and filters states LLFolderViewFolder* parent_folder = item->getParentFolder(); - if ( parent_folder ) + // Move up through parent folders and see what's visible + while(parent_folder) { - if ( show_all_folders ) - { // "Show all folders" is on, so this folder is visible - visible = TRUE; - } - else - { // Move up through parent folders and see what's visible - while(parent_folder) - { - visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); - parent_folder = parent_folder->getParentFolder(); - } - } + visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); + parent_folder = parent_folder->getParentFolder(); } // deselect item if any ancestor is closed or didn't pass filter requirements. @@ -816,15 +620,10 @@ void LLFolderView::clearSelection() mSelectThisID.setNull(); } -std::set<LLUUID> LLFolderView::getSelectionList() const +std::set<LLFolderViewItem*> LLFolderView::getSelectionList() const { - std::set<LLUUID> selection; - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); - item_it != mSelectedItems.end(); - ++item_it) - { - selection.insert((*item_it)->getListener()->getUUID()); - } + std::set<LLFolderViewItem*> selection; + std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin())); return selection; } @@ -862,7 +661,7 @@ void LLFolderView::draw() if (mDebugFilters) { std::string current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d", - mFilter->getCurrentGeneration(), mFilter->getMinRequiredGeneration(), mFilter->getMustPassGeneration()); + mFilter->getCurrentGeneration(), mFilter->getFirstSuccessGeneration(), mFilter->getFirstRequiredGeneration()); LLFontGL::getFontMonospace()->renderUTF8(current_filter_string, 0, 2, getRect().getHeight() - LLFontGL::getFontMonospace()->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f), LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); @@ -901,25 +700,23 @@ void LLFolderView::draw() mSearchString.clear(); } - if (hasVisibleChildren() - || mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) + if (hasVisibleChildren()) { mStatusText.clear(); mStatusTextBox->setVisible( FALSE ); } else if (mShowEmptyMessage) { - if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration()) + if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mCompletedFilterGeneration < mFilter->getFirstSuccessGeneration()) { + RN: Get this from filter mStatusText = LLTrans::getString("Searching"); } else { if (getFilter()) { - LLStringUtil::format_map_t args; - args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig()); - mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage(), args); + mStatusText = getFilter()->getEmptyLookupMessage(); } } mStatusTextBox->setValue(mStatusText); @@ -963,7 +760,7 @@ void LLFolderView::finishRenamingItem( void ) closeRenamer(); - // List is re-sorted alphabeticly, so scroll to make sure the selected item is visible. + // List is re-sorted alphabetically, so scroll to make sure the selected item is visible. scrollToShowSelection(); } @@ -1074,8 +871,8 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL } else if (count > 1) { - LLDynamicArray<LLFolderViewEventListener*> listeners; - LLFolderViewEventListener* listener; + LLDynamicArray<LLFolderViewModelItem*> listeners; + LLFolderViewModelItemInventory* listener; LLFolderViewItem* last_item = items[count - 1]; LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); while(new_selection && new_selection->isSelected()) @@ -1102,12 +899,12 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL for(S32 i = 0; i < count; ++i) { listener = items[i]->getListener(); - if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewEventListener*>::FAIL)) + if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewModelItemInventory*>::FAIL)) { listeners.put(listener); } } - listener = listeners.get(0); + listener = static_cast<LLFolderViewModelItemInventory*>(listeners.get(0)); if(listener) { listener->removeBatch(listeners); @@ -1138,7 +935,7 @@ void LLFolderView::openSelectedItems( void ) // IT_{OBJECT,ATTACHMENT} creates LLProperties // floaters; others create LLPreviews. Put // each one in the right type of container. - LLFolderViewEventListener* listener = (*item_it)->getListener(); + LLFolderViewModelItemInventory* listener = (*item_it)->getListener(); bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); if (is_prop) LLFloater::setFloaterHost(multi_propertiesp); @@ -1294,7 +1091,7 @@ void LLFolderView::copy() S32 count = mSelectedItems.size(); if(getVisible() && getEnabled() && (count > 0)) { - LLFolderViewEventListener* listener = NULL; + LLFolderViewModelItemInventory* listener = NULL; selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { @@ -1318,7 +1115,7 @@ BOOL LLFolderView::canCut() const for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) { const LLFolderViewItem* item = *selected_it; - const LLFolderViewEventListener* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = item->getListener(); if (!listener || !listener->isItemRemovable()) { @@ -1335,7 +1132,7 @@ void LLFolderView::cut() S32 count = mSelectedItems.size(); if(getVisible() && getEnabled() && (count > 0)) { - LLFolderViewEventListener* listener = NULL; + LLFolderViewModelItemInventory* listener = NULL; selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { @@ -1363,7 +1160,7 @@ BOOL LLFolderView::canPaste() const { // *TODO: only check folders and parent folders of items const LLFolderViewItem* item = (*item_it); - const LLFolderViewEventListener* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = item->getListener(); if(!listener || !listener->isClipboardPasteable()) { const LLFolderViewFolder* folderp = item->getParentFolder(); @@ -1391,7 +1188,7 @@ void LLFolderView::paste() for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) { LLFolderViewItem* item = *selected_it; - LLFolderViewEventListener* listener = item->getListener(); + LLFolderViewModelItemInventory* listener = item->getListener(); if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY) { item = item->getParentFolder(); @@ -1402,7 +1199,7 @@ void LLFolderView::paste() std::set<LLFolderViewItem*>::iterator set_iter; for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) { - LLFolderViewEventListener* listener = (*set_iter)->getListener(); + LLFolderViewModelItemInventory* listener = (*set_iter)->getListener(); if(listener && listener->isClipboardPasteable()) { listener->pasteFromClipboard(); @@ -1845,7 +1642,7 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) S32 count = mSelectedItems.size(); LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); if ( handled - && ( count > 0 && (hasVisibleChildren() || mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) ) // show menu only if selected items are visible + && ( count > 0 && (hasVisibleChildren()) ) // show menu only if selected items are visible && menu ) { if (mCallbackRegistrar) @@ -2032,55 +1829,6 @@ void LLFolderView::setShowSingleSelection(BOOL show) } } -void LLFolderView::addItemID(const LLUUID& id, LLFolderViewItem* itemp) -{ - mItemMap[id] = itemp; -} - -void LLFolderView::removeItemID(const LLUUID& id) -{ - mItemMap.erase(id); -} - -LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); -LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id) -{ - LLFastTimer _(FTM_GET_ITEM_BY_ID); - if (id == getListener()->getUUID()) - { - return this; - } - - std::map<LLUUID, LLFolderViewItem*>::iterator map_it; - map_it = mItemMap.find(id); - if (map_it != mItemMap.end()) - { - return map_it->second; - } - - return NULL; -} - -LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id) -{ - if (id == getListener()->getUUID()) - { - return this; - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end(); - ++iter) - { - LLFolderViewFolder *folder = (*iter); - if (folder->getListener()->getUUID() == id) - { - return folder; - } - } - return NULL; -} - bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) { std::string action = userdata.asString(); @@ -2111,7 +1859,7 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) } - std::set<LLUUID> selected_items = getSelectionList(); + std::set<LLFolderViewItem*> selected_items = getSelectionList(); LLMultiPreview* multi_previewp = NULL; LLMultiProperties* multi_propertiesp = NULL; @@ -2132,11 +1880,11 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) LLFloater::setFloaterHost(multi_propertiesp); } - std::set<LLUUID>::iterator set_iter; + std::set<LLFolderViewItem*>::iterator set_iter; for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) { - LLFolderViewItem* folder_item = getItemByID(*set_iter); + LLFolderViewItem* folder_item = *set_iter; if(!folder_item) continue; LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); if(!bridge) continue; @@ -2486,72 +2234,18 @@ void LLFolderView::onRenamerLost() } } -LLInventoryFilter* LLFolderView::getFilter() +LLFolderViewFilter* LLFolderView::getFilter() { return mFilter; } -void LLFolderView::setFilterPermMask( PermissionMask filter_perm_mask ) -{ - mFilter->setFilterPermissions(filter_perm_mask); -} - -U32 LLFolderView::getFilterObjectTypes() const -{ - return mFilter->getFilterObjectTypes(); -} - -PermissionMask LLFolderView::getFilterPermissions() const -{ - return mFilter->getFilterPermissions(); -} - -BOOL LLFolderView::isFilterModified() -{ - return mFilter->isNotDefault(); -} - -void delete_selected_item(void* user_data) -{ - if(user_data) - { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->removeSelectedItems(); - } -} - -void copy_selected_item(void* user_data) -{ - if(user_data) - { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->copy(); - } -} - -void paste_items(void* user_data) -{ - if(user_data) - { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->paste(); - } -} - -void open_selected_items(void* user_data) -{ - if(user_data) - { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->openSelectedItems(); - } -} - -void properties_selected_items(void* user_data) +S32 LLFolderView::getItemHeight() { - if(user_data) + S32 debug_height = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; + if(!hasVisibleChildren()) { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->propertiesSelectedItems(); + //We need to display status textbox, let's reserve some place for it + return llmax(debug_height, mStatusTextBox->getTextPixelHeight()); } + return debug_height; } diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 9a6bf05cd1..15a3f662c4 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -47,9 +47,10 @@ #include "lltooldraganddrop.h" #include "llviewertexture.h" -class LLFolderViewEventListener; +class LLFolderViewModelInterface; class LLFolderViewFolder; class LLFolderViewItem; +class LLFolderViewFilter; class LLInventoryModel; class LLPanel; class LLLineEditor; @@ -76,8 +77,8 @@ public: Optional<bool> use_label_suffix, allow_multiselect, show_empty_message, - show_load_status, use_ellipses; + Mandatory<LLFolderViewModelInterface*> view_model; Params(); }; @@ -88,9 +89,8 @@ public: virtual LLFolderView* getRoot() { return this; } - // FolderViews default to sort by name. This will change that, - // and resort the items if necessary. - void setSortOrder(U32 order); + LLFolderViewModelInterface* getViewModel() { return mViewModel; } + void setFilterPermMask(PermissionMask filter_perm_mask); typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t; @@ -98,14 +98,7 @@ public: void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } // filter is never null - LLInventoryFilter* getFilter(); - const std::string getFilterSubString(BOOL trim = FALSE); - U32 getFilterObjectTypes() const; - PermissionMask getFilterPermissions() const; - // *NOTE: use getFilter()->getShowFolderState(); - //LLInventoryFilter::EFolderShow getShowFolderState(); - U32 getSortOrder() const; - BOOL isFilterModified(); + LLFolderViewFilter* getFilter(); bool getAllowMultiSelect() { return mAllowMultiSelect; } @@ -113,19 +106,18 @@ public: void closeAllFolders(); void openTopLevelFolders(); - virtual void toggleOpen() {}; - virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse); virtual BOOL addFolder( LLFolderViewFolder* folder); // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); + virtual S32 getItemHeight(); void arrangeAll() { mArrangeGeneration++; } S32 getArrangeGeneration() { return mArrangeGeneration; } - // applies filters to control visibility of inventory items - virtual void filter( LLInventoryFilter& filter); + // applies filters to control visibility of items + virtual void filter( LLFolderViewFilter& filter); // get the last selected item virtual LLFolderViewItem* getCurSelectedItem( void ); @@ -134,21 +126,15 @@ public: virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); - // Used by menu callbacks - void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); - - // Called once a frame to update the selection if mSelectThisID has been set - void updateSelection(); - // This method is used to toggle the selection of an item. Walks // children, and keeps track of selected objects. virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - virtual std::set<LLUUID> getSelectionList() const; + virtual std::set<LLFolderViewItem*> getSelectionList() const; // make sure if ancestor is selected, descendents are not void sanitizeSelection(); - void clearSelection(); + virtual void clearSelection(); void addToSelectionList(LLFolderViewItem* item); void removeFromSelectionList(LLFolderViewItem* item); @@ -170,6 +156,7 @@ public: void autoOpenItem(LLFolderViewFolder* item); void closeAutoOpenedFolders(); BOOL autoOpenTest(LLFolderViewFolder* item); + BOOL isOpen() const { return TRUE; } // root folder always open // copy & paste virtual void copy(); @@ -218,11 +205,6 @@ public: F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } bool getUseEllipses() { return mUseEllipses; } - void addItemID(const LLUUID& id, LLFolderViewItem* itemp); - void removeItemID(const LLUUID& id); - LLFolderViewItem* getItemByID(const LLUUID& id); - LLFolderViewFolder* getFolderByID(const LLUUID& id); - bool doToSelected(LLInventoryModel* model, const LLSD& userdata); void doIdle(); // Real idle routine @@ -267,6 +249,8 @@ protected: void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response); + LLInventorySort& getSortFunction() { return mSortFunction; } + protected: LLHandle<LLView> mPopupMenuHandle; @@ -297,7 +281,7 @@ protected: LLFrameTimer mAutoOpenTimer; LLFrameTimer mSearchTimer; std::string mSearchString; - LLInventoryFilter* mFilter; + LLFolderViewFilter* mFilter; BOOL mShowSelectionContext; BOOL mShowSingleSelection; LLFrameTimer mMultiSelectionFadeTimer; @@ -307,14 +291,13 @@ protected: signal_t mReshapeSignal; S32 mSignalSelectCallback; S32 mMinWidth; - S32 mRunningHeight; - std::map<LLUUID, LLFolderViewItem*> mItemMap; BOOL mDragAndDropThisFrame; - LLUUID mSelectThisID; // if non null, select this item - LLPanel* mParentPanel; + LLInventorySort mSortFunction; + LLFolderViewModelInterface* mViewModel; + /** * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. * NOTE: For now it uses only to cut LLFolderViewItem::mLabel text to be used for Landmarks in Places Panel. @@ -334,9 +317,6 @@ public: }; -bool sort_item_name(LLFolderViewItem* a, LLFolderViewItem* b); -bool sort_item_date(LLFolderViewItem* a, LLFolderViewItem* b); - // Flags for buildContextMenu() const U32 SUPPRESS_OPEN_ITEM = 0x1; const U32 FIRST_SELECTED_ITEM = 0x2; diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h index aee31ca033..280708a39c 100644 --- a/indra/newview/llfoldervieweventlistener.h +++ b/indra/newview/llfoldervieweventlistener.h @@ -32,72 +32,263 @@ #include "llpermissionsflags.h" #include "llpointer.h" #include "llwearabletype.h" +#include "lltooldraganddrop.h" +// These are grouping of inventory types. +// Order matters when sorting system folders to the top. +enum EInventorySortGroup +{ + SG_SYSTEM_FOLDER, + SG_TRASH_FOLDER, + SG_NORMAL_FOLDER, + SG_ITEM +}; -class LLFolderViewItem; -class LLFolderView; class LLFontGL; class LLInventoryModel; class LLMenuGL; -class LLScrollContainer; class LLUIImage; class LLUUID; +class LLFolderViewItem; +class LLFolderViewFolder; -// This is an abstract base class that users of the folderview classes -// would use to catch the useful events emitted from the folder -// views. -class LLFolderViewEventListener +class LLFolderViewFilter { public: - virtual ~LLFolderViewEventListener( void ) {} + LLFolderViewFilter() {} + virtual ~LLFolderViewFilter() {} + + // +-------------------------------------------------------------------+ + // + Execution And Results + // +-------------------------------------------------------------------+ + virtual bool check(const LLFolderViewItem* item) = 0; + virtual bool check(const LLInventoryItem* item) = 0; + virtual bool checkFolder(const LLFolderViewFolder* folder) const = 0; + virtual bool checkFolder(const LLUUID& folder_id) const = 0; + + virtual void setEmptyLookupMessage(const std::string& message) = 0; + const virtual std::string& getEmptyLookupMessage() const = 0; + + // +-------------------------------------------------------------------+ + // + Status + // +-------------------------------------------------------------------+ + virtual bool isActive() const = 0; + virtual bool isModified() const = 0; + virtual bool isModifiedAndClear() = 0; + virtual void clearModified() = 0; + virtual const std::string& getName() const = 0; + virtual const std::string& getFilterText() = 0; + //RN: this is public to allow system to externally force a global refilter + virtual void setModified(EFilterBehavior behavior = FILTER_RESTART) = 0; + + // +-------------------------------------------------------------------+ + // + Count + // +-------------------------------------------------------------------+ + virtual void setFilterCount(S32 count) = 0; + virtual S32 getFilterCount() const = 0; + virtual void decrementFilterCount() = 0; + + // +-------------------------------------------------------------------+ + // + Default + // +-------------------------------------------------------------------+ + virtual BOOL isNotDefault() const = 0; + virtual void markDefault() = 0; + virtual void resetDefault() = 0; + + // +-------------------------------------------------------------------+ + // + Generation + // +-------------------------------------------------------------------+ + virtual S32 getCurrentGeneration() const = 0; + virtual S32 getFirstSuccessGeneration() const = 0; + virtual S32 getFirstRequiredGeneration() const = 0; +}; + +struct LLFolderViewModelInterface +{ + virtual void requestSortAll() = 0; + virtual void requestSort(class LLFolderViewFolder*) = 0; + + virtual void sort(class LLFolderViewFolder*) = 0; + virtual void filter(class LLFolderViewFolder*) = 0; +}; + +struct LLFolderViewModelCommon : public LLFolderViewModelInterface +{ + LLFolderViewModelCommon() + : mTargetSortVersion(0) + {} + + virtual void requestSortAll() + { + // sort everything + mTargetSortVersion++; + } + + virtual void requestSort(class LLFolderViewFolder* folder) + { + folder->requestSort(); + } + +protected: + bool needsSort(class LLFolderViewModelItem* item) + { + return item->getSortVersion() < mTargetSortVersion; + } + + S32 mTargetSortVersion; +}; + + +// This is am abstract base class that users of the folderview classes +// would use to bridge the folder view with the underlying data +class LLFolderViewModelItem +{ +public: + virtual ~LLFolderViewModelItem( void ) {}; + + virtual void update() {} //called when drawing virtual const std::string& getName() const = 0; virtual const std::string& getDisplayName() const = 0; - virtual const LLUUID& getUUID() const = 0; - virtual time_t getCreationDate() const = 0; // UTC seconds - virtual PermissionMask getPermissionMask() const = 0; - virtual LLFolderType::EType getPreferredType() const = 0; + virtual LLPointer<LLUIImage> getIcon() const = 0; virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } + virtual LLFontGL::StyleFlags getLabelStyle() const = 0; virtual std::string getLabelSuffix() const = 0; + virtual void openItem( void ) = 0; virtual void closeItem( void ) = 0; - virtual void previewItem( void ) = 0; virtual void selectItem(void) = 0; - virtual void showProperties(void) = 0; + virtual BOOL isItemRenameable() const = 0; virtual BOOL renameItem(const std::string& new_name) = 0; + virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder + virtual void move( LLFolderViewModelItem* parent_listener ) = 0; + virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed - virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. virtual BOOL removeItem() = 0; - virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) = 0; - virtual void move( LLFolderViewEventListener* parent_listener ) = 0; + virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0; + virtual BOOL isItemCopyable() const = 0; virtual BOOL copyToClipboard() const = 0; virtual void cutToClipboard() = 0; + virtual BOOL isClipboardPasteable() const = 0; virtual void pasteFromClipboard() = 0; virtual void pasteLinkFromClipboard() = 0; + virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; - virtual BOOL isUpToDate() const = 0; - virtual BOOL hasChildren() const = 0; - virtual LLInventoryType::EType getInventoryType() const = 0; - virtual void performAction(LLInventoryModel* model, std::string action) = 0; - virtual LLWearableType::EType getWearableType() const = 0; - + // This method should be called when a drag begins. returns TRUE // if the drag can begin, otherwise FALSE. + virtual LLToolDragAndDrop::ESource getDragSource() const = 0; virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; - + // This method will be called to determine if a drop can be // performed, and will set drop to TRUE if a drop is // requested. Returns TRUE if a drop is possible/happened, // otherwise FALSE. virtual BOOL dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - std::string& tooltip_msg) = 0; + EDragAndDropType cargo_type, + void* cargo_data, + std::string& tooltip_msg) = 0; + + virtual void requestSort() = 0; + virtual S32 getSortVersion() = 0; + virtual void setSortVersion(S32 version) = 0; +}; + +class LLFolderViewModelItemCommon : public LLFolderViewModelItem +{ +public: + LLFolderViewModelItemCommon() + : mSortVersion(-1) + {} + + void requestSort() { mSortVersion = -1; } + S32 getSortVersion() { return mSortVersion; } + void setSortVersion(S32 version) { mSortVersion = VERSION;} + +protected: + S32 mSortVersion; +}; + +template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE> +class LLFolderViewModel : public LLFolderViewModelCommon +{ +protected: + LLFolderViewModel() {} + + typedef SORT_TYPE SortType; + typedef ITEM_TYPE ItemType; + typedef FOLDER_TYPE FolderType; + typedef FILTER_TYPE FilterType; + + virtual const SortType& getSorter() const { return mSorter; } + virtual void setSorter(const SortType& type) { mSorter = sorter; requestSortAll(); } + virtual FilterType& getFilter() const { return mFilter; } + virtual void setFilter(const FilterType& filter) { mFilter = filter; } + +public: + + struct ViewModelCompare() + { + ViewModelCompare(const SortType& sorter) + : mSorter(sorter) + {} + + int operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) + { + return mSorter(static_cast<const ItemType*>(a->getListener()), static_cast<const ItemType*>(b->getListener())); + } + + int operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) + { + return mSorter(static_cast<const ItemType*>(a->getListener()), static_cast<const ItemType*>(b->getListener())); + } + + const SortType& mSorter; + } + + void sort(LLFolderViewFolder* folder) + { + if (needsSort(folder)) + { + std::sort(folder->getFoldersBegin(), folder->getFoldersEnd(), ViewModelCompare(getSorter())); + std::sort(folder->getItemsBegin(), folder->getItemsEnd(), ViewModelCompare(getSorter())); + folder->getListener()->setSortVersion(mTargetSortVersion); + folder->requestArrange(); + } + } + + void filter(LLFolderViewFolder* folder) + { + FilterType& filter = getFilter(); + for (std::list<LLFolderViewItem*>::iterator it = folder->getItemsBegin(), end_it = folder->getItemsEnd(); + it != end_it; + ++it) + { + LLFolderViewItem* child_item = *it; + child_item->setFiltered(filter(static_cast<ItemType*>(child_item->getListener())), filter.getCurrentGeneration()) + } + + for (std::list<LLFolderViewFolder*>::iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); + it != end_it; + ++it) + { + LLFolderViewItem* child_folder = *it; + child_folder->setFiltered(filter(static_cast<ItemType*>(child_folder->getListener())), filter.getCurrentGeneration()) + } + } + +protected: + SortType mSorter; + FilterType mFilter; }; + + + + #endif diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 43d3675d17..f452ae25c3 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -29,6 +29,7 @@ // viewer includes #include "llfolderview.h" // Items depend extensively on LLFolderViews +#include "llfolderview.h" #include "llfoldervieweventlistener.h" #include "llviewerfoldertype.h" #include "llinventorybridge.h" // for LLItemBridge in LLInventorySort::operator() @@ -121,15 +122,12 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mStringMatchOffset(std::string::npos), mControlLabelRotation(0.f), mDragAndDropTarget(FALSE), - mIsLoading(FALSE), mLabel(p.name), mRoot(p.root), - mCreationDate(p.creation_date), mIcon(p.icon), mIconOpen(p.icon_open), mIconOverlay(p.icon_overlay), mListener(p.listener), - mShowLoadStatus(false), mIsMouseOverTitle(false) { } @@ -218,14 +216,13 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) // until we find out otherwise BOOL LLFolderViewItem::potentiallyVisible() { - // we haven't been checked against min required filter - // or we have and we passed - return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered(); + return getFiltered() // we've passed the filter + || getLastFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration()); // or we don't know yet } BOOL LLFolderViewItem::getFiltered() { - return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); + return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getFirstSuccessGeneration(); } BOOL LLFolderViewItem::getFiltered(S32 filter_generation) @@ -244,60 +241,47 @@ void LLFolderViewItem::setIcon(LLUIImagePtr icon) mIcon = icon; } -// refresh information from the listener -void LLFolderViewItem::refreshFromListener() +void LLFolderViewItem::refresh() { - if(mListener) - { - mLabel = mListener->getDisplayName(); - LLFolderType::EType preferred_type = mListener->getPreferredType(); - - // *TODO: to be removed when database supports multi language. This is a - // temporary attempt to display the inventory folder in the user locale. - // mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID - // it uses the same way to find localized string + if(!getListener()) return; - // HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) - // Translation of Accessories folder in Library inventory folder - bool accessories = false; - if(mLabel == std::string("Accessories")) - { - //To ensure that Accessories folder is in Library we have to check its parent folder. - //Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model - LLInventoryCategory* cat = gInventory.getCategory(mListener->getUUID()); - if(cat) - { - const LLUUID& parent_folder_id = cat->getParentUUID(); - accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); - } - } + mLabel = getListener()->getDisplayName(); + LLFolderType::EType preferred_type = getListener()->getPreferredType(); - //"Accessories" inventory category has folder type FT_NONE. So, this folder - //can not be detected as protected with LLFolderType::lookupIsProtectedType - if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) - { - LLTrans::findString(mLabel, "InvFolder " + mLabel); - }; + // *TODO: to be removed when database supports multi language. This is a + // temporary attempt to display the inventory folder in the user locale. + // mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID + // it uses the same way to find localized string - setToolTip(mLabel); - setIcon(mListener->getIcon()); - time_t creation_date = mListener->getCreationDate(); - if ((creation_date > 0) && (mCreationDate != creation_date)) - { - setCreationDate(creation_date); - dirtyFilter(); - } - if (mRoot->useLabelSuffix()) + // HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) + // Translation of Accessories folder in Library inventory folder + bool accessories = false; + if(mLabel == std::string("Accessories")) + { + //To ensure that Accessories folder is in Library we have to check its parent folder. + //Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model + LLInventoryCategory* cat = gInventory.getCategory(getListener()->getUUID()); + if(cat) { - mLabelStyle = mListener->getLabelStyle(); - mLabelSuffix = mListener->getLabelSuffix(); + const LLUUID& parent_folder_id = cat->getParentUUID(); + accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); } } -} -void LLFolderViewItem::refresh() -{ - refreshFromListener(); + //"Accessories" inventory category has folder type FT_NONE. So, this folder + //can not be detected as protected with LLFolderType::lookupIsProtectedType + if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) + { + LLTrans::findString(mLabel, "InvFolder " + mLabel); + }; + + setToolTip(mLabel); + setIcon(getListener()->getIcon()); + if (mRoot->useLabelSuffix()) + { + mLabelStyle = getListener()->getLabelStyle(); + mLabelSuffix = getListener()->getLabelSuffix(); + } std::string searchable_label(mLabel); searchable_label.append(mLabelSuffix); @@ -316,11 +300,7 @@ void LLFolderViewItem::refresh() } mLabelWidthDirty = true; -} - -void LLFolderViewItem::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) -{ - functor(mListener); + dirtyFilter(); } // This function is called when items are added or view filters change. It's @@ -386,19 +366,14 @@ void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL getRoot()->changeSelection(selection, selected); } -std::set<LLUUID> LLFolderViewItem::getSelectionList() const +std::set<LLFolderViewItem*> LLFolderViewItem::getSelectionList() const { - std::set<LLUUID> selection; + std::set<LLFolderViewItem*> selection; return selection; } -EInventorySortGroup LLFolderViewItem::getSortGroup() const -{ - return SG_ITEM; -} - // addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) { if (!folder) { @@ -459,7 +434,7 @@ void LLFolderViewItem::filter( LLInventoryFilter& filter) } setFiltered(passed_filter, filter.getCurrentGeneration()); - mStringMatchOffset = filter.getStringMatchOffset(); + mStringMatchOffset = filter.getStringMatchOffset(this); filter.decrementFilterCount(); if (getRoot()->getDebugFilters()) @@ -522,9 +497,9 @@ void LLFolderViewItem::selectItem(void) { if (mIsSelected == FALSE) { - if (mListener) + if (getListener()) { - mListener->selectItem(); + getListener()->selectItem(); } mIsSelected = TRUE; } @@ -532,9 +507,9 @@ void LLFolderViewItem::selectItem(void) BOOL LLFolderViewItem::isMovable() { - if( mListener ) + if( getListener() ) { - return mListener->isItemMovable(); + return getListener()->isItemMovable(); } else { @@ -544,9 +519,9 @@ BOOL LLFolderViewItem::isMovable() BOOL LLFolderViewItem::isRemovable() { - if( mListener ) + if( getListener() ) { - return mListener->isItemRemovable(); + return getListener()->isItemRemovable(); } else { @@ -572,9 +547,9 @@ BOOL LLFolderViewItem::remove() { return FALSE; } - if(mListener) + if(getListener()) { - return mListener->removeItem(); + return getListener()->removeItem(); } return TRUE; } @@ -582,25 +557,25 @@ BOOL LLFolderViewItem::remove() // Build an appropriate context menu for the item. void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) { - if(mListener) + if(getListener()) { - mListener->buildContextMenu(menu, flags); + getListener()->buildContextMenu(menu, flags); } } void LLFolderViewItem::openItem( void ) { - if( mListener ) + if( getListener() ) { - mListener->openItem(); + getListener()->openItem(); } } void LLFolderViewItem::preview( void ) { - if (mListener) + if (getListener()) { - mListener->previewItem(); + getListener()->previewItem(); } } @@ -608,9 +583,9 @@ void LLFolderViewItem::rename(const std::string& new_name) { if( !new_name.empty() ) { - if( mListener ) + if( getListener() ) { - mListener->renameItem(new_name); + getListener()->renameItem(new_name); if(mParentFolder) { @@ -633,11 +608,11 @@ LLViewerInventoryItem * LLFolderViewItem::getInventoryItem(void) const std::string& LLFolderViewItem::getName( void ) const { - if(mListener) + if(getListener()) { - return mListener->getName(); + return getListener()->getName(); } - return mLabel; + return z; } // LLView functionality @@ -713,21 +688,19 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) // *TODO: push this into listener and remove // dependency on llagent - if (mListener - && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getRootFolderID())) + if (getListener()) { - src = LLToolDragAndDrop::SOURCE_AGENT; + src = getListener()->getDragSource(); } - else if (mListener - && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getLibraryRootFolderID())) + else { - src = LLToolDragAndDrop::SOURCE_LIBRARY; + src = LLToolDragAndDrop::SOURCE_VIEWER; } can_drag = root->startDrag(src); if (can_drag) { - // if (mListener) mListener->startDrag(); + // if (getListener()) getListener()->startDrag(); // RN: when starting drag and drop, clear out last auto-open root->autoOpenTest(NULL); root->setShowSelectionContext(TRUE); @@ -816,9 +789,9 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, { BOOL accepted = FALSE; BOOL handled = FALSE; - if(mListener) + if(getListener()) { - accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + accepted = getListener()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); handled = accepted; if (accepted) { @@ -864,15 +837,14 @@ void LLFolderViewItem::draw() const S32 FOCUS_LEFT = 1; const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - const BOOL in_inventory = getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getRootFolderID()); - const BOOL in_library = getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getLibraryRootFolderID()); + getListener()->update(); //--------------------------------------------------------------------------------// // Draw open folder arrow // - const bool up_to_date = mListener && mListener->isUpToDate(); + const bool up_to_date = getListener() && getListener()->isUpToDate(); const bool possibly_has_children = ((up_to_date && hasVisibleChildren()) // we fetched our children and some of them have passed the filter... - || (!up_to_date && mListener && mListener->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter) + || (!up_to_date && getListener() && getListener()->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter) if (possibly_has_children) { LLUIImage* arrow_image = default_params.folder_arrow_image; @@ -1030,30 +1002,6 @@ void LLFolderViewItem::draw() LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); - //--------------------------------------------------------------------------------// - // Draw "Loading..." text - // - bool root_is_loading = false; - if (in_inventory) - { - root_is_loading = LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress(); - } - if (in_library) - { - root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress(); - } - if ((mIsLoading - && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) - || (LLInventoryModelBackgroundFetch::instance().folderFetchActive() - && root_is_loading - && mShowLoadStatus)) - { - std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) "; - font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x, FALSE); - } - //--------------------------------------------------------------------------------// // Draw label suffix // @@ -1067,28 +1015,29 @@ void LLFolderViewItem::draw() //--------------------------------------------------------------------------------// // Highlight string match // - if (mStringMatchOffset != std::string::npos) - { - // don't draw backgrounds for zero-length strings - S32 filter_string_length = getRoot()->getFilterSubString().size(); - if (filter_string_length > 0) - { - std::string combined_string = mLabel + mLabelSuffix; - S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; - S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; - S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); - S32 top = getRect().getHeight() - TOP_PAD; - - LLUIImage* box_image = default_params.selection_image; - LLRect box_rect(left, top, right, bottom); - box_image->draw(box_rect, sFilterBGColor); - F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); - F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; - font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, - sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - filter_string_length, S32_MAX, &right_x, FALSE ); - } - } + RN: expose interface for highlighting + //if (mStringMatchOffset != std::string::npos) + //{ + // // don't draw backgrounds for zero-length strings + // S32 filter_string_length = getRoot()->getFilterSubString().size(); + // if (filter_string_length > 0) + // { + // std::string combined_string = mLabel + mLabelSuffix; + // S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; + // S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; + // S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); + // S32 top = getRect().getHeight() - TOP_PAD; + // + // LLUIImage* box_image = default_params.selection_image; + // LLRect box_rect(left, top, right, bottom); + // box_image->draw(box_rect, sFilterBGColor); + // F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); + // F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + // font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, + // sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + // filter_string_length, S32_MAX, &right_x, FALSE ); + // } + //} } @@ -1097,19 +1046,16 @@ void LLFolderViewItem::draw() ///---------------------------------------------------------------------------- LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): - LLFolderViewItem( p ), // 0 = no create time + LLFolderViewItem( p ), mIsOpen(FALSE), mExpanderHighlighted(FALSE), mCurHeight(0.f), mTargetHeight(0.f), mAutoOpenCountdown(0.f), - mSubtreeCreationDate(0), - mAmTrash(LLFolderViewFolder::UNKNOWN), mLastArrangeGeneration( -1 ), mLastCalculatedWidth(0), mCompletedFilterGeneration(-1), mMostFilteredDescendantGeneration(-1), - mNeedsSort(false), mPassedFolderFilter(FALSE) { } @@ -1130,32 +1076,30 @@ void LLFolderViewFolder::setFilteredFolder(bool filtered, S32 filter_generation) bool LLFolderViewFolder::getFilteredFolder(S32 filter_generation) { - return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); + return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter()->getFirstSuccessGeneration(); } // addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) { if (!folder) { return FALSE; } mParentFolder = folder; - root->addItemID(getListener()->getUUID(), this); return folder->addFolder(this); } +static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); + // Finds width and height of this object and its children. Also // makes sure that this view and its children are the right size. S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) { // sort before laying out contents - if (mNeedsSort) - { - mFolders.sort(mSortFunction); - mItems.sort(mSortFunction); - mNeedsSort = false; - } + getRoot->getViewModel()->sort(this); + + LLFastTimer t2(FTM_ARRANGE); mHasVisibleChildren = hasFilteredDescendants(filter_generation); @@ -1166,7 +1110,6 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) mCurHeight = llmax((F32)*height, mCurHeight); // initialize running height value as height of single item in case we have no children - *height = getItemHeight(); F32 running_height = (F32)*height; F32 target_height = (F32)*height; @@ -1176,7 +1119,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) // set last arrange generation first, in case children are animating // and need to be arranged again mLastArrangeGeneration = getRoot()->getArrangeGeneration(); - if (mIsOpen) + if (isOpen()) { // Add sizes of children S32 parent_item_height = getRect().getHeight(); @@ -1252,7 +1195,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) // animate current height towards target height if (llabs(mCurHeight - mTargetHeight) > 1.f) { - mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(mIsOpen ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); + mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); requestArrange(); @@ -1303,9 +1246,7 @@ BOOL LLFolderViewFolder::needsArrange() void LLFolderViewFolder::requestSort() { - mNeedsSort = true; - // whenever item order changes, we need to lay things out again - requestArrange(); + getRoot()->getViewModel()->requestSort(this); } void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up) @@ -1327,7 +1268,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) // if failed to pass filter newer than must_pass_generation // you will automatically fail this time, so we only // check against items that have passed the filter - S32 must_pass_generation = filter.getMustPassGeneration(); + S32 must_pass_generation = filter.getFirstRequiredGeneration(); bool autoopen_folders = (filter.hasFilterString()); @@ -1380,11 +1321,11 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) // when applying a filter, matching folders get their contents downloaded first if (filter.isNotDefault() - && getFiltered(filter.getMinRequiredGeneration()) - && (mListener - && !gInventory.isCategoryComplete(mListener->getUUID()))) + && getFiltered(filter.getFirstSuccessGeneration()) + && (getListener() + && !gInventory.isCategoryComplete(getListener()->getUUID()))) { - LLInventoryModelBackgroundFetch::instance().start(mListener->getUUID()); + LLInventoryModelBackgroundFetch::instance().start(getListener()->getUUID()); } // now query children @@ -1405,7 +1346,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) if (folder->getCompletedFilterGeneration() >= filter_generation) { // track latest generation to pass any child items - if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getMinRequiredGeneration())) + if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getFirstSuccessGeneration())) { mMostFilteredDescendantGeneration = filter_generation; requestArrange(); @@ -1459,7 +1400,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) item->filter( filter ); - if (item->getFiltered(filter.getMinRequiredGeneration())) + if (item->getFiltered(filter.getFirstSuccessGeneration())) { mMostFilteredDescendantGeneration = filter_generation; requestArrange(); @@ -1524,8 +1465,8 @@ void LLFolderViewFolder::dirtyFilter() BOOL LLFolderViewFolder::getFiltered() { - return getFilteredFolder(getRoot()->getFilter()->getMinRequiredGeneration()) - && LLFolderViewItem::getFiltered(); + return getFilteredFolder(getRoot()->getFilter()->getFirstSuccessGeneration()) + && LLFolderViewItem::getFiltered(); } BOOL LLFolderViewFolder::getFiltered(S32 filter_generation) @@ -1541,7 +1482,7 @@ BOOL LLFolderViewFolder::hasFilteredDescendants(S32 filter_generation) BOOL LLFolderViewFolder::hasFilteredDescendants() { - return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration(); + return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getFirstSuccessGeneration(); } // Passes selection information on to children and record selection @@ -1896,14 +1837,6 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) void LLFolderViewFolder::destroyView() { - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - LLFolderViewItem* item = (*iit); - getRoot()->removeItemID(item->getListener()->getUUID()); - } - std::for_each(mItems.begin(), mItems.end(), DeletePointer()); mItems.clear(); @@ -1913,8 +1846,6 @@ void LLFolderViewFolder::destroyView() folderp->destroyView(); // removes entry from mFolders } - //deleteAllChildren(); - if (mParentFolder) { mParentFolder->removeView(this); @@ -1976,103 +1907,14 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) dirtyFilter(); //because an item is going away regardless of filter status, force rearrange requestArrange(); - getRoot()->removeItemID(item->getListener()->getUUID()); removeChild(item); } -bool LLFolderViewFolder::isTrash() const -{ - if (mAmTrash == LLFolderViewFolder::UNKNOWN) - { - mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH; - } - return mAmTrash == LLFolderViewFolder::TRASH; -} - -void LLFolderViewFolder::sortBy(U32 order) -{ - if (!mSortFunction.updateSort(order)) - { - // No changes. - return; - } - - // Propagate this change to sub folders - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->sortBy(order); - } - - // Don't sort the topmost folders (My Inventory and Library) - if (mListener->getUUID().notNull()) - { - mFolders.sort(mSortFunction); - mItems.sort(mSortFunction); - } - - if (order & LLInventoryFilter::SO_DATE) - { - time_t latest = 0; - - if (!mItems.empty()) - { - LLFolderViewItem* item = *(mItems.begin()); - latest = item->getCreationDate(); - } - - if (!mFolders.empty()) - { - LLFolderViewFolder* folder = *(mFolders.begin()); - if (folder->getCreationDate() > latest) - { - latest = folder->getCreationDate(); - } - } - mSubtreeCreationDate = latest; - } -} - -void LLFolderViewFolder::setItemSortOrder(U32 ordering) -{ - if (mSortFunction.updateSort(ordering)) - { - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->setItemSortOrder(ordering); - } - - mFolders.sort(mSortFunction); - mItems.sort(mSortFunction); - } -} - -EInventorySortGroup LLFolderViewFolder::getSortGroup() const -{ - if (isTrash()) - { - return SG_TRASH_FOLDER; - } - - if( mListener ) - { - if(LLFolderType::lookupIsProtectedType(mListener->getPreferredType())) - { - return SG_SYSTEM_FOLDER; - } - } - - return SG_NORMAL_FOLDER; -} - BOOL LLFolderViewFolder::isMovable() { - if( mListener ) + if( getListener() ) { - if( !(mListener->isItemMovable()) ) + if( !(getListener()->isItemMovable()) ) { return FALSE; } @@ -2103,9 +1945,9 @@ BOOL LLFolderViewFolder::isMovable() BOOL LLFolderViewFolder::isRemovable() { - if( mListener ) + if( getListener() ) { - if( !(mListener->isItemRemovable()) ) + if( !(getListener()->isItemRemovable()) ) { return FALSE; } @@ -2145,37 +1987,23 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) item->dirtyFilter(); - // Update the folder creation date if the folder has no creation date - bool setting_date = false; - const time_t item_creation_date = item->getCreationDate(); - if ((item_creation_date > 0) && (mCreationDate == 0)) - { - setCreationDate(item_creation_date); - setting_date = true; - } - // Handle sorting requestArrange(); requestSort(); - // Traverse parent folders and update creation date and resort, if necessary - LLFolderViewFolder* parentp = getParentFolder(); - while (parentp) - { - // Update the parent folder creation date - if (setting_date && (parentp->mCreationDate == 0)) - { - parentp->setCreationDate(item_creation_date); - } + FIXME: RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria + //// Traverse parent folders and update creation date and resort, if necessary + //LLFolderViewFolder* parentp = this; + //while (parentp) + //{ + // if (parentp->mSortFunction.isByDate()) + // { + // // parent folder doesn't have a time stamp yet, so get it from us + // parentp->requestSort(); + // } - if (parentp->mSortFunction.isByDate()) - { - // parent folder doesn't have a time stamp yet, so get it from us - parentp->requestSort(); - } - - parentp = parentp->getParentFolder(); - } + // parentp = parentp->getParentFolder(); + //} return TRUE; } @@ -2192,12 +2020,15 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) // rearrange all descendants too, as our indentation level might have changed folder->requestArrange(TRUE); requestSort(); - LLFolderViewFolder* parentp = getParentFolder(); - while (parentp && !parentp->mSortFunction.isByDate()) + if (getRoot()->getSortFunction().isByDate()) { - // parent folder doesn't have a time stamp yet, so get it from us - parentp->requestSort(); - parentp = parentp->getParentFolder(); + LLFolderViewFolder* parentp = getParentFolder(); + while(parentp) + { + // parent folder doesn't have a time stamp yet, so get it from us + parentp->requestSort(); + parentp = parentp->getParentFolder(); + } } return TRUE; } @@ -2224,7 +2055,7 @@ void LLFolderViewFolder::requestArrange(BOOL include_descendants) void LLFolderViewFolder::toggleOpen() { - setOpen(!mIsOpen); + setOpen(!isOpen()); } // Force a folder open or closed @@ -2235,17 +2066,17 @@ void LLFolderViewFolder::setOpen(BOOL openitem) void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) { - BOOL was_open = mIsOpen; + BOOL was_open = isOpen(); mIsOpen = openitem; - if (mListener) + if (getListener()) { if(!was_open && openitem) { - mListener->openItem(); + getListener()->openItem(); } else if(was_open && !openitem) { - mListener->closeItem(); + getListener()->closeItem(); } } @@ -2265,7 +2096,7 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP); } - if (was_open != mIsOpen) + if (was_open != isOpen()) { requestArrange(); } @@ -2334,23 +2165,6 @@ void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) } } -void LLFolderViewFolder::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) -{ - functor(mListener); - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->applyListenerFunctorRecursively(functor); - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - (*iit)->applyListenerFunctorRecursively(functor); - } -} - // LLView functionality BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, @@ -2361,7 +2175,7 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, { BOOL handled = FALSE; - if (mIsOpen) + if (isOpen()) { handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL); } @@ -2383,7 +2197,7 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = mListener && mListener->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); + BOOL accepted = getListener() && getListener()->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); if (accepted) { @@ -2409,9 +2223,9 @@ BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) BOOL handled = FALSE; // fetch contents of this folder, as context menu can depend on contents // still, user would have to open context menu again to see the changes - gInventory.fetchDescendentsOf(mListener->getUUID()); + gInventory.fetchDescendentsOf(getListener()->getUUID()); - if( mIsOpen ) + if( isOpen() ) { handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; } @@ -2441,7 +2255,7 @@ BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) { BOOL handled = FALSE; - if( mIsOpen ) + if( isOpen() ) { handled = childrenHandleMouseDown(x,y,mask) != NULL; } @@ -2475,7 +2289,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) */ BOOL handled = FALSE; - if( mIsOpen ) + if( isOpen() ) { handled = childrenHandleDoubleClick( x, y, mask ) != NULL; } @@ -2503,7 +2317,7 @@ void LLFolderViewFolder::draw() { mControlLabelRotation = mAutoOpenCountdown * -90.f; } - else if (mIsOpen) + else if (isOpen()) { mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); } @@ -2512,31 +2326,10 @@ void LLFolderViewFolder::draw() mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); } - bool possibly_has_children = false; - bool up_to_date = mListener && mListener->isUpToDate(); - if(!up_to_date - && mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter) - { - possibly_has_children = true; - } - - - BOOL loading = (mIsOpen - && possibly_has_children - && !up_to_date ); - - if ( loading && !mIsLoading ) - { - // Measure how long we've been in the loading state - mTimeSinceRequestStart.reset(); - } - - mIsLoading = loading; - LLFolderViewItem::draw(); // draw children if root folder, or any other folder that is open or animating to closed state - if( getRoot() == this || (mIsOpen || mCurHeight != mTargetHeight )) + if( getRoot() == this || (isOpen() || mCurHeight != mTargetHeight )) { LLView::draw(); } @@ -2544,20 +2337,14 @@ void LLFolderViewFolder::draw() mExpanderHighlighted = FALSE; } -time_t LLFolderViewFolder::getCreationDate() const -{ - return llmax<time_t>(mCreationDate, mSubtreeCreationDate); -} - - BOOL LLFolderViewFolder::potentiallyVisible() { // folder should be visible by it's own filter status return LLFolderViewItem::potentiallyVisible() // or one or more of its descendants have passed the minimum filter requirement - || hasFilteredDescendants(getRoot()->getFilter()->getMinRequiredGeneration()) + || hasFilteredDescendants() // or not all of its descendants have been checked against minimum filter requirement - || getCompletedFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration(); + || getCompletedFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration(); } // this does prefix traversal, as folders are listed above their contents @@ -2771,41 +2558,27 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it return result; } - -bool LLInventorySort::updateSort(U32 order) -{ - if (order != mSortOrder) - { - mSortOrder = order; - mByDate = (order & LLInventoryFilter::SO_DATE); - mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); - mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); - return true; - } - return false; -} - -bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b) +bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) { // ignore sort order for landmarks in the Favorites folder. // they should be always sorted as in Favorites bar. See EXT-719 if (a->getSortGroup() == SG_ITEM && b->getSortGroup() == SG_ITEM - && a->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK - && b->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) + && a->getInventoryType() == LLInventoryType::IT_LANDMARK + && b->getInventoryType() == LLInventoryType::IT_LANDMARK) { static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - LLUUID a_uuid = a->getParentFolder()->getListener()->getUUID(); - LLUUID b_uuid = b->getParentFolder()->getListener()->getUUID(); + LLUUID a_uuid = a->getParentFolder()->getUUID(); + LLUUID b_uuid = b->getParentFolder()->getUUID(); if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) { // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem // or to LLInvFVBridge - LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a->getListener()))->getItem(); - LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b->getListener()))->getItem(); + LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a))->getItem(); + LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b))->getItem(); if (!aitem || !bitem) return false; S32 a_sort = aitem->getSortField(); @@ -2852,8 +2625,6 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde } else { - // BUG: This is very very slow. The getCreationDate() is log n in number - // of inventory items. time_t first_create = a->getCreationDate(); time_t second_create = b->getCreationDate(); if (first_create == second_create) @@ -2866,3 +2637,4 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde } } } + diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 4e8dc2da16..317228f1ad 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -30,52 +30,13 @@ #include "lldarray.h" // *TODO: Eliminate, forward declare #include "lluiimage.h" -class LLFontGL; class LLFolderView; -class LLFolderViewEventListener; +class LLFolderViewModelItemInventory; class LLFolderViewFolder; class LLFolderViewFunctor; -class LLFolderViewItem; -class LLFolderViewListenerFunctor; class LLInventoryFilter; -class LLMenuGL; -class LLUIImage; class LLViewerInventoryItem; -// These are grouping of inventory types. -// Order matters when sorting system folders to the top. -enum EInventorySortGroup -{ - SG_SYSTEM_FOLDER, - SG_TRASH_FOLDER, - SG_NORMAL_FOLDER, - SG_ITEM -}; - -// *TODO: do we really need one sort object per folder? -// can we just have one of these per LLFolderView ? -class LLInventorySort -{ -public: - LLInventorySort() - : mSortOrder(0), - mByDate(false), - mSystemToTop(false), - mFoldersByName(false) { } - - // Returns true if order has changed - bool updateSort(U32 order); - U32 getSort() { return mSortOrder; } - bool isByDate() { return mByDate; } - - bool operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b); -private: - U32 mSortOrder; - bool mByDate; - bool mSystemToTop; - bool mFoldersByName; -}; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderViewItem // @@ -91,78 +52,71 @@ public: struct Params : public LLInitParam::Block<Params, LLView::Params> { - Optional<LLUIImage*> icon; - Optional<LLUIImage*> icon_open; // used for folders - Optional<LLUIImage*> icon_overlay; // for links - Optional<LLFolderView*> root; - Mandatory<LLFolderViewEventListener*> listener; + Optional<LLUIImage*> icon, + icon_open, // used for folders + icon_overlay, // for links + folder_arrow_image, + selection_image; + Optional<LLFolderView*> root; + Mandatory<LLFolderViewModelItemInventory*> listener; - Optional<LLUIImage*> folder_arrow_image; - Optional<S32> folder_indentation; // pixels - Optional<LLUIImage*> selection_image; - Optional<S32> item_height; // pixels - Optional<S32> item_top_pad; // pixels + Optional<S32> folder_indentation, // pixels + item_height, + item_top_pad; - Optional<S32> creation_date; //UTC seconds + Optional<time_t> creation_date; Params(); }; // layout constants - static const S32 LEFT_PAD = 5; + static const S32 LEFT_PAD = 5; // LEFT_INDENTATION is set via folder_indentation above - static const S32 ICON_PAD = 2; - static const S32 ICON_WIDTH = 16; - static const S32 TEXT_PAD = 1; - static const S32 TEXT_PAD_RIGHT = 4; - static const S32 ARROW_SIZE = 12; + static const S32 ICON_PAD = 2; + static const S32 ICON_WIDTH = 16; + static const S32 TEXT_PAD = 1; + static const S32 TEXT_PAD_RIGHT = 4; + static const S32 ARROW_SIZE = 12; static const S32 MAX_FOLDER_ITEM_OVERLAP = 2; // animation parameters static const F32 FOLDER_CLOSE_TIME_CONSTANT; static const F32 FOLDER_OPEN_TIME_CONSTANT; - // Mostly for debugging printout purposes. const std::string& getSearchableLabel() { return mSearchableLabel; } - BOOL isLoading() const { return mIsLoading; } - private: BOOL mIsSelected; protected: friend class LLUICtrlFactory; - friend class LLFolderViewEventListener; + friend class LLFolderViewModelItem; LLFolderViewItem(const Params& p); - std::string mLabel; - std::string mSearchableLabel; - S32 mLabelWidth; - bool mLabelWidthDirty; - time_t mCreationDate; - LLFolderViewFolder* mParentFolder; - LLFolderViewEventListener* mListener; - BOOL mIsCurSelection; - BOOL mSelectPending; - LLFontGL::StyleFlags mLabelStyle; - std::string mLabelSuffix; - LLUIImagePtr mIcon; - std::string mStatusText; - LLUIImagePtr mIconOpen; - LLUIImagePtr mIconOverlay; - BOOL mHasVisibleChildren; - S32 mIndentation; - S32 mItemHeight; - BOOL mPassedFilter; - S32 mLastFilterGeneration; - std::string::size_type mStringMatchOffset; - F32 mControlLabelRotation; - LLFolderView* mRoot; - BOOL mDragAndDropTarget; - BOOL mIsLoading; - LLTimer mTimeSinceRequestStart; - bool mShowLoadStatus; - bool mIsMouseOverTitle; + std::string mLabel; + std::string mSearchableLabel; + S32 mLabelWidth; + bool mLabelWidthDirty; + LLFolderViewFolder* mParentFolder; + LLFolderViewModelItemInventory* mListener; + BOOL mIsCurSelection; + BOOL mSelectPending; + LLFontGL::StyleFlags mLabelStyle; + std::string mLabelSuffix; + LLUIImagePtr mIcon; + std::string mStatusText; + LLUIImagePtr mIconOpen; + LLUIImagePtr mIconOverlay; + BOOL mHasVisibleChildren; + S32 mIndentation; + S32 mItemHeight; + BOOL mPassedFilter; + S32 mLastFilterGeneration; + std::string::size_type mStringMatchOffset; + F32 mControlLabelRotation; + LLFolderView* mRoot; + BOOL mDragAndDropTarget; + bool mIsMouseOverTitle; // helper function to change the selection from the root. void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected); @@ -174,11 +128,11 @@ protected: static LLFontGL* getLabelFontForStyle(U8 style); - virtual void setCreationDate(time_t creation_date_utc) { mCreationDate = creation_date_utc; } - public: BOOL postBuild(); + virtual void openItem( void ); + // This function clears the currently selected item, and records // the specified selected item appropriately for display and use // in the UI. If open is TRUE, then folders are opened up along @@ -198,9 +152,7 @@ public: // addToFolder() returns TRUE if it succeeds. FALSE otherwise enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE }; - virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); - - virtual EInventorySortGroup getSortGroup() const; + virtual BOOL addToFolder(LLFolderViewFolder* folder); // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. @@ -231,7 +183,7 @@ public: virtual void selectItem(); // gets multiple-element selection - virtual std::set<LLUUID> getSelectionList() const; + virtual std::set<LLFolderViewItem*> getSelectionList() const; // Returns true is this object and all of its children can be removed (deleted by user) virtual BOOL isRemovable(); @@ -252,15 +204,13 @@ public: BOOL hasVisibleChildren() { return mHasVisibleChildren; } - void setShowLoadStatus(bool status) { mShowLoadStatus = status; } - // Call through to the viewed object and return true if it can be // removed. Returns true if it's removed. //virtual BOOL removeRecursively(BOOL single_item); BOOL remove(); // Build an appropriate context menu for the item. Flags unused. - void buildContextMenu(LLMenuGL& menu, U32 flags); + void buildContextMenu(class LLMenuGL& menu, U32 flags); // This method returns the actual name of the thing being // viewed. This method will ask the viewed object itself. @@ -273,8 +223,6 @@ public: // contents possible before the entire view has been constructed. const std::string& getLabel() const { return mLabel; } - // Used for sorting, like getLabel() above. - virtual time_t getCreationDate() const { return mCreationDate; } LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } @@ -282,22 +230,15 @@ public: LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); - const LLFolderViewEventListener* getListener( void ) const { return mListener; } - LLFolderViewEventListener* getListener( void ) { return mListener; } + const LLFolderViewModelItemInventory* getListener( void ) const { return mListener; } + LLFolderViewModelItemInventory* getListener( void ) { return mListener; } - // Gets the inventory item if it exists (null otherwise) - LLViewerInventoryItem * getInventoryItem(void); - // just rename the object. void rename(const std::string& new_name); - // open - virtual void openItem( void ); - virtual void preview(void); // Show children (unfortunate that this is called "open") virtual void setOpen(BOOL open = TRUE) {}; - virtual BOOL isOpen() const { return FALSE; } virtual LLFolderView* getRoot(); @@ -314,11 +255,8 @@ public: void setIcon(LLUIImagePtr icon); // refresh information from the object being viewed. - void refreshFromListener(); virtual void refresh(); - virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); - // LLView functionality virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); @@ -338,14 +276,40 @@ public: EAcceptance* accept, std::string& tooltip_msg); + // Gets the inventory item if it exists (null otherwise) + LLViewerInventoryItem * getInventoryItem(void); + // open + virtual void preview(void); + private: static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts }; +class LLInventorySort +{ +public: + LLInventorySort(U32 order) + : mSortOrder(0), + mByDate(false), + mSystemToTop(false), + mFoldersByName(false) + { + mSortOrder = order; + mByDate = (order & LLInventoryFilter::SO_DATE); + mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); + mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); + } -// function used for sorting. -typedef bool (*sort_order_f)(LLFolderViewItem* a, LLFolderViewItem* b); + bool isByDate() { return mByDate; } + U32 getSortOrder() { return mSortOrder; } + bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b); +private: + U32 mSortOrder; + bool mByDate; + bool mSystemToTop; + bool mFoldersByName; +}; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderViewFolder @@ -362,10 +326,6 @@ protected: friend class LLUICtrlFactory; public: - typedef enum e_trash - { - UNKNOWN, TRASH, NOT_TRASH - } ETrash; typedef std::list<LLFolderViewItem*> items_t; typedef std::list<LLFolderViewFolder*> folders_t; @@ -373,15 +333,12 @@ public: protected: items_t mItems; folders_t mFolders; - LLInventorySort mSortFunction; BOOL mIsOpen; BOOL mExpanderHighlighted; F32 mCurHeight; F32 mTargetHeight; F32 mAutoOpenCountdown; - time_t mSubtreeCreationDate; - mutable ETrash mAmTrash; S32 mLastArrangeGeneration; S32 mLastCalculatedWidth; S32 mCompletedFilterGeneration; @@ -407,17 +364,13 @@ public: LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); // addToFolder() returns TRUE if it succeeds. FALSE otherwise - virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); + virtual BOOL addToFolder(LLFolderViewFolder* folder); // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); BOOL needsArrange(); - void requestSort(); - - // Returns the sort group (system, trash, folder) for this folder. - virtual EInventorySortGroup getSortGroup() const; virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up); virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; } @@ -478,15 +431,11 @@ public: // extractItem() removes the specified item from the folder, but // doesn't delete it. - void extractItem( LLFolderViewItem* item ); + virtual void extractItem( LLFolderViewItem* item ); // This function is called by a child that needs to be resorted. void resort(LLFolderViewItem* item); - void setItemSortOrder(U32 ordering); - void sortBy(U32); - //BOOL (*func)(LLFolderViewItem* a, LLFolderViewItem* b)); - void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; } // folders can be opened. This will usually be called by internal @@ -500,6 +449,8 @@ public: // don't rearrange child folder contents unless explicitly requested virtual void requestArrange(BOOL include_descendants = FALSE); + virtual void requestSort(); + // internal method which doesn't update the entire view. This // method was written because the list iterators destroy the state // of other iterations, thus, we can't arrange while iterating @@ -518,7 +469,6 @@ public: std::string& tooltip_msg); void applyFunctorRecursively(LLFolderViewFunctor& functor); - virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); // Just apply this functor to the folder's immediate children. void applyFunctorToChildren(LLFolderViewFunctor& functor); @@ -544,32 +494,18 @@ public: std::string& tooltip_msg); virtual void draw(); - time_t getCreationDate() const; - bool isTrash() const; - folders_t::const_iterator getFoldersBegin() const { return mFolders.begin(); } - folders_t::const_iterator getFoldersEnd() const { return mFolders.end(); } + folders_t::iterator getFoldersBegin() const { return mFolders.begin(); } + folders_t::iterator getFoldersEnd() const { return mFolders.end(); } folders_t::size_type getFoldersCount() const { return mFolders.size(); } - items_t::const_iterator getItemsBegin() const { return mItems.begin(); } - items_t::const_iterator getItemsEnd() const { return mItems.end(); } + items_t::iterator getItemsBegin() const { return mItems.begin(); } + items_t::iterator getItemsEnd() const { return mItems.end(); } items_t::size_type getItemsCount() const { return mItems.size(); } + LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items); }; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewListenerFunctor -// -// This simple abstract base class can be used to applied to all -// listeners in a hierarchy. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderViewListenerFunctor -{ -public: - virtual ~LLFolderViewListenerFunctor() {} - virtual void operator()(LLFolderViewEventListener* listener) = 0; -}; #endif // LLFOLDERVIEWITEM_H diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index 11401d6c68..a64ddd185d 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -47,13 +47,13 @@ static const std::string INVENTORY_STRING_FRIENDS_ALL_SUBFOLDER = "All"; // helper functions // NOTE: For now Friends & All folders are created as protected folders of the LLFolderType::FT_CALLINGCARD type. -// So, their names will be processed in the LLFolderViewItem::refreshFromListener() to be localized +// So, their names will be processed in the LLFolderViewItem::refresh() to be localized // using "InvFolder LABEL_NAME" as LLTrans::findString argument. // We must use in this file their hard-coded names to ensure found them on different locales. EXT-5829. // These hard-coded names will be stored in InventoryItems but shown localized in FolderViewItems -// If hack in the LLFolderViewItem::refreshFromListener() to localize protected folder is removed +// If hack in the LLFolderViewItem::refresh() to localize protected folder is removed // or these folders are not protected these names should be localized in another place/way. inline const std::string get_friend_folder_name() { diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 2de2b17373..47444d3762 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -115,10 +115,10 @@ void teleport_via_landmark(const LLUUID& asset_id); static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); static bool check_category(LLInventoryModel* model, const LLUUID& cat_id, - LLFolderView* active_folder_view, + LLInventoryPanel* active_panel, LLInventoryFilter* filter); static bool check_item(const LLUUID& item_id, - LLFolderView* active_folder_view, + LLInventoryPanel* active_panel, LLInventoryFilter* filter); // Helper functions @@ -191,9 +191,24 @@ LLFolderType::EType LLInvFVBridge::getPreferredType() const // Folders don't have creation dates. time_t LLInvFVBridge::getCreationDate() const { - return 0; + LLInventoryObject* objectp = getInventoryObject(); + if (objectp) + { + return objectp->getCreationDate(); + } + return (time_t)0; +} + +void LLInvFVBridge::setCreationDate(time_t creation_date_utc) +{ + LLInventoryObject* objectp = getInventoryObject(); + if (objectp) + { + objectp->setCreationDate(creation_date_utc); + } } + // Can be destroyed (or moved to trash) BOOL LLInvFVBridge::isItemRemovable() const { @@ -233,7 +248,7 @@ void LLInvFVBridge::showProperties() */ } -void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) +void LLInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch) { // Deactivate gestures when moving them into Trash LLInvFVBridge* bridge; @@ -242,11 +257,11 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc LLViewerInventoryCategory* cat = NULL; LLInventoryModel::cat_array_t descendent_categories; LLInventoryModel::item_array_t descendent_items; - S32 count = batch.count(); + S32 count = batch.size(); S32 i,j; for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.get(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); if (item) @@ -259,7 +274,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc } for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.get(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); if (cat) @@ -277,7 +292,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc removeBatchNoCheck(batch); } -void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch) +void LLInvFVBridge::removeBatchNoCheck(std::vector<LLFolderViewModelItem*>& batch) { // this method moves a bunch of items and folders to the trash. As // per design guidelines for the inventory model, the message is @@ -293,14 +308,14 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener* uuid_vec_t move_ids; LLInventoryModel::update_map_t update; bool start_new_message = true; - S32 count = batch.count(); + S32 count = batch.size(); S32 i; // first, hide any 'preview' floaters that correspond to the items // being deleted. for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.get(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); if(item) @@ -313,7 +328,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener* for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.get(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); if(item) @@ -809,6 +824,12 @@ LLInventoryModel* LLInvFVBridge::getInventoryModel() const return panel ? panel->getModel() : NULL; } +LLInventoryFilter* getInventoryFilter() const +{ + LLInventoryPanel* panel = mInventoryPanel.get(); + return panel ? panel->getFilter() : NULL; +} + BOOL LLInvFVBridge::isItemInTrash() const { LLInventoryModel* model = getInventoryModel(); @@ -1183,7 +1204,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const if (can_list) { - LLFolderViewFolder * object_folderp = mRoot->getFolderByID(object_id); + LLFolderViewFolder * object_folderp = mInventoryPanel->getFolderByID(object_id); if (object_folderp) { can_list = !object_folderp->isLoading(); @@ -1194,7 +1215,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const { // Get outbox id const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); - LLFolderViewItem * outbox_itemp = mRoot->getItemByID(outbox_id); + LLFolderViewItem * outbox_itemp = mInventoryPanel->getItemByID(outbox_id); if (outbox_itemp) { @@ -1216,6 +1237,21 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const #endif } +LLToolDragAndDrop::ESource LLInvFVBridge::getDragSource() const +{ + if (gInventory.isObjectDescendentOf(getUUID(), gInventory.getRootFolderID())) + { + return LLToolDragAndDrop::SOURCE_AGENT; + } + else if (gInventory.isObjectDescendentOf(getUUID(), gInventory.getLibraryRootFolderID())) + { + return LLToolDragAndDrop::SOURCE_LIBRARY; + } + + return SOURCE_VIEWER; +} + + // +=================================================+ // | InventoryFVBridgeBuilder | @@ -1296,7 +1332,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) LLInventoryItem* itemp = model->getItem(mUUID); if (!itemp) return; - LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); + LLFolderViewItem* folder_view_itemp = mInventoryPanel.get()->getItemByID(itemp->getParentUUID()); if (!folder_view_itemp) return; folder_view_itemp->getListener()->pasteFromClipboard(); @@ -1308,7 +1344,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) LLInventoryItem* itemp = model->getItem(mUUID); if (!itemp) return; - LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); + LLFolderViewItem* folder_view_itemp = mInventoryPanel.get()->getItemByID(itemp->getParentUUID()); if (!folder_view_itemp) return; folder_view_itemp->getListener()->pasteLinkFromClipboard(); @@ -1718,6 +1754,60 @@ BOOL LLFolderBridge::isItemMovable() const void LLFolderBridge::selectItem() { } +std::string& LLFolderBridge::getDisplayName() const +{ + return mDisplayName; +} + + +void LLFolderBridge::update() +{ + bool possibly_has_children = false; + bool up_to_date = isUpToDate(); + if(!up_to_date && hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter) + { + possibly_has_children = true; + } + + BOOL loading = (possibly_has_children + && !up_to_date ); + + if (loading != mIsLoading) + { + if ( loading && !mIsLoading ) + { + // Measure how long we've been in the loading state + mTimeSinceRequestStart.reset(); + } + + const BOOL in_inventory = gInventory.isObjectDescendentOf(getUUID(), gInventory.getRootFolderID()); + const BOOL in_library = gInventory.isObjectDescendentOf(getUUID(), gInventory.getLibraryRootFolderID()); + + bool root_is_loading = false; + if (in_inventory) + { + root_is_loading = LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress(); + } + if (in_library) + { + root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress(); + } + if ((mIsLoading + && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) + || (LLInventoryModelBackgroundFetch::instance().folderFetchActive() + && root_is_loading)) + { + mDisplayName = LLInvFVBridge::getDisplayName() + " ( " + LLTrans::getString("LoadingData") + " ) "; + mIsLoading = true; + } + else + { + mDisplayName = LLInvFVBridge::getDisplayName(); + mIsLoading = false; + } + } +} + // Iterate through a folder's children to determine if @@ -1746,7 +1836,7 @@ BOOL LLFolderBridge::isItemRemovable() const } LLInventoryPanel* panel = mInventoryPanel.get(); - LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); + LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getItemByID(mUUID) : NULL); if (folderp) { LLIsItemRemovable folder_test; @@ -1969,7 +2059,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, LLInventoryPanel* destination_panel = mInventoryPanel.get(); if (!destination_panel) return false; - LLInventoryFilter* filter = destination_panel->getFilter(); + LLInventoryFilter* filter = getInventoryFilter(); if (!filter) return false; const LLUUID &cat_id = inv_cat->getUUID(); @@ -2188,7 +2278,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, { // Check whether the folder being dragged from active inventory panel // passes the filter of the destination panel. - is_movable = check_category(model, cat_id, active_folder_view, filter); + is_movable = check_category(model, cat_id, active_panel, filter); } } } @@ -2621,7 +2711,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) { if ("open" == action) { - LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(mRoot->getItemByID(mUUID)); + LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(mInventoryPanel.get()->getItemByID(mUUID)); if (f) { f->setOpen(TRUE); @@ -2890,7 +2980,7 @@ void LLFolderBridge::pasteFromClipboard() if (move_is_into_outbox) { - LLFolderViewItem * outbox_itemp = mRoot->getItemByID(mUUID); + LLFolderViewItem * outbox_itemp = mInventoryPanel.get()->getItemByID(mUUID); if (outbox_itemp) { @@ -3055,7 +3145,7 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv return ((item_array.count() > 0) ? TRUE : FALSE ); } -void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) +void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items) { LLInventoryModel* model = getInventoryModel(); llassert(model != NULL); @@ -3066,30 +3156,30 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) if (lost_and_found_id == mUUID) { // This is the lost+found folder. - mItems.push_back(std::string("Empty Lost And Found")); + items.push_back(std::string("Empty Lost And Found")); - mDisabledItems.push_back(std::string("New Folder")); - mDisabledItems.push_back(std::string("New Script")); - mDisabledItems.push_back(std::string("New Note")); - mDisabledItems.push_back(std::string("New Gesture")); - mDisabledItems.push_back(std::string("New Clothes")); - mDisabledItems.push_back(std::string("New Body Parts")); - } + disabled_items.push_back(std::string("New Folder")); + disabled_items.push_back(std::string("New Script")); + disabled_items.push_back(std::string("New Note")); + disabled_items.push_back(std::string("New Gesture")); + disabled_items.push_back(std::string("New Clothes")); + disabled_items.push_back(std::string("New Body Parts")); + } if(trash_id == mUUID) { // This is the trash. - mItems.push_back(std::string("Empty Trash")); + items.push_back(std::string("Empty Trash")); } else if(isItemInTrash()) { // This is a folder in the trash. - mItems.clear(); // clear any items that used to exist - addTrashContextMenuOptions(mItems, mDisabledItems); + items.clear(); // clear any items that used to exist + addTrashContextMenuOptions(items, disabled_items); } else if(isOutboxFolder()) { - addOutboxContextMenuOptions(flags, mItems, mDisabledItems); + addOutboxContextMenuOptions(flags, items, disabled_items); } else if(isAgentInventory()) // do not allow creating in library { @@ -3103,40 +3193,40 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) { - mItems.push_back(std::string("New Folder")); + items.push_back(std::string("New Folder")); } - mItems.push_back(std::string("New Script")); - mItems.push_back(std::string("New Note")); - mItems.push_back(std::string("New Gesture")); - mItems.push_back(std::string("New Clothes")); - mItems.push_back(std::string("New Body Parts")); + items.push_back(std::string("New Script")); + items.push_back(std::string("New Note")); + items.push_back(std::string("New Gesture")); + items.push_back(std::string("New Clothes")); + items.push_back(std::string("New Body Parts")); } #if SUPPORT_ENSEMBLES // Changing folder types is an unfinished unsupported feature // and can lead to unexpected behavior if enabled. - mItems.push_back(std::string("Change Type")); + items.push_back(std::string("Change Type")); const LLViewerInventoryCategory *cat = getCategory(); if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) { - mDisabledItems.push_back(std::string("Change Type")); + disabled_items.push_back(std::string("Change Type")); } #endif - getClipboardEntries(false, mItems, mDisabledItems, flags); + getClipboardEntries(false, items, disabled_items, flags); } else { // Want some but not all of the items from getClipboardEntries for outfits. if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT)) { - mItems.push_back(std::string("Rename")); + items.push_back(std::string("Rename")); - addDeleteContextMenuOptions(mItems, mDisabledItems); + addDeleteContextMenuOptions(items, disabled_items); // EXT-4030: disallow deletion of currently worn outfit const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory())) { - mDisabledItems.push_back(std::string("Delete")); + disabled_items.push_back(std::string("Delete")); } } } @@ -3165,20 +3255,41 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) // Preemptively disable system folder removal if more than one item selected. if ((flags & FIRST_SELECTED_ITEM) == 0) { - mDisabledItems.push_back(std::string("Delete System Folder")); + disabled_items.push_back(std::string("Delete System Folder")); } if (!isOutboxFolder()) { - mItems.push_back(std::string("Share")); + items.push_back(std::string("Share")); if (!canShare()) { - mDisabledItems.push_back(std::string("Share")); + disabled_items.push_back(std::string("Share")); + } + } + // Add menu items that are dependent on the contents of the folder. + LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID); + if (category) + { + uuid_vec_t folders; + folders.push_back(category->getUUID()); + + sSelf = getHandle(); + LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE); + fetch->startFetch(); + inc_busy_count(); + if (fetch->isFinished()) + { + buildContextMenuFolderOptions(flags, items, disabled_items); + } + else + { + // it's all on its way - add an observer, and the inventory will call done for us when everything is here. + gInventory.addObserver(fetch); } } } -void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) +void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items) { // Build folder specific options back up LLInventoryModel* model = getInventoryModel(); @@ -3205,21 +3316,21 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) { - mItems.push_back(std::string("Calling Card Separator")); - mItems.push_back(std::string("Conference Chat Folder")); - mItems.push_back(std::string("IM All Contacts In Folder")); + items.push_back(std::string("Calling Card Separator")); + items.push_back(std::string("Conference Chat Folder")); + items.push_back(std::string("IM All Contacts In Folder")); } } if (!isItemRemovable()) { - mDisabledItems.push_back(std::string("Delete")); + disabled_items.push_back(std::string("Delete")); } #ifndef LL_RELEASE_FOR_DOWNLOAD if (LLFolderType::lookupIsProtectedType(type)) { - mItems.push_back(std::string("Delete System Folder")); + items.push_back(std::string("Delete System Folder")); } #endif @@ -3234,7 +3345,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) checkFolderForContentsOfType(model, is_object) || checkFolderForContentsOfType(model, is_gesture) ) { - mItems.push_back(std::string("Folder Wearables Separator")); + items.push_back(std::string("Folder Wearables Separator")); // Only enable add/replace outfit for non-system folders. if (!is_system_folder) @@ -3242,25 +3353,25 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) // Adding an outfit onto another (versus replacing) doesn't make sense. if (type != LLFolderType::FT_OUTFIT) { - mItems.push_back(std::string("Add To Outfit")); + items.push_back(std::string("Add To Outfit")); } - mItems.push_back(std::string("Replace Outfit")); + items.push_back(std::string("Replace Outfit")); } if (is_ensemble) { - mItems.push_back(std::string("Wear As Ensemble")); + items.push_back(std::string("Wear As Ensemble")); } - mItems.push_back(std::string("Remove From Outfit")); + items.push_back(std::string("Remove From Outfit")); if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID)) { - mDisabledItems.push_back(std::string("Remove From Outfit")); + disabled_items.push_back(std::string("Remove From Outfit")); } if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID)) { - mDisabledItems.push_back(std::string("Replace Outfit")); + disabled_items.push_back(std::string("Replace Outfit")); } - mItems.push_back(std::string("Outfit Separator")); + items.push_back(std::string("Outfit Separator")); } } @@ -3269,39 +3380,16 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { sSelf.markDead(); - mItems.clear(); - mDisabledItems.clear(); + menuentry_vec_t items; + menuentry_vec_t disabled_items; lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; LLInventoryModel* model = getInventoryModel(); if(!model) return; - buildContextMenuBaseOptions(flags); - - // Add menu items that are dependent on the contents of the folder. - LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID); - if (category) - { - uuid_vec_t folders; - folders.push_back(category->getUUID()); - - sSelf = getHandle(); - LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE); - fetch->startFetch(); - inc_busy_count(); - if (fetch->isFinished()) - { - buildContextMenuFolderOptions(flags); - } - else - { - // it's all on its way - add an observer, and the inventory will call done for us when everything is here. - gInventory.addObserver(fetch); - } - } - - hide_context_entries(menu, mItems, mDisabledItems); + buildContextMenuBaseOptions(flags, items, disabled_items); + hide_context_entries(menu, items, disabled_items); // Reposition the menu, in case we're adding items to an existing menu. menu.needsArrange(); @@ -3402,9 +3490,7 @@ void LLFolderBridge::createNewCategory(void* user_data) { LLFolderBridge* bridge = (LLFolderBridge*)user_data; if(!bridge) return; - LLInventoryPanel* panel = bridge->mInventoryPanel.get(); - if (!panel) return; - LLInventoryModel* model = panel->getModel(); + LLInventoryModel* model = bridge->getInventoryModel(); if(!model) return; LLUUID id; id = model->createNewCategory(bridge->getUUID(), @@ -3482,6 +3568,24 @@ void LLFolderBridge::createNewEyes(void* user_data) LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_EYES); } +EInventorySortGroup LLFolderBridge::getSortGroup() const +{ + LLFolderType::EType preferred_type = getPreferredType(); + + if (preferred_type == LLFolderType::FT_TRASH) + { + return SG_TRASH_FOLDER; + } + + if(LLFolderType::lookupIsProtectedType(preferred_type)) + { + return SG_SYSTEM_FOLDER; + } + + return SG_NORMAL_FOLDER; +} + + // static void LLFolderBridge::createWearable(LLFolderBridge* bridge, LLWearableType::EType type) { @@ -3635,7 +3739,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLInventoryPanel* destination_panel = mInventoryPanel.get(); if (!destination_panel) return false; - LLInventoryFilter* filter = destination_panel->getFilter(); + LLInventoryFilter* filter = getInventoryFilter(); if (!filter) return false; const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); @@ -3752,10 +3856,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // passes the filter of the destination panel. if (accept && active_panel) { - LLFolderView* active_folder_view = active_panel->getRootFolder(); - if (!active_folder_view) return false; - - LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); + LLFolderViewItem* fv_item = active_panel->getItemByID(inv_item->getUUID()); if (!fv_item) return false; accept = filter->check(fv_item); @@ -3770,10 +3871,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } // If an item is being dragged between windows, unselect everything in the active window // so that we don't follow the selection to its new location (which is very annoying). + // RN: a better solution would be to deselect automatically when an item is moved + // and then select any item that is dropped only in the panel that it is dropped in if (active_panel && (destination_panel != active_panel)) - { - active_panel->unSelectAll(); - } + { + active_panel->unSelectAll(); + } //-------------------------------------------------------------------------------- // Destination folder logic @@ -3975,10 +4078,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // passes the filter of the destination panel. if (accept && active_panel) { - LLFolderView* active_folder_view = active_panel->getRootFolder(); - if (!active_folder_view) return false; - - LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); + LLFolderViewItem* fv_item = active_panel->getItemByID(inv_item->getUUID()); if (!fv_item) return false; accept = filter->check(fv_item); @@ -4021,10 +4121,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // static bool check_category(LLInventoryModel* model, const LLUUID& cat_id, - LLFolderView* active_folder_view, + LLInventoryPanel* active_panel, LLInventoryFilter* filter) { - if (!model || !active_folder_view || !filter) + if (!model || !active_panel || !filter) return false; if (!filter->checkFolder(cat_id)) @@ -4044,13 +4144,13 @@ bool check_category(LLInventoryModel* model, // Empty folder should be checked as any other folder view item. // If we are filtering by date the folder should not pass because // it doesn't have its own creation date. See LLInvFVBridge::getCreationDate(). - return check_item(cat_id, active_folder_view, filter); + return check_item(cat_id, active_panel, filter); } for (S32 i = 0; i < num_descendent_categories; ++i) { LLInventoryCategory* category = descendent_categories[i]; - if(!check_category(model, category->getUUID(), active_folder_view, filter)) + if(!check_category(model, category->getUUID(), active_panel, filter)) { return false; } @@ -4059,7 +4159,7 @@ bool check_category(LLInventoryModel* model, for (S32 i = 0; i < num_descendent_items; ++i) { LLViewerInventoryItem* item = descendent_items[i]; - if(!check_item(item->getUUID(), active_folder_view, filter)) + if(!check_item(item->getUUID(), active_panel, filter)) { return false; } @@ -4070,12 +4170,12 @@ bool check_category(LLInventoryModel* model, // static bool check_item(const LLUUID& item_id, - LLFolderView* active_folder_view, + LLInventoryPanel* active_panel, LLInventoryFilter* filter) { - if (!active_folder_view || !filter) return false; + if (!active_panel || !filter) return false; - LLFolderViewItem* fv_item = active_folder_view->getItemByID(item_id); + LLFolderViewItem* fv_item = active_panel->getItemByID(item_id); if (!fv_item) return false; return filter->check(fv_item); @@ -4404,7 +4504,7 @@ LLCallingCardBridge::~LLCallingCardBridge() void LLCallingCardBridge::refreshFolderViewItem() { LLInventoryPanel* panel = mInventoryPanel.get(); - LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; + LLFolderViewItem* itemp = panel ? panel->getItemByID(mUUID) : NULL; if (itemp) { itemp->refresh(); @@ -5897,7 +5997,8 @@ void LLLinkFolderBridge::gotoItem() const LLUUID &cat_uuid = getFolderID(); if (!cat_uuid.isNull()) { - if (LLFolderViewItem *base_folder = mRoot->getItemByID(cat_uuid)) + LLFolderViewItem *base_folder = mInventoryPanel.get()->getItemByID(cat_uuid) + if (base_folder) { if (LLInventoryModel* model = getInventoryModel()) { @@ -6235,9 +6336,8 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_ /************************************************************************/ void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { - LLFolderBridge::buildContextMenu(menu, flags); - - menuentry_vec_t disabled_items, items = getMenuItems(); + menuentry_vec_t disabled_items, items; + buildContextMenuOptions(flags, items, disabled_items); items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); @@ -6286,5 +6386,4 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( } - // EOF diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 3b4f845f54..e9c54dc4bc 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -32,6 +32,7 @@ #include "llfoldervieweventlistener.h" #include "llinventorymodel.h" #include "llinventoryobserver.h" +#include "llinventorypanel.h" #include "llviewercontrol.h" #include "llwearable.h" @@ -41,7 +42,7 @@ class LLInventoryModel; class LLMenuGL; class LLCallingCardObserver; class LLViewerJointAttachment; - +class LLFolderView; typedef std::vector<std::string> menuentry_vec_t; @@ -56,7 +57,7 @@ typedef std::vector<std::string> menuentry_vec_t; // functionality a bit. (except for folders, you can create those // manually...) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInvFVBridge : public LLFolderViewEventListener +class LLInvFVBridge : public LLFolderViewModelItemInventory { public: // This method is a convenience function which creates the correct @@ -83,13 +84,14 @@ public: virtual void restoreToWorld() {} //-------------------------------------------------------------------- - // Inherited LLFolderViewEventListener functions + // Inherited LLFolderViewModelItemInventory functions //-------------------------------------------------------------------- virtual const std::string& getName() const; virtual const std::string& getDisplayName() const; virtual PermissionMask getPermissionMask() const; virtual LLFolderType::EType getPreferredType() const; virtual time_t getCreationDate() const; + virtual void setCreationDate(time_t creation_date_utc); virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } virtual std::string getLabelSuffix() const { return LLStringUtil::null; } virtual void openItem() {} @@ -103,8 +105,8 @@ public: virtual BOOL isItemInTrash() const; virtual BOOL isLink() const; //virtual BOOL removeItem() = 0; - virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch); - virtual void move(LLFolderViewEventListener* new_parent_bridge) {} + virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); + virtual void move(LLFolderViewModelItem* new_parent_bridge) {} virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL copyToClipboard() const { return FALSE; } virtual void cutToClipboard(); @@ -115,6 +117,7 @@ public: void getClipboardEntries(bool show_asset_id, menuentry_vec_t &items, menuentry_vec_t &disabled_items, U32 flags); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); + virtual LLToolDragAndDrop::ESource getDragSource() const; virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, @@ -122,6 +125,7 @@ public: std::string& tooltip_msg) { return FALSE; } virtual LLInventoryType::EType getInventoryType() const { return mInvType; } virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } + EInventorySortGroup getSortGroup() const { return SG_ITEM; } //-------------------------------------------------------------------- // Convenience functions for adding various common menu options. @@ -140,14 +144,15 @@ protected: LLInventoryObject* getInventoryObject() const; LLInventoryModel* getInventoryModel() const; - + LLInventoryFilter* getInventoryFilter() const; + BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash? BOOL isLinkedObjectMissing() const; // Is this a linked obj whose baseobj is not in inventory? - BOOL isAgentInventory() const; // false if lost or in the inventory library - BOOL isCOFFolder() const; // true if COF or descendent of - BOOL isInboxFolder() const; // true if COF or descendent of marketplace inbox - BOOL isOutboxFolder() const; // true if COF or descendent of marketplace outbox + BOOL isAgentInventory() const; // false if lost or in the inventory library + BOOL isCOFFolder() const; // true if COF or descendant of + BOOL isInboxFolder() const; // true if COF or descendant of marketplace inbox + BOOL isOutboxFolder() const; // true if COF or descendant of marketplace outbox BOOL isOutboxFolderDirectParent() const; const LLUUID getOutboxFolder() const; @@ -160,13 +165,14 @@ protected: LLViewerInventoryCategory* item, const LLUUID& new_parent, BOOL restamp); - void removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch); + void removeBatchNoCheck(std::vector<LLFolderViewModelItem*>& batch); protected: - LLHandle<LLInventoryPanel> mInventoryPanel; - LLFolderView* mRoot; - const LLUUID mUUID; // item id - LLInventoryType::EType mInvType; - BOOL mIsLink; + LLHandle<LLInventoryPanel> mInventoryPanel; + LLFolderView* mRoot; + const LLUUID mUUID; // item id + LLInventoryType::EType mInvType; + bool mIsLink; + LLTimer mTimeSinceRequestStart; void purgeItem(LLInventoryModel *model, const LLUUID &uuid); }; @@ -233,15 +239,18 @@ class LLFolderBridge : public LLInvFVBridge public: LLFolderBridge(LLInventoryPanel* inventory, LLFolderView* root, - const LLUUID& uuid) : - LLInvFVBridge(inventory, root, uuid), + const LLUUID& uuid) + : LLInvFVBridge(inventory, root, uuid), mCallingCards(FALSE), - mWearables(FALSE) + mWearables(FALSE), + mIsLoading(false) {} BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg); BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg); + const std::string& getDisplayName() const; + virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem(); virtual void closeItem(); @@ -277,14 +286,17 @@ public: virtual BOOL isClipboardPasteableAsLink() const; virtual BOOL copyToClipboard() const; + EInventorySortGroup getSortGroup() const; + virtual void update(); + static void createWearable(LLFolderBridge* bridge, LLWearableType::EType type); LLViewerInventoryCategory* getCategory() const; LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; } protected: - void buildContextMenuBaseOptions(U32 flags); - void buildContextMenuFolderOptions(U32 flags); + void buildContextMenuOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items); + void buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items); //-------------------------------------------------------------------- // Menu callbacks @@ -310,8 +322,6 @@ protected: void modifyOutfit(BOOL append); void determineFolderType(); - menuentry_vec_t getMenuItems() { return mItems; } // returns a copy of current menu items - void dropToFavorites(LLInventoryItem* inv_item); void dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); @@ -323,11 +333,12 @@ public: static void staticFolderOptionsMenu(); private: - BOOL mCallingCards; - BOOL mWearables; - menuentry_vec_t mItems; - menuentry_vec_t mDisabledItems; - LLRootHandle<LLFolderBridge> mHandle; + bool mCallingCards; + bool mWearables; + bool mIsLoading; + LLTimer mTimeSinceRequestStart; + std::string mDisplayName; + LLRootHandle<LLFolderBridge> mHandle; }; class LLTextureBridge : public LLItemBridge diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 5496c273f2..9c84be5eac 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -41,39 +41,39 @@ // linden library includes #include "lltrans.h" -LLInventoryFilter::FilterOps::FilterOps() : - mFilterObjectTypes(0xffffffffffffffffULL), - mFilterCategoryTypes(0xffffffffffffffffULL), - mFilterWearableTypes(0xffffffffffffffffULL), - mMinDate(time_min()), - mMaxDate(time_max()), - mHoursAgo(0), - mShowFolderState(SHOW_NON_EMPTY_FOLDERS), - mPermissions(PERM_NONE), - mFilterTypes(FILTERTYPE_OBJECT), - mFilterUUID(LLUUID::null), - mFilterLinks(FILTERLINK_INCLUDE_LINKS) +LLInventoryFilter::FilterOps::FilterOps(const Params& p) +: mFilterObjectTypes(p.object_types), + mFilterCategoryTypes(p.category_types), + mFilterWearableTypes(p.wearable_types), + mMinDate(p.date_range.min_date), + mMaxDate(p.date_range.max_date), + mHoursAgo(p.hours_ago), + mShowFolderState(p.show_folder_state), + mPermissions(p.permissions), + mFilterTypes(p.types), + mFilterUUID(p.uuid), + mFilterLinks(p.links) { } ///---------------------------------------------------------------------------- /// Class LLInventoryFilter ///---------------------------------------------------------------------------- -LLInventoryFilter::LLInventoryFilter(const std::string& name) +LLInventoryFilter::LLInventoryFilter(const std::string& name, const Params& p) : mName(name), mModified(FALSE), mNeedTextRebuild(TRUE), - mEmptyLookupMessage("InventoryNoMatchingItems") + mEmptyLookupMessage("InventoryNoMatchingItems"), + mFilterOps(p.filter_ops) { - mOrder = SO_FOLDERS_BY_NAME; // This gets overridden by a pref immediately + mOrder = p.sort_order; // This gets overridden by a pref immediately - mSubStringMatchOffset = 0; - mFilterSubString.clear(); - mFilterGeneration = 0; - mMustPassGeneration = S32_MAX; - mMinRequiredGeneration = 0; + mFilterSubString(p.substring); + mLastSuccessGeneration = 0; + mLastFailGeneration = S32_MAX; + getFirstSuccessGeneration = 0; mFilterCount = 0; - mNextFilterGeneration = mFilterGeneration + 1; + mNextFilterGeneration = mLastSuccessGeneration + 1; mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff"); mFilterBehavior = FILTER_NONE; @@ -95,7 +95,7 @@ BOOL LLInventoryFilter::check(const LLFolderViewItem* item) return TRUE; } - mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; + std::string::size_type string_offset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; const BOOL passed_filtertype = checkAgainstFilterType(item); const BOOL passed_permissions = checkAgainstPermissions(item); @@ -103,20 +103,20 @@ BOOL LLInventoryFilter::check(const LLFolderViewItem* item) const BOOL passed = (passed_filtertype && passed_permissions && passed_filterlink && - (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); + (mFilterSubString.size() == 0 || string_offset != std::string::npos)); return passed; } bool LLInventoryFilter::check(const LLInventoryItem* item) { - mSubStringMatchOffset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; + std::string::size_type string_offset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; const bool passed_filtertype = checkAgainstFilterType(item); const bool passed_permissions = checkAgainstPermissions(item); const bool passed = (passed_filtertype && passed_permissions && - (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); + (mFilterSubString.size() == 0 || string_offset != std::string::npos)); return passed; } @@ -130,7 +130,7 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const return false; } - const LLFolderViewEventListener* listener = folder->getListener(); + const LLFolderViewModelItemInventory* listener = folder->getListener(); if (!listener) { llwarns << "Folder view event listener not found." << llendl; @@ -168,7 +168,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const { - const LLFolderViewEventListener* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = item->getListener(); if (!listener) return FALSE; LLInventoryType::EType object_type = listener->getInventoryType(); @@ -311,7 +311,7 @@ bool LLInventoryFilter::checkAgainstFilterType(const LLInventoryItem* item) cons BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const { - const LLFolderViewEventListener* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = item->getListener(); if (!listener) return FALSE; PermissionMask perm = listener->getPermissionMask(); @@ -339,7 +339,7 @@ bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) con BOOL LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const { - const LLFolderViewEventListener* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = item->getListener(); if (!listener) return TRUE; const LLUUID object_id = listener->getUUID(); @@ -359,9 +359,9 @@ const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const return mFilterSubString; } -std::string::size_type LLInventoryFilter::getStringMatchOffset() const +std::string::size_type LLInventoryFilter::getStringMatchOffset(LLFolderViewItem* item) const { - return mSubStringMatchOffset; + return mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; } // has user modified default filter params? @@ -685,7 +685,7 @@ void LLInventoryFilter::setModified(EFilterBehavior behavior) { mModified = TRUE; mNeedTextRebuild = TRUE; - mFilterGeneration = mNextFilterGeneration++; + mLastSuccessGeneration = mNextFilterGeneration++; if (mFilterBehavior == FILTER_NONE) { @@ -704,17 +704,17 @@ void LLInventoryFilter::setModified(EFilterBehavior behavior) switch(mFilterBehavior) { case FILTER_RESTART: - mMustPassGeneration = mFilterGeneration; - mMinRequiredGeneration = mFilterGeneration; + mLastFailGeneration = mLastSuccessGeneration; + mFirstSuccessGeneration = mLastSuccessGeneration; break; case FILTER_LESS_RESTRICTIVE: - mMustPassGeneration = mFilterGeneration; + mLastFailGeneration = mLastSuccessGeneration; break; case FILTER_MORE_RESTRICTIVE: - mMinRequiredGeneration = mFilterGeneration; + mFirstSuccessGeneration = mLastSuccessGeneration; // must have passed either current filter generation (meaningless, as it hasn't been run yet) // or some older generation, so keep the value - mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration); + mLastFailGeneration = llmin(mLastFailGeneration, mLastSuccessGeneration); break; default: llerrs << "Bad filter behavior specified" << llendl; @@ -930,60 +930,34 @@ const std::string& LLInventoryFilter::getFilterText() return mFilterText; } -void LLInventoryFilter::toLLSD(LLSD& data) const +void LLInventoryFilter::toParams(Params& params) const { - data["filter_types"] = (LLSD::Integer)getFilterObjectTypes(); - data["min_date"] = (LLSD::Integer)getMinDate(); - data["max_date"] = (LLSD::Integer)getMaxDate(); - data["hours_ago"] = (LLSD::Integer)getHoursAgo(); - data["show_folder_state"] = (LLSD::Integer)getShowFolderState(); - data["permissions"] = (LLSD::Integer)getFilterPermissions(); - data["substring"] = (LLSD::String)getFilterSubString(); - data["sort_order"] = (LLSD::Integer)getSortOrder(); - data["since_logoff"] = (LLSD::Boolean)isSinceLogoff(); + params.filter_ops.types = getFilterObjectTypes(); + params.filter_ops.date_range.min_date = getMinDate(); + params.filter_ops.date_range.max_date = getMaxDate(); + params.filter_ops.hours_ago = getHoursAgo(); + params.filter_ops.show_folder_state = getShowFolderState(); + params.filter_ops.permissions = getFilterPermissions(); + params.substring = getFilterSubString(); + params.sort_order = getSortOrder(); + params.since_logoff = isSinceLogoff(); } -void LLInventoryFilter::fromLLSD(LLSD& data) +void LLInventoryFilter::fromParams(const Params& data) { - if(data.has("filter_types")) + if (!params.validateBlock()) { - setFilterObjectTypes((U32)data["filter_types"].asInteger()); + return; } - if(data.has("min_date") && data.has("max_date")) - { - setDateRange(data["min_date"].asInteger(), data["max_date"].asInteger()); - } - - if(data.has("hours_ago")) - { - setHoursAgo((U32)data["hours_ago"].asInteger()); - } - - if(data.has("show_folder_state")) - { - setShowFolderState((EFolderShow)data["show_folder_state"].asInteger()); - } - - if(data.has("permissions")) - { - setFilterPermissions((PermissionMask)data["permissions"].asInteger()); - } - - if(data.has("substring")) - { - setFilterSubString(std::string(data["substring"].asString())); - } - - if(data.has("sort_order")) - { - setSortOrder((U32)data["sort_order"].asInteger()); - } - - if(data.has("since_logoff")) - { - setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean()); - } + setFilterObjectTypes(params.filter_ops.types); + setDateRange(params.filter_ops.date_range.min_date, params.filter_ops.date_range.max_date); + setHoursAgo(params.filter_ops.hours_ago); + setShowFolderState(params.filter_ops.show_folder_state); + setFilterPermissions(params.filter_ops.permissions); + setFilterSubString(params.substring); + setSortOrder(params.sort_order); + setDateRangeLastLogoff(params.since_logoff); } U64 LLInventoryFilter::getFilterObjectTypes() const @@ -1052,15 +1026,15 @@ void LLInventoryFilter::decrementFilterCount() S32 LLInventoryFilter::getCurrentGeneration() const { - return mFilterGeneration; + return mLastSuccessGeneration; } -S32 LLInventoryFilter::getMinRequiredGeneration() const +S32 LLInventoryFilter::getFirstSuccessGeneration() const { - return mMinRequiredGeneration; + return mFirstSuccessGeneration; } -S32 LLInventoryFilter::getMustPassGeneration() const +S32 LLInventoryFilter::getFirstRequiredGeneration() const { - return mMustPassGeneration; + return mLastFailGeneration; } void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) @@ -1068,9 +1042,13 @@ void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) mEmptyLookupMessage = message; } +RN: turn this into a param const std::string& LLInventoryFilter::getEmptyLookupMessage() const { - return mEmptyLookupMessage; + LLStringUtil::format_map_t args; + args["[SEARCH_TERM]"] = LLURI::escape(getFilterSubStringOrig()); + + return LLTrans::getString(mEmptyLookupMessage, args); } @@ -1080,3 +1058,26 @@ bool LLInventoryFilter::areDateLimitsSet() || mFilterOps.mMaxDate != time_max() || mFilterOps.mHoursAgo != 0; } + +LLInventoryFilter& LLInventoryFilter::operator=( const LLInventoryFilter& other ) +{ + fromParams(other.toParams()); +} + + +bool LLInventoryFilter::FilterOps::DateRange::validateBlock( bool emit_errors /*= true*/ ) +{ + bool valid = LLInitParam::Block<DateRange>::validateBlock(emit_errors); + if (valid) + { + if (max_date() < min_date()) + { + if (emit_errors) + { + llwarns << "max_date should be greater or equal to min_date" << llendl; + } + valid = false; + } + } + return valid; +} diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 6be2acfaa3..7f33be3878 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -34,7 +34,7 @@ class LLFolderViewItem; class LLFolderViewFolder; class LLInventoryItem; -class LLInventoryFilter +class LLInventoryFilter : public LLFolderViewFilter { public: enum EFolderShow @@ -53,13 +53,13 @@ public: }; enum EFilterType { - FILTERTYPE_NONE = 0, - FILTERTYPE_OBJECT = 0x1 << 0, // normal default search-by-object-type - FILTERTYPE_CATEGORY = 0x1 << 1, // search by folder type - FILTERTYPE_UUID = 0x1 << 2, // find the object with UUID and any links to it - FILTERTYPE_DATE = 0x1 << 3, // search by date range - FILTERTYPE_WEARABLE = 0x1 << 4, // search by wearable type - FILTERTYPE_EMPTYFOLDERS = 0x1 << 5 // pass if folder is not a system folder to be hidden if empty + FILTERTYPE_NONE = 0, + FILTERTYPE_OBJECT = 0x1 << 0, // normal default search-by-object-type + FILTERTYPE_CATEGORY = 0x1 << 1, // search by folder type + FILTERTYPE_UUID = 0x1 << 2, // find the object with UUID and any links to it + FILTERTYPE_DATE = 0x1 << 3, // search by date range + FILTERTYPE_WEARABLE = 0x1 << 4, // search by wearable type + FILTERTYPE_EMPTYFOLDERS = 0x1 << 5 // pass if folder is not a system folder to be hidden if }; enum EFilterLink @@ -71,13 +71,87 @@ public: enum ESortOrderType { - SO_NAME = 0, // Sort inventory by name - SO_DATE = 0x1, // Sort inventory by date - SO_FOLDERS_BY_NAME = 0x1 << 1, // Force folder sort by name - SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2 // Force system folders to be on top + SO_NAME = 0, // Sort inventory by name + SO_DATE = 0x1, // Sort inventory by date + SO_FOLDERS_BY_NAME = 0x1 << 1, // Force folder sort by name + SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2 // Force system folders to be on top }; - LLInventoryFilter(const std::string& name); + struct FilterOps + { + struct DateRange : public LLInitParam::Block<DateRange> + { + Optional<time_t> min_date; + Optional<time_t> max_date; + + DateRange() + : min_date("min_date", time_min()), + max_date("max_date", time_max()) + {} + + bool validateBlock(bool emit_errors = true); + }; + + struct Params : public LLInitParam::Block<Params> + { + Optional<U32> types; + Optional<U64> object_types, + wearable_types, + category_types; + Optional<EFilterLink> links; + Optional<LLUUID> uuid; + Optional<DateRange> date_range; + Optional<S32> hours_ago; + Optional<EFolderShow> show_folder_state; + Optional<PermissionMask> permissions; + + Params() + : types("filter_types", FILTERTYPE_OBJECT), + object_types("object_types", 0xffffFFFFffffFFFFULL), + wearable_types("wearable_types", 0xffffFFFFffffFFFFULL), + category_types("category_types", 0xffffFFFFffffFFFFULL), + links("links", FILTERLINK_INCLUDE_LINKS), + uuid("uuid"), + date_range("date_range"), + hours_ago("hours_ago", 0), + show_folder_state("show_folder_state", SHOW_NON_EMPTY_FOLDERS), + permissions("permissions", PERM_NONE) + {} + }; + + FilterOps(const Params& = Params()); + + U32 mFilterTypes; + + U64 mFilterObjectTypes; // For _OBJECT + U64 mFilterWearableTypes; + U64 mFilterCategoryTypes; // For _CATEGORY + LLUUID mFilterUUID; // for UUID + + time_t mMinDate; + time_t mMaxDate; + U32 mHoursAgo; + EFolderShow mShowFolderState; + PermissionMask mPermissions; + U64 mFilterLinks; + }; + + struct Params : public LLInitParam::Block<Params> + { + Optional<FilterOps::Params> filter_ops; + Optional<std::string> substring; + Optional<U32> sort_order; + Optional<bool> since_logoff; + + Params() + : filter_ops(""), + substring("substring"), + sort_order("sort_order"), + since_logoff("since_logoff") + {} + }; + + LLInventoryFilter(const std::string& name, const Params& p); virtual ~LLInventoryFilter(); // +-------------------------------------------------------------------+ @@ -86,7 +160,7 @@ public: void setFilterObjectTypes(U64 types); U64 getFilterObjectTypes() const; U64 getFilterCategoryTypes() const; - BOOL isFilterObjectTypesWith(LLInventoryType::EType t) const; + bool isFilterObjectTypesWith(LLInventoryType::EType t) const; void setFilterCategoryTypes(U64 types); void setFilterUUID(const LLUUID &object_id); void setFilterWearableTypes(U64 types); @@ -96,7 +170,7 @@ public: void setFilterSubString(const std::string& string); const std::string& getFilterSubString(BOOL trim = FALSE) const; const std::string& getFilterSubStringOrig() const { return mFilterSubStringOrig; } - BOOL hasFilterString() const; + bool hasFilterString() const; void setFilterPermissions(PermissionMask perms); PermissionMask getFilterPermissions() const; @@ -115,18 +189,17 @@ public: // +-------------------------------------------------------------------+ // + Execution And Results // +-------------------------------------------------------------------+ - BOOL check(const LLFolderViewItem* item); + bool check(const LLFolderViewItem* item); bool check(const LLInventoryItem* item); bool checkFolder(const LLFolderViewFolder* folder) const; bool checkFolder(const LLUUID& folder_id) const; - BOOL checkAgainstFilterType(const LLFolderViewItem* item) const; + bool checkAgainstFilterType(const LLFolderViewItem* item) const; bool checkAgainstFilterType(const LLInventoryItem* item) const; - BOOL checkAgainstPermissions(const LLFolderViewItem* item) const; + bool checkAgainstPermissions(const LLFolderViewItem* item) const; bool checkAgainstPermissions(const LLInventoryItem* item) const; - BOOL checkAgainstFilterLinks(const LLFolderViewItem* item) const; - - std::string::size_type getStringMatchOffset() const; + bool checkAgainstFilterLinks(const LLFolderViewItem* item) const; + std::string::size_type getStringMatchOffset(LLFolderViewItem* item) const; // +-------------------------------------------------------------------+ // + Presentation // +-------------------------------------------------------------------+ @@ -142,10 +215,10 @@ public: // +-------------------------------------------------------------------+ // + Status // +-------------------------------------------------------------------+ - BOOL isActive() const; - BOOL isModified() const; - BOOL isModifiedAndClear(); - BOOL isSinceLogoff() const; + bool isActive() const; + bool isModified() const; + bool isModifiedAndClear(); + bool isSinceLogoff() const; void clearModified(); const std::string& getName() const; const std::string& getFilterText(); @@ -162,7 +235,7 @@ public: // +-------------------------------------------------------------------+ // + Default // +-------------------------------------------------------------------+ - BOOL isNotDefault() const; + bool isNotDefault() const; void markDefault(); void resetDefault(); @@ -170,14 +243,17 @@ public: // + Generation // +-------------------------------------------------------------------+ S32 getCurrentGeneration() const; - S32 getMinRequiredGeneration() const; - S32 getMustPassGeneration() const; + S32 getFirstSuccessGeneration() const; + S32 getFirstRequiredGeneration() const; + // +-------------------------------------------------------------------+ // + Conversion // +-------------------------------------------------------------------+ - void toLLSD(LLSD& data) const; - void fromLLSD(LLSD& data); + void toParams(Params& params) const; + void fromParams(const Params& p); + + LLInventoryFilter& operator =(const LLInventoryFilter& other); private: bool areDateLimitsSet(); @@ -203,7 +279,8 @@ private: U32 mOrder; U32 mLastLogoff; - FilterOps mFilterOps; + std::string::size_type mSubStringMatchOffset; + FilterOps mFilterOps; FilterOps mDefaultFilterOps; std::string::size_type mSubStringMatchOffset; @@ -211,9 +288,9 @@ private: std::string mFilterSubStringOrig; const std::string mName; - S32 mFilterGeneration; - S32 mMustPassGeneration; - S32 mMinRequiredGeneration; + S32 mLastSuccessGeneration; + S32 mLastFailGeneration; + S32 mFirstSuccessGeneration; S32 mNextFilterGeneration; S32 mFilterCount; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 01a8ecfb5d..f5e2a23da0 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -37,6 +37,7 @@ #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" #include "llfolderview.h" +#include "llfolderviewitem.h" #include "llimfloater.h" #include "llimview.h" #include "llinventorybridge.h" @@ -54,6 +55,62 @@ const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("Recent const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; +// +// class LLFolderViewModelInventory +// +void LLFolderViewModelInventory::requestSort(class LLFolderViewFolder* folder) +{ + base_t::requestSort(folder); + if (getSorter().isByDate()) + { + // sort by date potentially affects parent folders which use a date + // derived from newest item in them + requestSort(folder->getParentFolder()); + } +} + +static LLFastTimer::DeclareTimer FTM_INVENTORY_SORT("Sort"); + +void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) +{ + LLFastTimer _(FTM_INVENTORY_SORT); + + if (!needsSort(folder)) return; + + LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getListener()); + if (modelp->getUUID().isNull()) return; + + for (std::list<LLFolderViewFolder*>::iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); + it != end_it; + ++it) + { + LLFolderViewFolder* child_folderp = *it; + sort(child_folderp); + + if (child_folderp->getFoldersCount() > 0) + { + time_t most_recent_folder_time = + static_cast<LLFolderViewModelItemInventory*>(child_folderp->getFoldersBegin()->getListener())->getCreationDate(); + LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getListener()); + if (most_recent_folder_time > modelp->getCreationDate()) + { + modelp->setCreationDate(most_recent_folder_time); + } + } + if (child_folderp->getItemsCount() > 0) + { + time_t most_recent_item_time = + static_cast<LLFolderViewModelItemInventory*>(child_folderp->getItemsBegin()->getListener())->getCreationDate(); + + LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getListener()); + if (most_recent_item_time > modelp->getCreationDate()) + { + modelp->setCreationDate(most_recent_item_time); + } + } + } + base_t::sort(folder); +} //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryPanelObserver @@ -133,7 +190,6 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mAllowMultiSelect(p.allow_multi_select), mShowItemLinkOverlays(p.show_item_link_overlays), mShowEmptyMessage(p.show_empty_message), - mShowLoadStatus(p.show_load_status), mViewsInitialized(false), mInvFVBridgeBuilder(NULL) { @@ -253,14 +309,11 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) LLInventoryPanel::~LLInventoryPanel() { - if (mFolderRoot) - { - U32 sort_order = mFolderRoot->getSortOrder(); - if (mSortOrderSetting != INHERIT_SORT_ORDER) - { - gSavedSettings.setU32(mSortOrderSetting, sort_order); - } - } + U32 sort_order = getViewModel()->getSortOrder(); + if (mSortOrderSetting != INHERIT_SORT_ORDER) + { + gSavedSettings.setU32(mSortOrderSetting, sort_order); + } gIdleCallbacks.deleteFunction(onIdle, this); @@ -276,26 +329,18 @@ LLInventoryPanel::~LLInventoryPanel() void LLInventoryPanel::draw() { // Select the desired item (in case it wasn't loaded when the selection was requested) - mFolderRoot->updateSelection(); + updateSelection(); LLPanel::draw(); } LLInventoryFilter* LLInventoryPanel::getFilter() { - if (mFolderRoot) - { - return mFolderRoot->getFilter(); - } - return NULL; + return getViewModel()->getFilter(); } const LLInventoryFilter* LLInventoryPanel::getFilter() const { - if (mFolderRoot) - { - return mFolderRoot->getFilter(); - } - return NULL; + return getViewModel()->getFilter(); } void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type) @@ -308,12 +353,12 @@ void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType U32 LLInventoryPanel::getFilterObjectTypes() const { - return mFolderRoot->getFilterObjectTypes(); + return getFilter()->getFilterObjectTypes(); } U32 LLInventoryPanel::getFilterPermMask() const { - return mFolderRoot->getFilterPermissions(); + return getFilter()->getFilterPermissions(); } @@ -334,16 +379,17 @@ void LLInventoryPanel::setFilterSubString(const std::string& string) const std::string LLInventoryPanel::getFilterSubString() { - return mFolderRoot->getFilterSubString(); + return getFilter()->getFilterSubString(); } void LLInventoryPanel::setSortOrder(U32 order) { + LLInventorySort sorter(order); getFilter()->setSortOrder(order); - if (getFilter()->isModified()) + if (order != getViewModel()->getSortOrder()) { - mFolderRoot->setSortOrder(order); + getViewModel()->setSorter(LLInventorySort(order)); // try to keep selection onscreen, even if it wasn't to start with mFolderRoot->scrollToShowSelection(); } @@ -351,12 +397,7 @@ void LLInventoryPanel::setSortOrder(U32 order) U32 LLInventoryPanel::getSortOrder() const { - return mFolderRoot->getSortOrder(); -} - -void LLInventoryPanel::requestSort() -{ - mFolderRoot->requestSort(); + return getViewModel()->getSortOrder(); } void LLInventoryPanel::setSinceLogoff(BOOL sl) @@ -405,7 +446,7 @@ void LLInventoryPanel::modelChanged(U32 mask) { const LLUUID& item_id = (*items_iter); const LLInventoryObject* model_item = model->getObject(item_id); - LLFolderViewItem* view_item = mFolderRoot->getItemByID(item_id); + LLFolderViewItem* view_item = getItemByID(item_id); // LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item // to folder is the fast way to get a folder without searching through folders tree. @@ -439,6 +480,7 @@ void LLInventoryPanel::modelChanged(U32 mask) if (model_item && view_item) { view_item->destroyView(); + removeItemID(view_item->getListener()->getUUID()); } view_item = buildNewViews(item_id); view_folder = dynamic_cast<LLFolderViewFolder *>(view_item); @@ -497,9 +539,9 @@ void LLInventoryPanel::modelChanged(U32 mask) else if (model_item && view_item) { // Don't process the item if it is the root - if (view_item->getRoot() != view_item) + if (view_item->getParentFolder()) { - LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolderRoot->getItemByID(model_item->getParentUUID()); + LLFolderViewFolder* new_parent = (LLFolderViewFolder*)getItemByID(model_item->getParentUUID()); // Item has been moved. if (view_item->getParentFolder() != new_parent) { @@ -507,13 +549,15 @@ void LLInventoryPanel::modelChanged(U32 mask) { // Item is to be moved and we found its new parent in the panel's directory, so move the item's UI. view_item->getParentFolder()->extractItem(view_item); - view_item->addToFolder(new_parent, mFolderRoot); + view_item->addToFolder(new_parent); + addItemID(view_item->getListener()->getUUID(), view_item); } else { // Item is to be moved outside the panel's directory (e.g. moved to trash for a panel that // doesn't include trash). Just remove the item's UI. view_item->destroyView(); + removeItemID(view_item->getListener()->getUUID()); } } } @@ -526,6 +570,7 @@ void LLInventoryPanel::modelChanged(U32 mask) { // Remove the item's UI. view_item->destroyView(); + removeItemID(view_item->getListener()->getUUID()); } } } @@ -574,14 +619,14 @@ void LLInventoryPanel::initializeViews() if (gAgent.isFirstLogin()) { // Auto open the user's library - LLFolderViewFolder* lib_folder = mFolderRoot->getFolderByID(gInventory.getLibraryRootFolderID()); + LLFolderViewFolder* lib_folder = getFolderByID(gInventory.getLibraryRootFolderID()); if (lib_folder) { lib_folder->setOpen(TRUE); } // Auto close the user's my inventory folder - LLFolderViewFolder* my_inv_folder = mFolderRoot->getFolderByID(gInventory.getRootFolderID()); + LLFolderViewFolder* my_inv_folder = getFolderByID(gInventory.getRootFolderID()); if (my_inv_folder) { my_inv_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); @@ -592,10 +637,11 @@ void LLInventoryPanel::initializeViews() LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id) { // Destroy the old view for this ID so we can rebuild it. - LLFolderViewItem* old_view = mFolderRoot->getItemByID(id); + LLFolderViewItem* old_view = getItemByID(id); if (old_view) { old_view->destroyView(); + removeItemID(old_view->getListener()->getUUID()); } return buildNewViews(id); @@ -619,7 +665,6 @@ LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool u p.use_label_suffix = useLabelSuffix; p.allow_multiselect = mAllowMultiSelect; p.show_empty_message = mShowEmptyMessage; - p.show_load_status = mShowLoadStatus; return LLUICtrlFactory::create<LLFolderView>(p); } @@ -680,7 +725,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) else if (objectp) { const LLUUID &parent_id = objectp->getParentUUID(); - parent_folder = (LLFolderViewFolder*)mFolderRoot->getItemByID(parent_id); + parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); if (parent_folder) { @@ -704,12 +749,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) objectp->getUUID()); if (new_listener) { - LLFolderViewFolder* folderp = createFolderViewFolder(new_listener); - if (folderp) - { - folderp->setItemSortOrder(mFolderRoot->getSortOrder()); - } - itemp = folderp; + itemp = createFolderViewFolder(new_listener); } } else @@ -732,7 +772,8 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) if (itemp) { - itemp->addToFolder(parent_folder, mFolderRoot); + itemp->addToFolder(parent_folder); + addItemID(itemp->getListener()->getUUID(), itemp); } } } @@ -904,7 +945,7 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc { return; } - mFolderRoot->setSelectionByID(obj_id, take_keyboard_focus); + setSelectionByID(obj_id, take_keyboard_focus); } void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb) @@ -917,7 +958,7 @@ void LLInventoryPanel::setSelectCallback(const boost::function<void (const std:: void LLInventoryPanel::clearSelection() { - mFolderRoot->clearSelection(); + mSelectThisID.setNull(); } void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action) @@ -953,12 +994,12 @@ void LLInventoryPanel::doToSelected(const LLSD& userdata) void LLInventoryPanel::doCreate(const LLSD& userdata) { - menu_create_inventory_item(mFolderRoot, LLFolderBridge::sSelf.get(), userdata); + menu_create_inventory_item(this, LLFolderBridge::sSelf.get(), userdata); } bool LLInventoryPanel::beginIMSession() { - std::set<LLUUID> selected_items = mFolderRoot->getSelectionList(); + std::set<LLFolderViewItem*> selected_items = mFolderRoot->getSelectionList(); std::string name; static int session_num = 1; @@ -966,12 +1007,11 @@ bool LLInventoryPanel::beginIMSession() LLDynamicArray<LLUUID> members; EInstantMessage type = IM_SESSION_CONFERENCE_START; - std::set<LLUUID>::const_iterator iter; + std::set<LLFolderViewItem*>::const_iterator iter; for (iter = selected_items.begin(); iter != selected_items.end(); iter++) { - LLUUID item = *iter; - LLFolderViewItem* folder_item = mFolderRoot->getItemByID(item); + LLFolderViewItem* folder_item = (*iter); if(folder_item) { @@ -1013,8 +1053,6 @@ bool LLInventoryPanel::beginIMSession() } else { - LLFolderViewItem* folder_item = mFolderRoot->getItemByID(item); - if(!folder_item) return true; LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener(); if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD) @@ -1056,13 +1094,13 @@ bool LLInventoryPanel::beginIMSession() bool LLInventoryPanel::attachObject(const LLSD& userdata) { // Copy selected item UUIDs to a vector. - std::set<LLUUID> selected_items = mFolderRoot->getSelectionList(); + std::set<LLFolderViewItem*> selected_items = mFolderRoot->getSelectionList(); uuid_vec_t items; - for (std::set<LLUUID>::const_iterator set_iter = selected_items.begin(); + for (std::set<LLFolderViewItem*>::const_iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) { - items.push_back(*set_iter); + items.push_back((*set_iter)->getListener()->getUUID()); } // Attach selected items. @@ -1209,6 +1247,84 @@ BOOL LLInventoryPanel::getIsHiddenFolderType(LLFolderType::EType folder_type) co return !(getFilter()->getFilterCategoryTypes() & (1ULL << folder_type)); } +void LLInventoryPanel::addItemID( const LLUUID& id, LLFolderViewItem* itemp ) +{ + mItemMap[id] = itemp; +} + +void LLInventoryPanel::removeItemID(const LLUUID& id) +{ + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(id, categories, items, TRUE); + + mItemMap.erase(id); + + for (LLInventoryModel::cat_array_t::iterator it = categories.begin(), end_it = categories.end(); + it != end_it; + ++it) + { + mItemMap.erase((*it)->getUUID()); + } + + for (LLInventoryModel::item_array_t::iterator it = items.begin(), end_it = items.end(); + it != end_it; + ++it) + { + mItemMap.erase((*it)->getUUID()); + } +} + +LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); +LLFolderViewItem* LLInventoryPanel::getItemByID(const LLUUID& id) +{ + LLFastTimer _(FTM_GET_ITEM_BY_ID); + if (id == mFolderRoot->getListener()->getUUID()) + { + return mFolderRoot; + } + + std::map<LLUUID, LLFolderViewItem*>::iterator map_it; + map_it = mItemMap.find(id); + if (map_it != mItemMap.end()) + { + return map_it->second; + } + + return NULL; +} + +LLFolderViewFolder* LLInventoryPanel::getFolderByID(const LLUUID& id) +{ + LLFolderViewItem* item = getItemByID(id); + return dynamic_cast<LLFolderViewFolder*>(item); +} + + +void LLInventoryPanel::setSelectionByID( const LLUUID& obj_id, BOOL take_keyboard_focus ) +{ + LLFolderViewItem* itemp = getItemByID(obj_id); + if(itemp && itemp->getListener()) + { + itemp->arrangeAndSet(TRUE, take_keyboard_focus); + mSelectThisID.setNull(); + return; + } + else + { + // save the desired item to be selected later (if/when ready) + mSelectThisID = obj_id; + } +} + +void LLInventoryPanel::updateSelection() +{ + if (mSelectThisID.notNull()) + { + setSelectionByID(mSelectThisID, false); + } +} + /************************************************************************/ /* Recent Inventory Panel related class */ diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 7d805f6862..787cacba43 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -30,6 +30,7 @@ #include "llassetstorage.h" #include "lldarray.h" +#include "llfolderviewitem.h" #include "llfloater.h" #include "llinventory.h" #include "llinventoryfilter.h" @@ -55,6 +56,18 @@ class LLFilterEditor; class LLTabContainer; class LLInvPanelComplObserver; +class LLFolderViewModelInventory +: public LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> +{ + typedef LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> base_t; + + virtual ~LLFolderViewModelInventory() {} + + void sort(LLFolderViewFolder* folder); + void requestSort(LLFolderViewFolder* folder); +}; + + class LLInventoryPanel : public LLPanel { //-------------------------------------------------------------------- @@ -85,7 +98,6 @@ public: Optional<std::string> start_folder; Optional<bool> use_label_suffix; Optional<bool> show_empty_message; - Optional<bool> show_load_status; Optional<LLScrollContainer::Params> scroll; Optional<bool> accepts_drag_and_drop; @@ -98,7 +110,6 @@ public: start_folder("start_folder"), use_label_suffix("use_label_suffix", true), show_empty_message("show_empty_message", true), - show_load_status("show_load_status"), scroll("scroll"), accepts_drag_and_drop("accepts_drag_and_drop") {} @@ -182,22 +193,35 @@ public: static void openInventoryPanelAndSetSelection(BOOL auto_open, const LLUUID& obj_id); + void addItemID(const LLUUID& id, LLFolderViewItem* itemp); + void removeItemID(const LLUUID& id); + LLFolderViewItem* getItemByID(const LLUUID& id); + LLFolderViewFolder* getFolderByID(const LLUUID& id); + void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); + void updateSelection(); + + LLFolderViewModelInventory* getViewModel() { return &mViewModel; } + const LLFolderViewModelInventory* getViewModel() const { return &mViewModel; } + protected: void openStartFolderOrMyInventory(); // open the first level of inventory void onItemsCompletion(); // called when selected items are complete - LLInventoryModel* mInventory; + LLUUID mSelectThisID; + LLInventoryModel* mInventory; LLInventoryObserver* mInventoryObserver; LLInvPanelComplObserver* mCompletionObserver; BOOL mAcceptsDragAndDrop; BOOL mAllowMultiSelect; BOOL mShowItemLinkOverlays; // Shows link graphic over inventory item icons BOOL mShowEmptyMessage; - BOOL mShowLoadStatus; LLFolderView* mFolderRoot; LLScrollContainer* mScroller; + LLFolderViewModelInventory mViewModel; + + std::map<LLUUID, LLFolderViewItem*> mItemMap; /** * Pointer to LLInventoryFVBridgeBuilder. * @@ -218,7 +242,6 @@ public: void setSortOrder(U32 order); U32 getSortOrder() const; - void requestSort(); private: std::string mSortOrderSetting; @@ -252,4 +275,25 @@ private: LLUUID mStartFolderID; }; +class LLFolderViewModelItemInventory + : public LLFolderViewModelItemCommon +{ +public: + virtual const LLUUID& getUUID() const = 0; + virtual time_t getCreationDate() const = 0; // UTC seconds + virtual void setCreationDate(time_t creation_date_utc) = 0; + virtual PermissionMask getPermissionMask() const = 0; + virtual LLFolderType::EType getPreferredType() const = 0; + virtual void previewItem( void ) = 0; + virtual void showProperties(void) = 0; + virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. + virtual BOOL isUpToDate() const = 0; + virtual BOOL hasChildren() const = 0; + virtual LLInventoryType::EType getInventoryType() const = 0; + virtual void performAction(LLInventoryModel* model, std::string action) = 0; + virtual LLWearableType::EType getWearableType() const = 0; + virtual EInventorySortGroup getSortGroup() const; + virtual void requestSort(const LLInventorySort& sorter); +}; + #endif // LL_LLINVENTORYPANEL_H diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index c7454e85a9..fd207f098f 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -299,7 +299,7 @@ void LLLandmarksPanel::onTeleport() return; } - LLFolderViewEventListener* listenerp = current_item->getListener(); + LLFolderViewModelItem* listenerp = current_item->getListener(); if (listenerp && listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) { listenerp->openItem(); @@ -360,7 +360,7 @@ void LLLandmarksPanel::onSelectorButtonClicked() LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem(); if (!cur_item) return; - LLFolderViewEventListener* listenerp = cur_item->getListener(); + LLFolderViewModelItem* listenerp = cur_item->getListener(); if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) { LLSD key; @@ -376,7 +376,7 @@ void LLLandmarksPanel::updateShowFolderState() if (!mLandmarksInventoryPanel->getFilter()) return; - bool show_all_folders = mLandmarksInventoryPanel->getRootFolder()->getFilterSubString().empty(); + bool show_all_folders = mLandmarksInventoryPanel->getFilterSubString().empty(); if (show_all_folders) { show_all_folders = category_has_descendents(mLandmarksInventoryPanel); @@ -466,7 +466,7 @@ LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPa LLFolderView* root = inventory_list->getRootFolder(); - LLFolderViewItem* item = root->getItemByID(obj_id); + LLFolderViewItem* item = inventory_list->getItemByID(obj_id); if (!item) return NULL; @@ -665,20 +665,20 @@ void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory { if (inventory_list != mFavoritesInventoryPanel) { - mFavoritesInventoryPanel->getRootFolder()->clearSelection(); + mFavoritesInventoryPanel->clearSelection(); } if (inventory_list != mLandmarksInventoryPanel) { - mLandmarksInventoryPanel->getRootFolder()->clearSelection(); + mLandmarksInventoryPanel->clearSelection(); } if (inventory_list != mMyInventoryPanel) { - mMyInventoryPanel->getRootFolder()->clearSelection(); + mMyInventoryPanel->clearSelection(); } if (inventory_list != mLibraryInventoryPanel) { - mLibraryInventoryPanel->getRootFolder()->clearSelection(); + mLibraryInventoryPanel->clearSelection(); } } @@ -738,7 +738,7 @@ void LLLandmarksPanel::onActionsButtonClick() if(!cur_item) return; - LLFolderViewEventListener* listenerp = cur_item->getListener(); + LLFolderViewModelItem* listenerp = cur_item->getListener(); if(!listenerp) return; @@ -794,7 +794,7 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const LLFolderViewItem* item = getCurSelectedItem(); if (item && mCurrentSelectedList == mLandmarksInventoryPanel) { - LLFolderViewEventListener* folder_bridge = NULL; + LLFolderViewModelItem* folder_bridge = NULL; if (item-> getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) { @@ -808,7 +808,7 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const folder_bridge = item->getListener(); } - menu_create_inventory_item(mCurrentSelectedList->getRootFolder(), + menu_create_inventory_item(mCurrentSelectedList, dynamic_cast<LLFolderBridge*> (folder_bridge), LLSD( "category"), gInventory.findCategoryUUIDForType( LLFolderType::FT_LANDMARK)); @@ -816,7 +816,7 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const else { //in case My Landmarks tab is completely empty (thus cannot be determined as being selected) - menu_create_inventory_item(mLandmarksInventoryPanel->getRootFolder(), NULL, LLSD("category"), + menu_create_inventory_item(mLandmarksInventoryPanel, NULL, LLSD("category"), gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK)); if (mMyLandmarksAccordionTab) @@ -977,12 +977,12 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const { if (!root_folder_view) return false; - std::set<LLUUID> selected_uuids = root_folder_view->getSelectionList(); + std::set<LLFolderViewItem*> selected_uuids = root_folder_view->getSelectionList(); // Allow to execute the command only if it can be applied to all selected items. - for (std::set<LLUUID>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) + for (std::set<LLFolderViewItem*>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) { - LLFolderViewItem* item = root_folder_view->getItemByID(*iter); + LLFolderViewItem* item = *iter; // If no item is found it might be a folder id. if (!item) @@ -1049,7 +1049,7 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const { if (mCurrentSelectedList) { - std::set<LLUUID> selection = mCurrentSelectedList->getRootFolder()->getSelectionList(); + std::set<LLFolderViewItem*> selection = mCurrentSelectedList->getRootFolder()->getSelectionList(); if (!selection.empty()) { return ( 1 == selection.size() && !LLAgentPicksInfo::getInstance()->isPickLimitReached() ); @@ -1105,27 +1105,23 @@ void LLLandmarksPanel::onMenuVisibilityChange(LLUICtrl* ctrl, const LLSD& param) { const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - std::set<LLUUID> selected_uuids = root_folder_view->getSelectionList(); + std::set<LLFolderViewItem*> selected_uuids = root_folder_view->getSelectionList(); // Iterate through selected items to find out if any of these items are in Trash // or all the items are in Trash category. - for (std::set<LLUUID>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) + for (std::set<LLFolderViewItem*>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) { - LLFolderViewItem* item = root_folder_view->getItemByID(*iter); + LLFolderViewItem* item = *iter; // If no item is found it might be a folder id. - if (!item) - { - item = root_folder_view->getFolderByID(*iter); - } if (!item) continue; - LLFolderViewEventListener* listenerp = item->getListener(); + LLFolderViewModelItem* listenerp = item->getListener(); if(!listenerp) continue; // Trash category itself should not be included because it can't be // actually restored from trash. - are_all_items_in_trash &= listenerp->isItemInTrash() && *iter != trash_id; + are_all_items_in_trash &= listenerp->isItemInTrash() && (*iter)->getListener()->getUUID() != trash_id; // If there are any selected items in Trash including the Trash category itself // we show "Restore Item" in context menu and hide other irrelevant items. @@ -1202,7 +1198,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold if (can_be_modified) { - LLFolderViewEventListener* listenerp = item->getListener(); + LLFolderViewModelItemInventory* listenerp = item->getListener(); if ("cut" == command_name) { @@ -1263,8 +1259,9 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg LLInventoryItem* item = static_cast<LLInventoryItem*>(cargo_data); if (item) { - LLFolderViewItem* fv_item = (mCurrentSelectedList && mCurrentSelectedList->getRootFolder()) ? - mCurrentSelectedList->getRootFolder()->getItemByID(item->getUUID()) : NULL; + LLFolderViewItem* fv_item = mCurrentSelectedList + ? mCurrentSelectedList->getItemByID(item->getUUID()) + : NULL; if (fv_item) { @@ -1392,7 +1389,7 @@ void LLLandmarksPanel::doCreatePick(LLLandmark* landmark) static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string) { // When search is cleared, restore the old folder state. - if (!inventory_list->getRootFolder()->getFilterSubString().empty() && string == "") + if (!inventory_list->getFilterSubString().empty() && string == "") { inventory_list->setFilterSubString(LLStringUtil::null); // Re-open folders that were open before @@ -1406,7 +1403,7 @@ static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::strin } // save current folder open state if no filter currently applied - if (inventory_list->getRootFolder()->getFilterSubString().empty()) + if (inventory_list->getFilterSubString().empty()) { inventory_list->saveFolderState(); } diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index c3c62920d3..d50cd3b270 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -53,6 +53,7 @@ #include "llviewermenu.h" #include "llviewertexturelist.h" #include "llsidepanelinventory.h" +#include "llfolderview.h" const std::string FILTERS_FILENAME("filters.xml"); @@ -171,7 +172,10 @@ BOOL LLPanelMainInventory::postBuild() { LLSD recent_items = savedFilterState.get( recent_items_panel->getFilter()->getName()); - recent_items_panel->getFilter()->fromLLSD(recent_items); + LLInventoryFilter::Params p; + LLParamSDParser parser; + parser.readSD(recent_items, p); + recent_items_panel->getFilter()->fromParams(p); } } @@ -212,21 +216,22 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) if (filter) { LLSD filterState; - filter->toLLSD(filterState); - filterRoot[filter->getName()] = filterState; + LLInventoryFilter::Params p; + filter->toParams(p); + if (p.validateBlock(false)) + { + LLParamSDParser().writeSD(filterState, p); + filterRoot[filter->getName()] = filterState; + } } } - LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items"); - if (recent_items_panel) - { - LLInventoryFilter* filter = recent_items_panel->getFilter(); - if (filter) - { - LLSD filterState; - filter->toLLSD(filterState); - filterRoot[filter->getName()] = filterState; - } + LLInventoryFilter* filter = getChild<LLInventoryPanel>("Recent Items")->getFilter(); + if (filter) + { + LLSD filterState; + filter->toLLSD(filterState); + filterRoot[filter->getName()] = filterState; } std::ostringstream filterSaveName; @@ -306,7 +311,7 @@ void LLPanelMainInventory::newWindow() void LLPanelMainInventory::doCreate(const LLSD& userdata) { - menu_create_inventory_item(getPanel()->getRootFolder(), NULL, userdata); + menu_create_inventory_item(getPanel(), NULL, userdata); } void LLPanelMainInventory::resetFilters() @@ -417,7 +422,7 @@ void LLPanelMainInventory::onFilterEdit(const std::string& search_string ) } // save current folder open state if no filter currently applied - if (!mActivePanel->getRootFolder()->isFilterModified()) + if (!mActivePanel->getFilter()->isNotDefault()) { mSavedFolderState->setApply(FALSE); mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -1110,15 +1115,15 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) if (root) { can_delete = TRUE; - std::set<LLUUID> selection_set = root->getSelectionList(); + std::set<LLFolderViewItem*> selection_set = root->getSelectionList(); if (selection_set.empty()) return FALSE; - for (std::set<LLUUID>::iterator iter = selection_set.begin(); + for (std::set<LLFolderViewItem*>::iterator iter = selection_set.begin(); iter != selection_set.end(); ++iter) { const LLUUID &item_id = (*iter); - LLFolderViewItem *item = root->getItemByID(item_id); - const LLFolderViewEventListener *listener = item->getListener(); + LLFolderViewItem *item = *iter; + const LLFolderViewModelItemInventory *listener = item->getListener(); llassert(listener); if (!listener) return FALSE; can_delete &= listener->isItemRemovable(); @@ -1148,7 +1153,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) if (command_name == "find_links") { LLFolderView* root = getActivePanel()->getRootFolder(); - std::set<LLUUID> selection_set = root->getSelectionList(); + std::set<LLFolderViewItem*> selection_set = root->getSelectionList(); if (selection_set.size() != 1) return FALSE; LLFolderViewItem* current_item = root->getCurSelectedItem(); if (!current_item) return FALSE; diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index 66c9c323cb..6804342106 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -94,7 +94,7 @@ LLInventoryPanel * LLPanelMarketplaceInbox::setupInventoryPanel() mInventoryPanel->setShape(inventory_placeholder_rect); // Set the sort order newest to oldest - mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE); + mInventoryPanel->getViewModel()->setSorter(LLInventoryFilter::SO_DATE); mInventoryPanel->getFilter()->markDefault(); // Set selection callback for proper update of inventory status buttons @@ -139,12 +139,12 @@ U32 LLPanelMarketplaceInbox::getFreshItemCount() const if (mInventoryPanel) { - const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder(); + LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder(); if (inbox_folder) { - LLFolderViewFolder::folders_t::const_iterator folders_it = inbox_folder->getFoldersBegin(); - LLFolderViewFolder::folders_t::const_iterator folders_end = inbox_folder->getFoldersEnd(); + LLFolderViewFolder::folders_t::iterator folders_it = inbox_folder->getFoldersBegin(); + LLFolderViewFolder::folders_t::iterator folders_end = inbox_folder->getFoldersEnd(); for (; folders_it != folders_end; ++folders_it) { @@ -157,8 +157,8 @@ U32 LLPanelMarketplaceInbox::getFreshItemCount() const } } - LLFolderViewFolder::items_t::const_iterator items_it = inbox_folder->getItemsBegin(); - LLFolderViewFolder::items_t::const_iterator items_end = inbox_folder->getItemsEnd(); + LLFolderViewFolder::items_t::iterator items_it = inbox_folder->getItemsBegin(); + LLFolderViewFolder::items_t::iterator items_end = inbox_folder->getItemsEnd(); for (; items_it != items_end; ++items_it) { diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index 678e4f2843..1d079adfd3 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -29,6 +29,7 @@ #include "llpanelmarketplaceinboxinventory.h" #include "llfolderview.h" +#include "llfolderviewitem.h" #include "llfoldervieweventlistener.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" @@ -253,9 +254,9 @@ LLInboxFolderViewItem::LLInboxFolderViewItem(const Params& p) #endif } -BOOL LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +BOOL LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder) { - BOOL retval = LLFolderViewItem::addToFolder(folder, root); + BOOL retval = LLFolderViewItem::addToFolder(folder); #if SUPPORTING_FRESH_ITEM_COUNT // Compute freshness if our parent is the root folder for the inbox diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h index d6b827ee3e..209f3a4098 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.h +++ b/indra/newview/llpanelmarketplaceinboxinventory.h @@ -81,8 +81,6 @@ public: bool isFresh() const { return mFresh; } protected: - void setCreationDate(time_t creation_date_utc); - bool mFresh; }; @@ -102,7 +100,7 @@ public: LLInboxFolderViewItem(const Params& p); - BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); + BOOL addToFolder(LLFolderViewFolder* folder); BOOL handleDoubleClick(S32 x, S32 y, MASK mask); void draw(); diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp index ff62cb23db..b5c7c4ca88 100644 --- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceoutboxinventory.cpp @@ -28,7 +28,7 @@ #include "llpanelmarketplaceoutboxinventory.h" -#include "llfolderview.h" +#include "llfolderviewitem.h" #include "llfoldervieweventlistener.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 1efd1c3d9c..2789fe0082 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -71,7 +71,7 @@ /// Class LLTaskInvFVBridge ///---------------------------------------------------------------------------- -class LLTaskInvFVBridge : public LLFolderViewEventListener +class LLTaskInvFVBridge : public LLFolderViewModelItemInventory { protected: LLUUID mUUID; @@ -102,7 +102,7 @@ public: S32 getPrice(); static bool commitBuyItem(const LLSD& notification, const LLSD& response); - // LLFolderViewEventListener functionality + // LLFolderViewModelItemInventory functionality virtual const std::string& getName() const; virtual const std::string& getDisplayName() const; virtual PermissionMask getPermissionMask() const { return PERM_NONE; } @@ -120,9 +120,9 @@ public: virtual BOOL isItemMovable() const; virtual BOOL isItemRemovable() const; virtual BOOL removeItem(); - virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch); - virtual void move(LLFolderViewEventListener* parent_listener); - virtual BOOL isItemCopyable() const; + virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); + virtual void move(LLFolderViewModelItem* parent_listener); + virtual BOOL isItemCopyable() const; virtual BOOL copyToClipboard() const; virtual void cutToClipboard(); virtual BOOL isClipboardPasteable() const; @@ -467,7 +467,7 @@ BOOL LLTaskInvFVBridge::removeItem() return FALSE; } -void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) +void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewModelItem*>& batch) { if (!mPanel) { @@ -507,7 +507,7 @@ void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& } } -void LLTaskInvFVBridge::move(LLFolderViewEventListener* parent_listener) +void LLTaskInvFVBridge::move(LLFolderViewModelItem* parent_listener) { } @@ -1547,7 +1547,8 @@ void LLPanelObjectInventory::reset() p.folder_indentation = -14; // subtract space normally reserved for folder expanders mFolders = LLUICtrlFactory::create<LLFolderView>(p); // this ensures that we never say "searching..." or "no items found" - mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + RN: make this happen by manipulating filter object directly + //mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); if (hasFocus()) @@ -1607,7 +1608,7 @@ void LLPanelObjectInventory::updateInventory() // << " panel UUID: " << panel->mTaskUUID << "\n" // << " task UUID: " << object->mID << llendl; // We're still interested in this task's inventory. - std::set<LLUUID> selected_items; + std::set<LLFolderViewItem*> selected_items; BOOL inventory_has_focus = FALSE; if (mHaveInventory) { @@ -1645,11 +1646,11 @@ void LLPanelObjectInventory::updateInventory() } // restore previous selection - std::set<LLUUID>::iterator selection_it; + std::set<LLFolderViewItem*>::iterator selection_it; BOOL first_item = TRUE; for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it) { - LLFolderViewItem* selected_item = mFolders->getItemByID(*selection_it); + LLFolderViewItem* selected_item = (*selection_it); if (selected_item) { //HACK: "set" first item then "change" each other one to get keyboard focus right @@ -1751,7 +1752,8 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li params.tool_tip = params.name; view = LLUICtrlFactory::create<LLFolderViewItem> (params); } - view->addToFolder(folder, mFolders); + view->addToFolder(folder); + addItemID(view->getListener()->getUUID(), view); } } diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 35e2e96bab..4abc7fea0e 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -270,7 +270,7 @@ private: if (inventory_panel->getVisible()) { - inventory_panel->setSortOrder(sort_order); + inventory_panel->getViewModel()->setSorter(sort_order); } else { @@ -738,7 +738,7 @@ void LLPanelOutfitEdit::onSearchEdit(const std::string& string) } // save current folder open state if no filter currently applied - if (mInventoryItemsPanel->getRootFolder()->getFilterSubString().empty()) + if (mInventoryItemsPanel->getFilterSubString().empty()) { mSavedFolderState->setApply(FALSE); mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -885,13 +885,13 @@ LLPanelOutfitEdit::selection_info_t LLPanelOutfitEdit::getAddMorePanelSelectionT { if (mInventoryItemsPanel != NULL && mInventoryItemsPanel->getVisible()) { - std::set<LLUUID> selected_uuids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); + std::set<LLFolderViewItem*> selected_items = mInventoryItemsPanel->getRootFolder()->getSelectionList(); - result.second = selected_uuids.size(); + result.second = selected_items.size(); if (result.second == 1) { - result.first = getWearableTypeByItemUUID(*(selected_uuids.begin())); + result.first = getWearableTypeByItemUUID((*selected_items.begin())->getListener()->getUUID()); } } else if (mWearableItemsList != NULL && mWearableItemsList->getVisible()) @@ -1310,7 +1310,7 @@ void LLPanelOutfitEdit::getCurrentItemUUID(LLUUID& selected_id) LLFolderViewItem* curr_item = mInventoryItemsPanel->getRootFolder()->getCurSelectedItem(); if (!curr_item) return; - LLFolderViewEventListener* listenerp = curr_item->getListener(); + LLFolderViewModelItemInventory* listenerp = curr_item->getListener(); if (!listenerp) return; selected_id = listenerp->getUUID(); @@ -1327,9 +1327,13 @@ void LLPanelOutfitEdit::getSelectedItemsUUID(uuid_vec_t& uuid_list) void (uuid_vec_t::* tmp)(LLUUID const &) = &uuid_vec_t::push_back; if (mInventoryItemsPanel->getVisible()) { - std::set<LLUUID> item_set = mInventoryItemsPanel->getRootFolder()->getSelectionList(); - - std::for_each(item_set.begin(), item_set.end(), boost::bind( tmp, &uuid_list, _1)); + std::set<LLFolderViewItem*> item_set = mInventoryItemsPanel->getRootFolder()->getSelectionList(); + for (std::set<LLFolderViewItem*>::iterator it = item_set.begin(), end_it = item_set.end(); + it != end_it; + ++it) + { + uuid_list.push_back((*it)->getListener()->getUUID()); + } } else if (mWearablesListViewPanel->getVisible()) { @@ -1374,13 +1378,13 @@ void LLPanelOutfitEdit::saveListSelection() { if(mWearablesListViewPanel->getVisible()) { - std::set<LLUUID> selected_ids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); + std::set<LLFolderViewItem*> selected_ids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); if(!selected_ids.size()) return; - for (std::set<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) + for (std::set<LLFolderViewItem*>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) { - mWearableItemsList->selectItemByUUID(*item_id, true); + mWearableItemsList->selectItemByUUID((*item_id)->getListener()->getUUID(), true); } mWearableItemsList->scrollToShowFirstSelectedItem(); } @@ -1398,7 +1402,7 @@ void LLPanelOutfitEdit::saveListSelection() for(std::vector<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) { - LLFolderViewItem* item = root->getItemByID(*item_id); + LLFolderViewItem* item = mInventoryItemsPanel->getItemByID(*item_id); if (!item) continue; LLFolderViewFolder* parent = item->getParentFolder(); diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index fe4cc0f55f..97c5d531d2 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -85,34 +85,33 @@ void LLPlacesLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) void LLPlacesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { + std::vector<std::string> items; + std::vector<std::string> disabled_items; + + LLInventoryPanel* inv_panel = mInventoryPanel.get(); + bool is_open = false; + if (inv_panel) { - std::vector<std::string> items; - std::vector<std::string> disabled_items; + LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getItemByID(mUUID)); + is_open = (NULL != folder) && folder->isOpen(); + } - LLInventoryPanel* inv_panel = mInventoryPanel.get(); - bool is_open = false; - if (inv_panel) - { - LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); - is_open = (NULL != folder) && folder->isOpen(); - } + // collect all items' names + fill_items_with_menu_items(items, menu); - // collect all items' names - fill_items_with_menu_items(items, menu); + // remove expand or collapse menu item depend on folder state + std::string collapse_expand_item_to_hide(is_open ? "expand" : "collapse"); + std::vector<std::string>::iterator it = std::find(items.begin(), items.end(), collapse_expand_item_to_hide); + if (it != items.end()) items.erase(it); - // remove expand or collapse menu item depend on folder state - std::string collapse_expand_item_to_hide(is_open ? "expand" : "collapse"); - std::vector<std::string>::iterator it = std::find(items.begin(), items.end(), collapse_expand_item_to_hide); - if (it != items.end()) items.erase(it); - // Disabled items are processed via LLLandmarksPanel::isActionEnabled() - // they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601 + // Disabled items are processed via LLLandmarksPanel::isActionEnabled() + // they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601 - // repeat parent functionality - sSelf = getHandle(); // necessary for "New Folder" functionality + // repeat parent functionality + sSelf = getHandle(); // necessary for "New Folder" functionality - hide_context_entries(menu, items, disabled_items); - } + hide_context_entries(menu, items, disabled_items); } //virtual @@ -140,7 +139,7 @@ LLFolderViewFolder* LLPlacesFolderBridge::getFolder() LLInventoryPanel* inv_panel = mInventoryPanel.get(); if (inv_panel) { - folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); + folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getItemByID(mUUID)); } return folder; diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index f7823f4fe8..1de26660bc 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -31,6 +31,7 @@ #include "llplacesinventorypanel.h" #include "llfoldervieweventlistener.h" +#include "llfolderview.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llpanellandmarks.h" @@ -91,7 +92,7 @@ void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& par p.parent_panel = this; p.allow_multiselect = mAllowMultiSelect; p.use_ellipses = true; // truncate inventory item text so remove horizontal scroller - mFolderRoot = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p); + mFolderRoot = LLUICtrlFactory::create<LLPlacesFolderView>(p); } diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 853656905c..f069da5869 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -267,7 +267,7 @@ void LLSidepanelAppearance::onOpenOutfitButtonClicked() if (inventory_panel) { LLFolderView* root = inventory_panel->getRootFolder(); - LLFolderViewItem *outfit_folder = root->getItemByID(outfit_link->getLinkedUUID()); + LLFolderViewItem *outfit_folder = inventory_panel->getItemByID(outfit_link->getLinkedUUID()); if (outfit_folder) { outfit_folder->setOpen(!outfit_folder->isOpen()); diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index c8b67cc9ec..a86523d32d 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -36,6 +36,7 @@ #include "llfirstuse.h" #include "llfloatersidepanelcontainer.h" #include "llfoldertype.h" +#include "llfolderview.h" #include "llhttpclient.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" @@ -653,7 +654,7 @@ U32 LLSidepanelInventory::getSelectedCount() { int count = 0; - std::set<LLUUID> selection_list = mPanelMainInventory->getActivePanel()->getRootFolder()->getSelectionList(); + std::set<LLFolderViewItem*> selection_list = mPanelMainInventory->getActivePanel()->getRootFolder()->getSelectionList(); count += selection_list.size(); if ((count == 0) && mInboxEnabled && (mInventoryPanelInbox != NULL)) @@ -704,9 +705,9 @@ void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox) updateVerbs(); } -std::set<LLUUID> LLSidepanelInventory::getInboxSelectionList() +std::set<LLFolderViewItem*> LLSidepanelInventory::getInboxSelectionList() { - std::set<LLUUID> inventory_selected_uuids; + std::set<LLFolderViewItem*> inventory_selected_uuids; if (mInboxEnabled && (mInventoryPanelInbox != NULL)) { diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h index a33607f50d..6aa349f0f3 100644 --- a/indra/newview/llsidepanelinventory.h +++ b/indra/newview/llsidepanelinventory.h @@ -63,6 +63,7 @@ public: BOOL isMainInventoryPanelActive() const; void clearSelections(bool clearMain, bool clearInbox); + std::set<LLFolderViewItem*> getInboxSelectionList(); std::set<LLUUID> getInboxSelectionList(); void showItemInfoPanel(); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 19a944e88e..92970003ef 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -345,7 +345,7 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask) { if (!root_folder->getCurSelectedItem()) { - LLFolderViewItem* itemp = root_folder->getItemByID(gInventory.getRootFolderID()); + LLFolderViewItem* itemp = mInventoryPanel->getItemByID(gInventory.getRootFolderID()); if (itemp) { root_folder->setSelection(itemp, FALSE, FALSE); @@ -848,7 +848,7 @@ void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string ) else if (mInventoryPanel->getFilterSubString().empty()) { // first letter in search term, save existing folder open state - if (!mInventoryPanel->getRootFolder()->isFilterModified()) + if (!mInventoryPanel->getFilter()->isNotDefault()) { mSavedFolderState.setApply(FALSE); mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 45ca23cdfe..d827b2b8aa 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1308,7 +1308,7 @@ const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not) // ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements... -void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) +void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) { std::string type_name = userdata.asString(); @@ -1332,7 +1332,7 @@ void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, cons LLUUID category = gInventory.createNewCategory(parent_id, preferred_type, LLStringUtil::null); gInventory.notifyObservers(); - root->setSelectionByID(category, TRUE); + panel->setSelectionByID(category, TRUE); } else if ("lsl" == type_name) { @@ -1375,7 +1375,7 @@ void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, cons llwarns << "Can't create unrecognized type " << type_name << llendl; } } - root->setNeedsAutoRename(TRUE); + panel->getRoot()->->setNeedsAutoRename(TRUE); } LLAssetType::EType LLViewerInventoryItem::getType() const @@ -1785,12 +1785,6 @@ void LLViewerInventoryItem::getSLURL() LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID); } -const LLPermissions& LLViewerInventoryItem::getPermissions() const -{ - // Use the actual permissions of the symlink, not its parent. - return LLInventoryItem::getPermissions(); -} - const LLUUID& LLViewerInventoryItem::getCreatorUUID() const { if (const LLViewerInventoryItem *linked_item = getLinkedItem()) @@ -1861,17 +1855,6 @@ LLWearableType::EType LLViewerInventoryItem::getWearableType() const return LLWearableType::EType(getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK); } - -time_t LLViewerInventoryItem::getCreationDate() const -{ - return LLInventoryItem::getCreationDate(); -} - -U32 LLViewerInventoryItem::getCRC32() const -{ - return LLInventoryItem::getCRC32(); -} - // *TODO: mantipov: should be removed with LMSortPrefix patch in llinventorymodel.cpp, EXT-3985 static char getSeparator() { return '@'; } BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName) diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 7822ef4da6..d66362d544 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -34,7 +34,7 @@ #include <boost/signals2.hpp> // boost::signals2::trackable -class LLFolderView; +class LLInventoryPanel; class LLFolderBridge; class LLViewerInventoryCategory; @@ -63,7 +63,6 @@ public: virtual S32 getSortField() const; virtual void setSortField(S32 sortField); virtual void getSLURL(); //Caches SLURL for landmark. //*TODO: Find a better way to do it and remove this method from here. - virtual const LLPermissions& getPermissions() const; virtual const bool getIsFullPerm() const; // 'fullperm' in the popular sense: modify-ok & copy-ok & transfer-ok, no special god rules applied virtual const LLUUID& getCreatorUUID() const; virtual const std::string& getDescription() const; @@ -72,8 +71,11 @@ public: virtual bool isWearableType() const; virtual LLWearableType::EType getWearableType() const; virtual U32 getFlags() const; - virtual time_t getCreationDate() const; - virtual U32 getCRC32() const; // really more of a checksum. + + using LLInventoryItem::getPermissions; + using LLInventoryItem::getCreationDate; + using LLInventoryItem::setCreationDate; + using LLInventoryItem::getCRC32; static BOOL extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName); @@ -372,7 +374,7 @@ void copy_inventory_from_notecard(const LLUUID& destination_id, U32 callback_id = 0); -void menu_create_inventory_item(LLFolderView* root, +void menu_create_inventory_item(LLInventoryPanel* root, LLFolderBridge* bridge, const LLSD& userdata, const LLUUID& default_parent_uuid = LLUUID::null); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index cefd9ef91d..23de64ec13 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -726,7 +726,7 @@ static void highlight_inventory_objects_in_panel(const std::vector<LLUUID>& item LLFolderView* fv = inventory_panel->getRootFolder(); if (fv) { - LLFolderViewItem* fv_item = fv->getItemByID(item_id); + LLFolderViewItem* fv_item = inventory_panel->getItemByID(item_id); if (fv_item) { LLFolderViewItem* fv_folder = fv_item->getParentFolder(); @@ -814,7 +814,13 @@ private: mSelectedItems.clear(); if (LLInventoryPanel::getActiveInventoryPanel()) { - mSelectedItems = LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); + std::set<LLFolderViewItem*> selection = LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); + for (std::set<LLFolderViewItem*>::iterator it = selection.begin(), end_it = selection.end(); + it != end_it; + ++it) + { + mSelectedItems.insert((*it)->getListener()->getUUID()); + } } mSelectedItems.erase(mMoveIntoFolderID); } @@ -849,7 +855,15 @@ private: } // get selected items (without destination folder) - selected_items_t selected_items = active_panel->getRootFolder()->getSelectionList(); + selected_items_t selected_items; + + std::set<LLFolderViewItem*> selection = LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); + for (std::set<LLFolderViewItem*>::iterator it = selection.begin(), end_it = selection.end(); + it != end_it; + ++it) + { + selected_items.insert((*it)->getListener()->getUUID()); + } selected_items.erase(mMoveIntoFolderID); // compare stored & current sets of selected items -- cgit v1.2.3 From 379eec8841212665881569c69804fafd96152387 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 15 Jun 2012 13:35:39 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose continuing fixing build errors renamed llfoldervieweventlistener.h to llfolderviewmodel.h --- indra/newview/CMakeLists.txt | 2 +- indra/newview/llavataractions.cpp | 4 +- indra/newview/llfloateroutbox.cpp | 2 +- indra/newview/llfolderview.cpp | 38 +-- indra/newview/llfolderview.h | 5 +- indra/newview/llfoldervieweventlistener.h | 294 ------------------- indra/newview/llfolderviewitem.cpp | 290 ++++++++----------- indra/newview/llfolderviewitem.h | 67 ++--- indra/newview/llfolderviewmodel.h | 313 +++++++++++++++++++++ indra/newview/llinventorybridge.cpp | 104 +++---- indra/newview/llinventorybridge.h | 30 +- indra/newview/llinventoryfilter.cpp | 31 +- indra/newview/llinventoryfilter.h | 33 +-- indra/newview/llinventoryfunctions.cpp | 2 +- indra/newview/llinventorypanel.cpp | 50 ++-- indra/newview/llinventorypanel.h | 86 +++--- indra/newview/llpanellandmarks.cpp | 40 +-- indra/newview/llpanelmaininventory.cpp | 22 +- indra/newview/llpanelmarketplaceinbox.cpp | 2 +- .../newview/llpanelmarketplaceoutboxinventory.cpp | 2 +- indra/newview/llpanelobjectinventory.cpp | 8 +- indra/newview/llpaneloutfitedit.cpp | 8 +- indra/newview/llplacesinventorypanel.cpp | 4 +- indra/newview/llsidepanelappearance.cpp | 2 +- indra/newview/llsidepanelinventory.cpp | 4 +- indra/newview/lltexturectrl.cpp | 4 +- 26 files changed, 688 insertions(+), 759 deletions(-) delete mode 100644 indra/newview/llfoldervieweventlistener.h create mode 100644 indra/newview/llfolderviewmodel.h (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 785bf4b868..4f447fd35b 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -808,7 +808,7 @@ set(viewer_HEADER_FILES llfloaterwindowsize.h llfloaterworldmap.h llfolderview.h - llfoldervieweventlistener.h + llfolderviewmodel.h llfolderviewitem.h llfollowcam.h llfriendcard.h diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index decfef2ae6..68dc7681cc 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -778,7 +778,7 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL const std::set<LLFolderViewItem*>::const_iterator it_end = inventory_selected.end(); for (; it != it_end; ++it) { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory((*it)->getListener()->getUUID()); + LLViewerInventoryCategory* inv_cat = gInventory.getCategory((*it)->getItemViewModel()->getUUID()); // any category can be offered. if (inv_cat) { @@ -788,7 +788,7 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL // check if inventory item can be given LLFolderViewItem* item = *it; if (!item) return false; - LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getListener()); + LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getViewModelItem()); if (bridge && bridge->canShare()) { continue; diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index ba0f51b467..04a55b261c 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -251,7 +251,7 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId) // Set the sort order newest to oldest - mOutboxInventoryPanel->getViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME); + mOutboxInventoryPanel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME); mOutboxInventoryPanel->getFilter()->markDefault(); fetchOutboxContents(); diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 1f48ef98f6..918e68e444 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -304,7 +304,7 @@ BOOL LLFolderView::canFocusChildren() const BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { // enforce sort order of My Inventory followed by Library - if (folder->getListener()->getUUID() == gInventory.getLibraryRootFolderID()) + if (folder->getViewModelItem()->getUUID() == gInventory.getLibraryRootFolderID()) { mFolders.push_back(folder); } @@ -366,7 +366,7 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen static LLFastTimer::DeclareTimer FTM_FILTER("Filter Inventory"); -void LLFolderView::filter( LLInventoryFilter& filter ) +void LLFolderView::filter( LLFolderViewFilter& filter ) { LLFastTimer t2(FTM_FILTER); filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); @@ -667,7 +667,7 @@ BOOL LLFolderView::startDrag(LLToolDragAndDrop::ESource source) { EDragAndDropType type = DAD_NONE; LLUUID id = LLUUID::null; - can_drag = can_drag && (*item_it)->getListener()->startDrag(&type, &id); + can_drag = can_drag && (*item_it)->getViewModelItem()->startDrag(&type, &id); types.push_back(type); cargo_ids.push_back(id); @@ -947,7 +947,7 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL for(S32 i = 0; i < count; ++i) { - listener = items[i]->getListener(); + listener = items[i]->getViewModelItem(); if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewModelItemInventory*>::FAIL)) { listeners.put(listener); @@ -984,7 +984,7 @@ void LLFolderView::openSelectedItems( void ) // IT_{OBJECT,ATTACHMENT} creates LLProperties // floaters; others create LLPreviews. Put // each one in the right type of container. - LLFolderViewModelItemInventory* listener = (*item_it)->getListener(); + LLFolderViewModelItemInventory* listener = (*item_it)->getViewModelItem(); bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); if (is_prop) LLFloater::setFloaterHost(multi_propertiesp); @@ -1010,7 +1010,7 @@ void LLFolderView::propertiesSelectedItems( void ) { LLFolderViewItem* folder_item = mSelectedItems.front(); if(!folder_item) return; - folder_item->getListener()->showProperties(); + folder_item->getViewModelItem()->showProperties(); } else { @@ -1021,7 +1021,7 @@ void LLFolderView::propertiesSelectedItems( void ) selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - (*item_it)->getListener()->showProperties(); + (*item_it)->getViewModelItem()->showProperties(); } LLFloater::setFloaterHost(NULL); @@ -1124,7 +1124,7 @@ BOOL LLFolderView::canCopy() const for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) { const LLFolderViewItem* item = *selected_it; - if (!item->getListener()->isItemCopyable()) + if (!item->getViewModelItem()->isItemCopyable()) { return FALSE; } @@ -1144,7 +1144,7 @@ void LLFolderView::copy() selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - listener = (*item_it)->getListener(); + listener = (*item_it)->getViewModelItem(); if(listener) { listener->copyToClipboard(); @@ -1164,7 +1164,7 @@ BOOL LLFolderView::canCut() const for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) { const LLFolderViewItem* item = *selected_it; - const LLFolderViewModelItemInventory* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = item->getViewModelItem(); if (!listener || !listener->isItemRemovable()) { @@ -1185,7 +1185,7 @@ void LLFolderView::cut() selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - listener = (*item_it)->getListener(); + listener = (*item_it)->getViewModelItem(); if(listener) { listener->cutToClipboard(); @@ -1210,11 +1210,11 @@ BOOL LLFolderView::canPaste() const { // *TODO: only check folders and parent folders of items const LLFolderViewItem* item = (*item_it); - const LLFolderViewModelItemInventory* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = item->getViewModelItem(); if(!listener || !listener->isClipboardPasteable()) { const LLFolderViewFolder* folderp = item->getParentFolder(); - listener = folderp->getListener(); + listener = folderp->getViewModelItem(); if (!listener || !listener->isClipboardPasteable()) { return FALSE; @@ -1238,7 +1238,7 @@ void LLFolderView::paste() for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) { LLFolderViewItem* item = *selected_it; - LLFolderViewModelItemInventory* listener = item->getListener(); + LLFolderViewModelItemInventory* listener = item->getViewModelItem(); if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY) { item = item->getParentFolder(); @@ -1271,8 +1271,8 @@ void LLFolderView::startRenamingSelectedItem( void ) { item = mSelectedItems.front(); } - if(getVisible() && getEnabled() && (count == 1) && item && item->getListener() && - item->getListener()->isItemRenameable()) + if(getVisible() && getEnabled() && (count == 1) && item && item->getViewModelItem() && + item->getViewModelItem()->isItemRenameable()) { mRenameItem = item; @@ -1581,7 +1581,7 @@ BOOL LLFolderView::canDoDelete() const for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - if (!(*item_it)->getListener()->isItemRemovable()) + if (!(*item_it)->getViewModelItem()->isItemRemovable()) { return FALSE; } @@ -1766,7 +1766,7 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, // when drop is not handled by child, it should be handled // by the folder which is the hierarchy root. if (!handled - && getListener()->getUUID().notNull()) + && getViewModelItem()->getUUID().notNull()) { handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); } @@ -1930,7 +1930,7 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) { LLFolderViewItem* folder_item = *set_iter; if(!folder_item) continue; - LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); + LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem(); if(!bridge) continue; bridge->performAction(model, action); } diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 37005f080f..9b8a629387 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -111,7 +111,7 @@ public: virtual LLFolderView* getRoot() { return this; } - LLFolderViewModelInterface* getViewModel() { return mViewModel; } + LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } void setFilterPermMask(PermissionMask filter_perm_mask); @@ -272,8 +272,6 @@ protected: void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response); - LLInventorySort& getSortFunction() { return mSortFunction; } - protected: LLHandle<LLView> mPopupMenuHandle; @@ -318,7 +316,6 @@ protected: LLPanel* mParentPanel; - LLInventorySort mSortFunction; LLFolderViewModelInterface* mViewModel; /** diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h deleted file mode 100644 index 76e051d12f..0000000000 --- a/indra/newview/llfoldervieweventlistener.h +++ /dev/null @@ -1,294 +0,0 @@ -/** - * @file llfoldervieweventlistener.h - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ -#ifndef LLFOLDERVIEWEVENTLISTENER_H -#define LLFOLDERVIEWEVENTLISTENER_H - -#include "lldarray.h" // *TODO: convert to std::vector -#include "llfoldertype.h" -#include "llfontgl.h" // just for StyleFlags enum -#include "llinventorytype.h" -#include "llpermissionsflags.h" -#include "llpointer.h" -#include "llwearabletype.h" -#include "lltooldraganddrop.h" - -// These are grouping of inventory types. -// Order matters when sorting system folders to the top. -enum EInventorySortGroup -{ - SG_SYSTEM_FOLDER, - SG_TRASH_FOLDER, - SG_NORMAL_FOLDER, - SG_ITEM -}; - -class LLFontGL; -class LLInventoryModel; -class LLMenuGL; -class LLUIImage; -class LLUUID; -class LLFolderViewItem; -class LLFolderViewFolder; - -class LLFolderViewFilter -{ -public: - LLFolderViewFilter() {} - virtual ~LLFolderViewFilter() {} - - // +-------------------------------------------------------------------+ - // + Execution And Results - // +-------------------------------------------------------------------+ - virtual bool check(const LLFolderViewItem* item) = 0; - virtual bool check(const LLInventoryItem* item) = 0; - virtual bool checkFolder(const LLFolderViewFolder* folder) const = 0; - virtual bool checkFolder(const LLUUID& folder_id) const = 0; - - virtual void setEmptyLookupMessage(const std::string& message) = 0; - const virtual std::string& getEmptyLookupMessage() const = 0; - - // +-------------------------------------------------------------------+ - // + Status - // +-------------------------------------------------------------------+ - virtual bool isActive() const = 0; - virtual bool isModified() const = 0; - virtual bool isModifiedAndClear() = 0; - virtual void clearModified() = 0; - virtual const std::string& getName() const = 0; - virtual const std::string& getFilterText() = 0; - //RN: this is public to allow system to externally force a global refilter - virtual void setModified(EFilterBehavior behavior = FILTER_RESTART) = 0; - - // +-------------------------------------------------------------------+ - // + Count - // +-------------------------------------------------------------------+ - virtual void setFilterCount(S32 count) = 0; - virtual S32 getFilterCount() const = 0; - virtual void decrementFilterCount() = 0; - - // +-------------------------------------------------------------------+ - // + Default - // +-------------------------------------------------------------------+ - virtual BOOL isNotDefault() const = 0; - virtual void markDefault() = 0; - virtual void resetDefault() = 0; - - // +-------------------------------------------------------------------+ - // + Generation - // +-------------------------------------------------------------------+ - virtual S32 getCurrentGeneration() const = 0; - virtual S32 getFirstSuccessGeneration() const = 0; - virtual S32 getFirstRequiredGeneration() const = 0; -}; - -struct LLFolderViewModelInterface -{ - virtual void requestSortAll() = 0; - virtual void requestSort(class LLFolderViewFolder*) = 0; - - virtual void sort(class LLFolderViewFolder*) = 0; - virtual void filter(class LLFolderViewFolder*) = 0; -}; - -struct LLFolderViewModelCommon : public LLFolderViewModelInterface -{ - LLFolderViewModelCommon() - : mTargetSortVersion(0) - {} - - virtual void requestSortAll() - { - // sort everything - mTargetSortVersion++; - } - - virtual void requestSort(class LLFolderViewFolder* folder) - { - folder->requestSort(); - } - -protected: - bool needsSort(class LLFolderViewModelItem* item) - { - return item->getSortVersion() < mTargetSortVersion; - } - - S32 mTargetSortVersion; -}; - - -// This is am abstract base class that users of the folderview classes -// would use to bridge the folder view with the underlying data -class LLFolderViewModelItem -{ -public: - virtual ~LLFolderViewModelItem( void ) {}; - - virtual void update() {} //called when drawing - virtual const std::string& getName() const = 0; - virtual const std::string& getDisplayName() const = 0; - - virtual LLPointer<LLUIImage> getIcon() const = 0; - virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } - - virtual LLFontGL::StyleFlags getLabelStyle() const = 0; - virtual std::string getLabelSuffix() const = 0; - - virtual void openItem( void ) = 0; - virtual void closeItem( void ) = 0; - virtual void selectItem(void) = 0; - - virtual BOOL isItemRenameable() const = 0; - virtual BOOL renameItem(const std::string& new_name) = 0; - - virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder - virtual void move( LLFolderViewModelItem* parent_listener ) = 0; - - virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed - virtual BOOL removeItem() = 0; - virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0; - - virtual BOOL isItemCopyable() const = 0; - virtual BOOL copyToClipboard() const = 0; - virtual BOOL cutToClipboard() const = 0; - - virtual BOOL isClipboardPasteable() const = 0; - virtual void pasteFromClipboard() = 0; - virtual void pasteLinkFromClipboard() = 0; - - virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; - - // This method should be called when a drag begins. returns TRUE - // if the drag can begin, otherwise FALSE. - virtual LLToolDragAndDrop::ESource getDragSource() const = 0; - virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; - - // This method will be called to determine if a drop can be - // performed, and will set drop to TRUE if a drop is - // requested. Returns TRUE if a drop is possible/happened, - // otherwise FALSE. - virtual BOOL dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - std::string& tooltip_msg) = 0; - - virtual void requestSort() = 0; - virtual S32 getSortVersion() = 0; - virtual void setSortVersion(S32 version) = 0; -}; - -class LLFolderViewModelItemCommon : public LLFolderViewModelItem -{ -public: - LLFolderViewModelItemCommon() - : mSortVersion(-1) - {} - - void requestSort() { mSortVersion = -1; } - S32 getSortVersion() { return mSortVersion; } - void setSortVersion(S32 version) { mSortVersion = VERSION;} - -protected: - S32 mSortVersion; -}; - -template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE> -class LLFolderViewModel : public LLFolderViewModelCommon -{ -protected: - LLFolderViewModel() {} - - typedef SORT_TYPE SortType; - typedef ITEM_TYPE ItemType; - typedef FOLDER_TYPE FolderType; - typedef FILTER_TYPE FilterType; - - virtual const SortType& getSorter() const { return mSorter; } - virtual void setSorter(const SortType& type) { mSorter = sorter; requestSortAll(); } - virtual FilterType& getFilter() const { return mFilter; } - virtual void setFilter(const FilterType& filter) { mFilter = filter; } - -public: - - struct ViewModelCompare() - { - ViewModelCompare(const SortType& sorter) - : mSorter(sorter) - {} - - int operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) - { - return mSorter(static_cast<const ItemType*>(a->getListener()), static_cast<const ItemType*>(b->getListener())); - } - - int operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) - { - return mSorter(static_cast<const ItemType*>(a->getListener()), static_cast<const ItemType*>(b->getListener())); - } - - const SortType& mSorter; - } - - void sort(LLFolderViewFolder* folder) - { - if (needsSort(folder)) - { - std::sort(folder->getFoldersBegin(), folder->getFoldersEnd(), ViewModelCompare(getSorter())); - std::sort(folder->getItemsBegin(), folder->getItemsEnd(), ViewModelCompare(getSorter())); - folder->getListener()->setSortVersion(mTargetSortVersion); - folder->requestArrange(); - } - } - - void filter(LLFolderViewFolder* folder) - { - FilterType& filter = getFilter(); - for (std::list<LLFolderViewItem*>::iterator it = folder->getItemsBegin(), end_it = folder->getItemsEnd(); - it != end_it; - ++it) - { - LLFolderViewItem* child_item = *it; - child_item->setFiltered(filter(static_cast<ItemType*>(child_item->getListener())), filter.getCurrentGeneration()) - } - - for (std::list<LLFolderViewFolder*>::iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); - it != end_it; - ++it) - { - LLFolderViewItem* child_folder = *it; - child_folder->setFiltered(filter(static_cast<ItemType*>(child_folder->getListener())), filter.getCurrentGeneration()) - } - } - -protected: - SortType mSorter; - FilterType mFilter; -}; - - - - - -#endif diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 13b721fa23..0a3c03e868 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -30,10 +30,9 @@ // viewer includes #include "llfolderview.h" // Items depend extensively on LLFolderViews #include "llfolderview.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" #include "llviewerfoldertype.h" #include "llinventorybridge.h" // for LLItemBridge in LLInventorySort::operator() -#include "llinventoryfilter.h" #include "llinventoryfunctions.h" #include "llinventorymodelbackgroundfetch.h" #include "llpanel.h" @@ -120,7 +119,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mItemHeight(p.item_height), mPassedFilter(FALSE), mLastFilterGeneration(-1), - mStringMatchOffset(std::string::npos), + //TODO RN: create interface for string highlighting + //mStringMatchOffset(std::string::npos), mControlLabelRotation(0.f), mDragAndDropTarget(FALSE), mLabel(p.name), @@ -218,7 +218,7 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) BOOL LLFolderViewItem::potentiallyVisible() { return getFiltered() // we've passed the filter - || getLastFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration()); // or we don't know yet + || getLastFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration(); // or we don't know yet } BOOL LLFolderViewItem::getFiltered() @@ -244,45 +244,17 @@ void LLFolderViewItem::setIcon(LLUIImagePtr icon) void LLFolderViewItem::refresh() { - if(!getListener()) return; + if(!getViewModelItem()) return; - mLabel = getListener()->getDisplayName(); - LLFolderType::EType preferred_type = getListener()->getPreferredType(); + mLabel = getViewModelItem()->getDisplayName(); - // *TODO: to be removed when database supports multi language. This is a - // temporary attempt to display the inventory folder in the user locale. - // mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID - // it uses the same way to find localized string - - // HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) - // Translation of Accessories folder in Library inventory folder - bool accessories = false; - if(mLabel == std::string("Accessories")) - { - //To ensure that Accessories folder is in Library we have to check its parent folder. - //Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model - LLInventoryCategory* cat = gInventory.getCategory(getListener()->getUUID()); - if(cat) - { - const LLUUID& parent_folder_id = cat->getParentUUID(); - accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); - } - } - - //"Accessories" inventory category has folder type FT_NONE. So, this folder - //can not be detected as protected with LLFolderType::lookupIsProtectedType - if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) - { - LLTrans::findString(mLabel, "InvFolder " + mLabel); - }; - - setToolTip(mLabel); - setIcon(getListener()->getIcon()); - if (mRoot->useLabelSuffix()) - { - mLabelStyle = getListener()->getLabelStyle(); - mLabelSuffix = getListener()->getLabelSuffix(); -} + setToolTip(mLabel); + setIcon(getViewModelItem()->getIcon()); + if (mRoot->useLabelSuffix()) + { + mLabelStyle = getViewModelItem()->getLabelStyle(); + mLabelSuffix = getViewModelItem()->getLabelSuffix(); + } std::string searchable_label(mLabel); searchable_label.append(mLabelSuffix); @@ -381,7 +353,6 @@ BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) return FALSE; } mParentFolder = folder; - root->addItemID(getListener()->getUUID(), this); return folder->addItem(this); } @@ -420,7 +391,7 @@ S32 LLFolderViewItem::getItemHeight() return mItemHeight; } -void LLFolderViewItem::filter( LLInventoryFilter& filter) +void LLFolderViewItem::filter( LLFolderViewFilter& filter) { const BOOL previous_passed_filter = mPassedFilter; const BOOL passed_filter = filter.check(this); @@ -435,7 +406,8 @@ void LLFolderViewItem::filter( LLInventoryFilter& filter) } setFiltered(passed_filter, filter.getCurrentGeneration()); - mStringMatchOffset = filter.getStringMatchOffset(this); + //TODO RN: create interface for string highlighting + //mStringMatchOffset = filter.getStringMatchOffset(this); filter.decrementFilterCount(); if (getRoot()->getDebugFilters()) @@ -498,9 +470,9 @@ void LLFolderViewItem::selectItem(void) { if (mIsSelected == FALSE) { - if (getListener()) + if (getViewModelItem()) { - getListener()->selectItem(); + getViewModelItem()->selectItem(); } mIsSelected = TRUE; } @@ -508,9 +480,9 @@ void LLFolderViewItem::selectItem(void) BOOL LLFolderViewItem::isMovable() { - if( getListener() ) + if( getViewModelItem() ) { - return getListener()->isItemMovable(); + return getViewModelItem()->isItemMovable(); } else { @@ -520,9 +492,9 @@ BOOL LLFolderViewItem::isMovable() BOOL LLFolderViewItem::isRemovable() { - if( getListener() ) + if( getViewModelItem() ) { - return getListener()->isItemRemovable(); + return getViewModelItem()->isItemRemovable(); } else { @@ -548,9 +520,9 @@ BOOL LLFolderViewItem::remove() { return FALSE; } - if(getListener()) + if(getViewModelItem()) { - return getListener()->removeItem(); + return getViewModelItem()->removeItem(); } return TRUE; } @@ -558,25 +530,17 @@ BOOL LLFolderViewItem::remove() // Build an appropriate context menu for the item. void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) { - if(getListener()) + if(getViewModelItem()) { - getListener()->buildContextMenu(menu, flags); + getViewModelItem()->buildContextMenu(menu, flags); } } void LLFolderViewItem::openItem( void ) { - if( getListener() ) + if( getViewModelItem() ) { - getListener()->openItem(); - } -} - -void LLFolderViewItem::preview( void ) -{ - if (getListener()) - { - getListener()->previewItem(); + getViewModelItem()->openItem(); } } @@ -584,9 +548,9 @@ void LLFolderViewItem::rename(const std::string& new_name) { if( !new_name.empty() ) { - if( getListener() ) + if( getViewModelItem() ) { - getListener()->renameItem(new_name); + getViewModelItem()->renameItem(new_name); if(mParentFolder) { @@ -601,19 +565,13 @@ const std::string& LLFolderViewItem::getSearchableLabel() const return mSearchableLabel; } -LLViewerInventoryItem * LLFolderViewItem::getInventoryItem(void) -{ - if (!getListener()) return NULL; - return gInventory.getItem(getListener()->getUUID()); -} - const std::string& LLFolderViewItem::getName( void ) const { - if(getListener()) + if(getViewModelItem()) { - return getListener()->getName(); + return getViewModelItem()->getName(); } - return z; + return LLStringUtil::null; } // LLView functionality @@ -689,9 +647,9 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) // *TODO: push this into listener and remove // dependency on llagent - if (getListener()) + if (getViewModelItem()) { - src = getListener()->getDragSource(); + src = getViewModelItem()->getDragSource(); } else { @@ -701,7 +659,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) can_drag = root->startDrag(src); if (can_drag) { - // if (getListener()) getListener()->startDrag(); + // if (getViewModelItem()) getViewModelItem()->startDrag(); // RN: when starting drag and drop, clear out last auto-open root->autoOpenTest(NULL); root->setShowSelectionContext(TRUE); @@ -738,7 +696,10 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) { - preview(); + if (getViewModelItem()) + { + getViewModelItem()->openItem(); + } return TRUE; } @@ -790,9 +751,9 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, { BOOL accepted = FALSE; BOOL handled = FALSE; - if(getListener()) + if(getViewModelItem()) { - accepted = getListener()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); handled = accepted; if (accepted) { @@ -838,15 +799,12 @@ void LLFolderViewItem::draw() const S32 FOCUS_LEFT = 1; const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - getListener()->update(); + getViewModelItem()->update(); //--------------------------------------------------------------------------------// // Draw open folder arrow // - const bool up_to_date = getListener() && getListener()->isUpToDate(); - const bool possibly_has_children = ((up_to_date && hasVisibleChildren()) // we fetched our children and some of them have passed the filter... - || (!up_to_date && getListener() && getListener()->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter) - if (possibly_has_children) + if (hasVisibleChildren() || getViewModelItem()->hasChildren()) { LLUIImage* arrow_image = default_params.folder_arrow_image; gl_draw_scaled_rotated_image( @@ -943,25 +901,27 @@ void LLFolderViewItem::draw() mDragAndDropTarget = FALSE; } - const LLViewerInventoryItem *item = getInventoryItem(); - const BOOL highlight_link = mIconOverlay && item && item->getIsLinkType(); - //--------------------------------------------------------------------------------// - // Draw open icon - // - const S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; - if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders - { - mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); - } - else if (mIcon) - { - mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - } + //TODO RN: implement this in terms of getIcon() and getIconOverlay() - if (highlight_link) - { - mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - } + //const LLViewerInventoryItem *item = getInventoryItem(); + //const BOOL highlight_link = mIconOverlay && item && item->getIsLinkType(); + ////--------------------------------------------------------------------------------// + //// Draw open icon + //// + //const S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; + //if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders + // { + // mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); + //} + //else if (mIcon) + //{ + // mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + // } + + //if (highlight_link) + //{ + // mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + //} //--------------------------------------------------------------------------------// // Exit if no label to draw @@ -972,8 +932,9 @@ void LLFolderViewItem::draw() } LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; - if (highlight_link) color = sLinkColor; - if (in_library) color = sLibraryColor; + //TODO RN: implement this in terms of getColor() + //if (highlight_link) color = sLinkColor; + //if (getViewModelItem() && gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; F32 right_x = 0; F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; @@ -984,7 +945,7 @@ void LLFolderViewItem::draw() // if (getRoot()->getDebugFilters()) { - if (!getFiltered() && !possibly_has_children) + if (!getFiltered() && !getViewModelItem()->hasChildren()) { color.mV[VALPHA] *= 0.5f; } @@ -1016,7 +977,7 @@ void LLFolderViewItem::draw() //--------------------------------------------------------------------------------// // Highlight string match // - RN: expose interface for highlighting + //TODO RN: expose interface for highlighting //if (mStringMatchOffset != std::string::npos) //{ // // don't draw backgrounds for zero-length strings @@ -1098,7 +1059,7 @@ static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) { // sort before laying out contents - getRoot->getViewModel()->sort(this); + getRoot()->getFolderViewModel()->sort(this); LLFastTimer t2(FTM_ARRANGE); @@ -1122,8 +1083,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) { LLFolderViewFolder* folderp = (*fit); - found = ( folderp->getListener() - && (folderp->getFiltered(filter_generation) + found = ( (folderp->getFiltered(filter_generation) || (folderp->getFilteredFolder(filter_generation) && folderp->hasFilteredDescendants(filter_generation)))); if (found) @@ -1164,10 +1124,9 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) } else { - folderp->setVisible( folderp->getListener() - && (folderp->getFiltered(filter_generation) + folderp->setVisible( folderp->getFiltered(filter_generation) || (folderp->getFilteredFolder(filter_generation) - && folderp->hasFilteredDescendants(filter_generation)))); // passed filter or has descendants that passed filter + && folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter } if (folderp->getVisible()) @@ -1277,7 +1236,7 @@ BOOL LLFolderViewFolder::needsArrange() void LLFolderViewFolder::requestSort() { - getRoot()->getViewModel()->requestSort(this); + getRoot()->getFolderViewModel()->requestSort(this); } void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up) @@ -1293,7 +1252,7 @@ void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recur } } -void LLFolderViewFolder::filter( LLInventoryFilter& filter) +void LLFolderViewFolder::filter( LLFolderViewFilter& filter) { S32 filter_generation = filter.getCurrentGeneration(); // if failed to pass filter newer than must_pass_generation @@ -1301,7 +1260,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) // check against items that have passed the filter S32 must_pass_generation = filter.getFirstRequiredGeneration(); - bool autoopen_folders = (filter.hasFilterString()); + bool autoopen_folders = filter.showAllResults(); // if we have already been filtered against this generation, skip out if (getCompletedFilterGeneration() >= filter_generation) @@ -1317,7 +1276,8 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) { // go ahead and flag this folder as done mLastFilterGeneration = filter_generation; - mStringMatchOffset = std::string::npos; + //TODO RN: create interface for string highlighting + //mStringMatchOffset = std::string::npos; } else // filter self only on first pass through { @@ -1351,15 +1311,6 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) return; } - // when applying a filter, matching folders get their contents downloaded first - if (filter.isNotDefault() - && getFiltered(filter.getFirstSuccessGeneration()) - && (getListener() - && !gInventory.isCategoryComplete(getListener()->getUUID()))) - { - LLInventoryModelBackgroundFetch::instance().start(getListener()->getUUID()); - } - // now query children for (folders_t::iterator iter = mFolders.begin(); iter != mFolders.end(); @@ -1449,7 +1400,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) } } -void LLFolderViewFolder::filterFolder(LLInventoryFilter& filter) +void LLFolderViewFolder::filterFolder(LLFolderViewFilter& filter) { const BOOL previous_passed_filter = mPassedFolderFilter; const BOOL passed_filter = filter.checkFolder(this); @@ -1944,9 +1895,9 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) BOOL LLFolderViewFolder::isMovable() { - if( getListener() ) + if( getViewModelItem() ) { - if( !(getListener()->isItemMovable()) ) + if( !(getViewModelItem()->isItemMovable()) ) { return FALSE; } @@ -1977,9 +1928,9 @@ BOOL LLFolderViewFolder::isMovable() BOOL LLFolderViewFolder::isRemovable() { - if( getListener() ) + if( getViewModelItem() ) { - if( !(getListener()->isItemRemovable()) ) + if( !(getViewModelItem()->isItemRemovable()) ) { return FALSE; } @@ -2023,7 +1974,7 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) requestArrange(); requestSort(); - FIXME: RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria + //TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria //// Traverse parent folders and update creation date and resort, if necessary //LLFolderViewFolder* parentp = this; //while (parentp) @@ -2052,16 +2003,7 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) // rearrange all descendants too, as our indentation level might have changed folder->requestArrange(TRUE); requestSort(); - if (getRoot()->getSortFunction().isByDate()) - { - LLFolderViewFolder* parentp = getParentFolder(); - while(parentp) - { - // parent folder doesn't have a time stamp yet, so get it from us - parentp->requestSort(); - parentp = parentp->getParentFolder(); - } - } + return TRUE; } @@ -2100,15 +2042,15 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r { BOOL was_open = isOpen(); mIsOpen = openitem; - if (getListener()) + if (getViewModelItem()) { if(!was_open && openitem) { - getListener()->openItem(); + getViewModelItem()->openItem(); } else if(was_open && !openitem) { - getListener()->closeItem(); + getViewModelItem()->closeItem(); } } @@ -2229,7 +2171,7 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = getListener() && getListener()->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); + BOOL accepted = getViewModelItem() && getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); if (accepted) { @@ -2253,9 +2195,6 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) { BOOL handled = FALSE; - // fetch contents of this folder, as context menu can depend on contents - // still, user would have to open context menu again to see the changes - gInventory.fetchDescendentsOf(getListener()->getUUID()); if( isOpen() ) { @@ -2311,11 +2250,11 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) { /* Disable outfit double click to wear - const LLUUID &cat_uuid = getListener()->getUUID(); + const LLUUID &cat_uuid = getViewModelItem()->getUUID(); const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid); if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) { - getListener()->performAction(NULL, NULL,"replaceoutfit"); + getViewModelItem()->performAction(NULL, NULL,"replaceoutfit"); return TRUE; } */ @@ -2594,30 +2533,31 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, { // ignore sort order for landmarks in the Favorites folder. // they should be always sorted as in Favorites bar. See EXT-719 - if (a->getSortGroup() == SG_ITEM - && b->getSortGroup() == SG_ITEM - && a->getInventoryType() == LLInventoryType::IT_LANDMARK - && b->getInventoryType() == LLInventoryType::IT_LANDMARK) - { + //TODO RN: fix sorting in favorites folder + //if (a->getSortGroup() == SG_ITEM + // && b->getSortGroup() == SG_ITEM + // && a->getInventoryType() == LLInventoryType::IT_LANDMARK + // && b->getInventoryType() == LLInventoryType::IT_LANDMARK) + //{ - static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + // static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - LLUUID a_uuid = a->getParentFolder()->getUUID(); - LLUUID b_uuid = b->getParentFolder()->getUUID(); + // LLUUID a_uuid = a->getParentFolder()->getUUID(); + // LLUUID b_uuid = b->getParentFolder()->getUUID(); - if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) - { - // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem - // or to LLInvFVBridge - LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a))->getItem(); - LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b))->getItem(); - if (!aitem || !bitem) - return false; - S32 a_sort = aitem->getSortField(); - S32 b_sort = bitem->getSortField(); - return a_sort < b_sort; - } - } + // if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) + // { + // // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem + // // or to LLInvFVBridge + // LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a))->getItem(); + // LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b))->getItem(); + // if (!aitem || !bitem) + // return false; + // S32 a_sort = aitem->getSortField(); + // S32 b_sort = bitem->getSortField(); + // return a_sort < b_sort; + // } + //} // We sort by name if we aren't sorting by date // OR if these are folders and we are sorting folders by name. @@ -2645,7 +2585,7 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, if (by_name) { - S32 compare = LLStringUtil::compareDict(a->getLabel(), b->getLabel()); + S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); if (0 == compare) { return (a->getCreationDate() > b->getCreationDate()); @@ -2661,7 +2601,7 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, time_t second_create = b->getCreationDate(); if (first_create == second_create) { - return (LLStringUtil::compareDict(a->getLabel(), b->getLabel()) < 0); + return (LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()) < 0); } else { diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index b7588223da..7bcc9dd0a2 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -31,11 +31,10 @@ #include "lluiimage.h" class LLFolderView; -class LLFolderViewModelItemInventory; +class LLFolderViewModelItem; class LLFolderViewFolder; class LLFolderViewFunctor; -class LLInventoryFilter; -class LLViewerInventoryItem; +class LLFolderViewFilter; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderViewItem @@ -57,8 +56,8 @@ public: icon_overlay, // for links folder_arrow_image, selection_image; - Optional<LLFolderView*> root; - Mandatory<LLFolderViewModelItemInventory*> listener; + Optional<LLFolderView*> root; + Mandatory<LLFolderViewModelItem*> listener; Optional<S32> folder_indentation, // pixels item_height, @@ -98,7 +97,7 @@ protected: S32 mLabelWidth; bool mLabelWidthDirty; LLFolderViewFolder* mParentFolder; - LLFolderViewModelItemInventory* mListener; + LLFolderViewModelItem* mListener; BOOL mIsCurSelection; BOOL mSelectPending; LLFontGL::StyleFlags mLabelStyle; @@ -112,7 +111,8 @@ protected: S32 mItemHeight; BOOL mPassedFilter; S32 mLastFilterGeneration; - std::string::size_type mStringMatchOffset; + //TODO RN: create interface for string highlighting + //std::string::size_type mStringMatchOffset; F32 mControlLabelRotation; LLFolderView* mRoot; BOOL mDragAndDropTarget; @@ -159,8 +159,8 @@ public: virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); virtual S32 getItemHeight(); - // applies filters to control visibility of inventory items - virtual void filter( LLInventoryFilter& filter); + // applies filters to control visibility of items + virtual void filter( LLFolderViewFilter& filter); // updates filter serial number and optionally propagated value up to root S32 getLastFilterGeneration() { return mLastFilterGeneration; } @@ -230,8 +230,8 @@ public: LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); - const LLFolderViewModelItemInventory* getListener( void ) const { return mListener; } - LLFolderViewModelItemInventory* getListener( void ) { return mListener; } + const LLFolderViewModelItem* getViewModelItem( void ) const { return mListener; } + LLFolderViewModelItem* getViewModelItem( void ) { return mListener; } // just rename the object. void rename(const std::string& new_name); @@ -277,41 +277,10 @@ public: EAcceptance* accept, std::string& tooltip_msg); - // Gets the inventory item if it exists (null otherwise) - LLViewerInventoryItem * getInventoryItem(void); - // open - virtual void preview(void); - private: static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts }; -class LLInventorySort -{ -public: - LLInventorySort(U32 order) - : mSortOrder(0), - mByDate(false), - mSystemToTop(false), - mFoldersByName(false) - { - mSortOrder = order; - mByDate = (order & LLInventoryFilter::SO_DATE); - mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); - mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); - } - - bool isByDate() { return mByDate; } - U32 getSortOrder() { return mSortOrder; } - - bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b); -private: - U32 mSortOrder; - bool mByDate; - bool mSystemToTop; - bool mFoldersByName; -}; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderViewFolder // @@ -379,8 +348,8 @@ public: BOOL hasFilteredDescendants(S32 filter_generation); BOOL hasFilteredDescendants(); - // applies filters to control visibility of inventory items - virtual void filter( LLInventoryFilter& filter); + // applies filters to control visibility of items + virtual void filter( LLFolderViewFilter& filter); virtual void setFiltered(BOOL filtered, S32 filter_generation); virtual BOOL getFiltered(); virtual BOOL getFiltered(S32 filter_generation); @@ -388,7 +357,7 @@ public: virtual void dirtyFilter(); // folder-specific filtering (filter status propagates top down instead of bottom up) - void filterFolder(LLInventoryFilter& filter); + void filterFolder(LLFolderViewFilter& filter); void setFilteredFolder(bool filtered, S32 filter_generation); bool getFilteredFolder(S32 filter_generation); @@ -496,12 +465,12 @@ public: virtual void draw(); - folders_t::iterator getFoldersBegin() const { return mFolders.begin(); } - folders_t::iterator getFoldersEnd() const { return mFolders.end(); } + folders_t::iterator getFoldersBegin() { return mFolders.begin(); } + folders_t::iterator getFoldersEnd() { return mFolders.end(); } folders_t::size_type getFoldersCount() const { return mFolders.size(); } - items_t::iterator getItemsBegin() const { return mItems.begin(); } - items_t::iterator getItemsEnd() const { return mItems.end(); } + items_t::const_iterator getItemsBegin() const { return mItems.begin(); } + items_t::const_iterator getItemsEnd() const { return mItems.end(); } items_t::size_type getItemsCount() const { return mItems.size(); } LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h new file mode 100644 index 0000000000..b81a81f837 --- /dev/null +++ b/indra/newview/llfolderviewmodel.h @@ -0,0 +1,313 @@ +/** + * @file llfolderviewmodel.h + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LLFOLDERVIEWEVENTLISTENER_H +#define LLFOLDERVIEWEVENTLISTENER_H + +#include "lldarray.h" // *TODO: convert to std::vector +#include "llfoldertype.h" +#include "llfontgl.h" // just for StyleFlags enum +#include "llfolderviewitem.h" +#include "llinventorytype.h" +#include "llpermissionsflags.h" +#include "llpointer.h" +#include "llwearabletype.h" +#include "lltooldraganddrop.h" + +// These are grouping of inventory types. +// Order matters when sorting system folders to the top. +enum EInventorySortGroup +{ + SG_SYSTEM_FOLDER, + SG_TRASH_FOLDER, + SG_NORMAL_FOLDER, + SG_ITEM +}; + +class LLFontGL; +class LLInventoryModel; +class LLMenuGL; +class LLUIImage; +class LLUUID; +class LLFolderViewItem; +class LLFolderViewFolder; + +class LLFolderViewFilter +{ +public: + enum EFilterBehavior + { + FILTER_NONE, // nothing to do, already filtered + FILTER_RESTART, // restart filtering from scratch + FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter + FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one + }; + +public: + + LLFolderViewFilter() {} + virtual ~LLFolderViewFilter() {} + + // +-------------------------------------------------------------------+ + // + Execution And Results + // +-------------------------------------------------------------------+ + virtual bool check(const LLFolderViewItem* item) = 0; + virtual bool check(const LLInventoryItem* item) = 0; + virtual bool checkFolder(const LLFolderViewFolder* folder) const = 0; + virtual bool checkFolder(const LLUUID& folder_id) const = 0; + + virtual void setEmptyLookupMessage(const std::string& message) = 0; + const virtual std::string& getEmptyLookupMessage() const = 0; + + virtual bool showAllResults() const = 0; + + // +-------------------------------------------------------------------+ + // + Status + // +-------------------------------------------------------------------+ + virtual bool isActive() const = 0; + virtual bool isModified() const = 0; + virtual bool isModifiedAndClear() = 0; + virtual void clearModified() = 0; + virtual const std::string& getName() const = 0; + virtual const std::string& getFilterText() = 0; + //RN: this is public to allow system to externally force a global refilter + virtual void setModified(EFilterBehavior behavior = FILTER_RESTART) = 0; + + // +-------------------------------------------------------------------+ + // + Count + // +-------------------------------------------------------------------+ + virtual void setFilterCount(S32 count) = 0; + virtual S32 getFilterCount() const = 0; + virtual void decrementFilterCount() = 0; + + // +-------------------------------------------------------------------+ + // + Default + // +-------------------------------------------------------------------+ + virtual bool isDefault() const = 0; + virtual bool isNotDefault() const = 0; + virtual void markDefault() = 0; + virtual void resetDefault() = 0; + + // +-------------------------------------------------------------------+ + // + Generation + // +-------------------------------------------------------------------+ + virtual S32 getCurrentGeneration() const = 0; + virtual S32 getFirstSuccessGeneration() const = 0; + virtual S32 getFirstRequiredGeneration() const = 0; +}; + +class LLFolderViewModelInterface +{ +public: + virtual void requestSortAll() = 0; + virtual void requestSort(class LLFolderViewFolder*) = 0; + + virtual void sort(class LLFolderViewFolder*) = 0; + virtual void filter(class LLFolderViewFolder*) = 0; +}; + +struct LLFolderViewModelCommon : public LLFolderViewModelInterface +{ + LLFolderViewModelCommon() + : mTargetSortVersion(0) + {} + + virtual void requestSortAll() + { + // sort everything + mTargetSortVersion++; + } + + virtual void requestSort(class LLFolderViewFolder* folder) + { + folder->requestSort(); + } + +protected: + bool needsSort(class LLFolderViewModelItem* item); + + S32 mTargetSortVersion; +}; + +// This is am abstract base class that users of the folderview classes +// would use to bridge the folder view with the underlying data +class LLFolderViewModelItem +{ +public: + virtual ~LLFolderViewModelItem( void ) {}; + + virtual void update() {} //called when drawing + virtual const std::string& getName() const = 0; + virtual const std::string& getDisplayName() const = 0; + + virtual LLPointer<LLUIImage> getIcon() const = 0; + virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } + + virtual LLFontGL::StyleFlags getLabelStyle() const = 0; + virtual std::string getLabelSuffix() const = 0; + + virtual void openItem( void ) = 0; + virtual void closeItem( void ) = 0; + virtual void selectItem(void) = 0; + + virtual BOOL isItemRenameable() const = 0; + virtual BOOL renameItem(const std::string& new_name) = 0; + + virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder + virtual void move( LLFolderViewModelItem* parent_listener ) = 0; + + virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed + virtual BOOL removeItem() = 0; + virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0; + + virtual BOOL isItemCopyable() const = 0; + virtual BOOL copyToClipboard() const = 0; + virtual BOOL cutToClipboard() const = 0; + + virtual BOOL isClipboardPasteable() const = 0; + virtual void pasteFromClipboard() = 0; + virtual void pasteLinkFromClipboard() = 0; + + virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; + + // This method should be called when a drag begins. returns TRUE + // if the drag can begin, otherwise FALSE. + virtual LLToolDragAndDrop::ESource getDragSource() const = 0; + virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; + + virtual bool hasChildren() const = 0; + + // This method will be called to determine if a drop can be + // performed, and will set drop to TRUE if a drop is + // requested. Returns TRUE if a drop is possible/happened, + // otherwise FALSE. + virtual BOOL dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + std::string& tooltip_msg) = 0; + + virtual void requestSort() = 0; + virtual S32 getSortVersion() = 0; + virtual void setSortVersion(S32 version) = 0; +}; + +class LLFolderViewModelItemCommon : public LLFolderViewModelItem +{ +public: + LLFolderViewModelItemCommon() + : mSortVersion(-1) + {} + + void requestSort() { mSortVersion = -1; } + S32 getSortVersion() { return mSortVersion; } + void setSortVersion(S32 version) { mSortVersion = version;} + +protected: + S32 mSortVersion; +}; + +template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE> +class LLFolderViewModel : public LLFolderViewModelCommon +{ +protected: + LLFolderViewModel() {} + virtual ~LLFolderViewModel() {} + + typedef SORT_TYPE SortType; + typedef ITEM_TYPE ItemType; + typedef FOLDER_TYPE FolderType; + typedef FILTER_TYPE FilterType; + + virtual const SortType& getSorter() const { return mSorter; } + virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } + virtual FilterType& getFilter() { return mFilter; } + virtual void setFilter(const FilterType& filter) { mFilter = filter; } + +public: + + struct ViewModelCompare + { + ViewModelCompare(const SortType& sorter) + : mSorter(sorter) + {} + + int operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) + { + return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); + } + + int operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) + { + return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); + } + + const SortType& mSorter; + }; + + void sort(LLFolderViewFolder* folder) + { + if (needsSort(folder->getViewModelItem())) + { + std::sort(folder->getFoldersBegin(), folder->getFoldersEnd(), ViewModelCompare(getSorter())); + std::sort(folder->getItemsBegin(), folder->getItemsEnd(), ViewModelCompare(getSorter())); + folder->getViewModelItem()->setSortVersion(mTargetSortVersion); + folder->requestArrange(); + } + } + + //TODO RN: fix this + void filter(LLFolderViewFolder* folder) + { + /*FilterType& filter = getFilter(); + for (std::list<LLFolderViewItem*>::const_iterator it = folder->getItemsBegin(), end_it = folder->getItemsEnd(); + it != end_it; + ++it) + { + LLFolderViewItem* child_item = *it; + child_item->setFiltered(filter.checkFolder(static_cast<ItemType*>(child_item->getViewModelItem())), filter.getCurrentGeneration()); + } + + for (std::list<LLFolderViewFolder*>::const_iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); + it != end_it; + ++it) + { + LLFolderViewItem* child_folder = *it; + child_folder->setFiltered(filter.check(static_cast<ItemType*>(child_folder->getViewModelItem())), filter.getCurrentGeneration()); + }*/ + } + +protected: + SortType mSorter; + FilterType mFilter; +}; + + +bool LLFolderViewModelCommon::needsSort(class LLFolderViewModelItem* item) +{ + return item->getSortVersion() < mTargetSortVersion; +} + + + +#endif diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index d0d2215361..b51bbf7bfe 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -208,7 +208,11 @@ const std::string& LLInvFVBridge::getName() const const std::string& LLInvFVBridge::getDisplayName() const { - return getName(); + if(mDisplayName.empty()) + { + buildDisplayName(); + } + return mDisplayName; } // Folders have full perms @@ -1292,7 +1296,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const void * cargo_data = (void *) obj; std::string tooltip_msg; - can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); + can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); } } } @@ -1407,7 +1411,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) LLFolderViewItem* folder_view_itemp = mInventoryPanel.get()->getItemByID(itemp->getParentUUID()); if (!folder_view_itemp) return; - folder_view_itemp->getListener()->pasteFromClipboard(); + folder_view_itemp->getViewModelItem()->pasteFromClipboard(); return; } else if ("paste_link" == action) @@ -1419,7 +1423,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) LLFolderViewItem* folder_view_itemp = mInventoryPanel.get()->getItemByID(itemp->getParentUUID()); if (!folder_view_itemp) return; - folder_view_itemp->getListener()->pasteLinkFromClipboard(); + folder_view_itemp->getViewModelItem()->pasteLinkFromClipboard(); return; } else if (isMarketplaceCopyAction(action)) @@ -1530,24 +1534,15 @@ PermissionMask LLItemBridge::getPermissionMask() const return perm_mask; } -const std::string& LLItemBridge::getDisplayName() const +void LLItemBridge::buildDisplayName() { - if(mDisplayName.empty()) + if(getItem()) { - buildDisplayName(getItem(), mDisplayName); - } - return mDisplayName; -} - -void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) -{ - if(item) - { - name.assign(item->getName()); + mDisplayName.assign(getItem()->getName()); } else { - name.assign(LLStringUtil::null); + mDisplayName.assign(LLStringUtil::null); } } @@ -1665,11 +1660,11 @@ BOOL LLItemBridge::renameItem(const std::string& new_name) { LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); new_item->rename(new_name); - buildDisplayName(new_item, mDisplayName); new_item->updateServer(FALSE); model->updateItem(new_item); model->notifyObservers(); + buildDisplayName(); } // return FALSE because we either notified observers (& therefore // rebuilt) or we didn't update. @@ -1821,9 +1816,37 @@ void LLFolderBridge::selectItem() // Have no fear: the first thing start() does is to test if everything for that folder has been fetched... LLInventoryModelBackgroundFetch::instance().start(getUUID(), true); } -std::string& LLFolderBridge::getDisplayName() const + +void LLFolderBridge::buildDisplayName() { - return mDisplayName; + LLFolderType::EType preferred_type = getPreferredType(); + + // *TODO: to be removed when database supports multi language. This is a + // temporary attempt to display the inventory folder in the user locale. + // mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID + // it uses the same way to find localized string + + // HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) + // Translation of Accessories folder in Library inventory folder + bool accessories = false; + if(getName() == "Accessories") + { + //To ensure that Accessories folder is in Library we have to check its parent folder. + //Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model + LLInventoryCategory* cat = gInventory.getCategory(getUUID()); + if(cat) + { + const LLUUID& parent_folder_id = cat->getParentUUID(); + accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); + } + } + + //"Accessories" inventory category has folder type FT_NONE. So, this folder + //can not be detected as protected with LLFolderType::lookupIsProtectedType + if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) + { + LLTrans::findString(mDisplayName, "InvFolder " + getName()); + }; } @@ -1884,11 +1907,11 @@ public: LLIsItemRemovable() : mPassed(TRUE) {} virtual void doFolder(LLFolderViewFolder* folder) { - mPassed &= folder->getListener()->isItemRemovable(); + mPassed &= folder->getViewModelItem()->isItemRemovable(); } virtual void doItem(LLFolderViewItem* item) { - mPassed &= item->getListener()->isItemRemovable(); + mPassed &= item->getViewModelItem()->isItemRemovable(); } BOOL mPassed; }; @@ -3084,7 +3107,7 @@ void LLFolderBridge::pasteFromClipboard() void * cargo_data = (void *) item; std::string tooltip_msg; - can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); + can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); } } @@ -3494,6 +3517,11 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { sSelf.markDead(); + // fetch contents of this folder, as context menu can depend on contents + // still, user would have to open context menu again to see the changes + gInventory.fetchDescendentsOf(getUUID()); + + menuentry_vec_t items; menuentry_vec_t disabled_items; @@ -3510,7 +3538,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) menu.arrangeAndClear(); } -BOOL LLFolderBridge::hasChildren() const +bool LLFolderBridge::hasChildren() const { LLInventoryModel* model = getInventoryModel(); if(!model) return FALSE; @@ -3802,9 +3830,9 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item) LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback(); LLInventoryPanel* panel = mInventoryPanel.get(); LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; - if (drag_over_item && drag_over_item->getListener()) + if (drag_over_item && drag_over_item->getViewModelItem()) { - cb.get()->setTargetLandmarkId(drag_over_item->getListener()->getUUID()); + cb.get()->setTargetLandmarkId(drag_over_item->getViewModelItem()->getUUID()); } copy_inventory_item( @@ -4004,7 +4032,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, if (itemp) { LLUUID srcItemId = inv_item->getUUID(); - LLUUID destItemId = itemp->getListener()->getUUID(); + LLUUID destItemId = itemp->getViewModelItem()->getUUID(); gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); } } @@ -4394,15 +4422,6 @@ void LLSoundBridge::openItem() } } -void LLSoundBridge::previewItem() -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - send_sound_trigger(item->getAssetUUID(), 1.0); - } -} - void LLSoundBridge::openSoundPreview(void* which) { LLSoundBridge *me = (LLSoundBridge *)which; @@ -5409,11 +5428,10 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name) { LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); new_item->rename(new_name); - buildDisplayName(new_item, mDisplayName); new_item->updateServer(FALSE); model->updateItem(new_item); - model->notifyObservers(); + buildDisplayName(); if (isAgentAvatarValid()) { @@ -6013,16 +6031,6 @@ void LLMeshBridge::openItem() } } -void LLMeshBridge::previewItem() -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - // preview mesh - } -} - - void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { lldebugs << "LLMeshBridge::buildContextMenu()" << llendl; diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 114144c8a4..bc5ac24c70 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -29,7 +29,7 @@ #include "llcallingcard.h" #include "llfloaterproperties.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" #include "llinventorymodel.h" #include "llinventoryobserver.h" #include "llinventorypanel.h" @@ -96,7 +96,6 @@ public: virtual std::string getLabelSuffix() const { return LLStringUtil::null; } virtual void openItem() {} virtual void closeItem() {} - virtual void previewItem() {openItem();} virtual void showProperties(); virtual BOOL isItemRenameable() const { return TRUE; } //virtual BOOL renameItem(const std::string& new_name) {} @@ -126,6 +125,8 @@ public: virtual LLInventoryType::EType getInventoryType() const { return mInvType; } virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } EInventorySortGroup getSortGroup() const { return SG_ITEM; } + virtual LLInventoryObject* getInventoryObject() const; + //-------------------------------------------------------------------- // Convenience functions for adding various common menu options. @@ -142,7 +143,6 @@ protected: protected: LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid); - LLInventoryObject* getInventoryObject() const; LLInventoryModel* getInventoryModel() const; LLInventoryFilter* getInventoryFilter() const; @@ -167,13 +167,16 @@ protected: BOOL restamp); void removeBatchNoCheck(std::vector<LLFolderViewModelItem*>& batch); protected: - LLHandle<LLInventoryPanel> mInventoryPanel; - LLFolderView* mRoot; - const LLUUID mUUID; // item id - LLInventoryType::EType mInvType; + LLHandle<LLInventoryPanel> mInventoryPanel; + LLFolderView* mRoot; + const LLUUID mUUID; // item id + LLInventoryType::EType mInvType; bool mIsLink; LLTimer mTimeSinceRequestStart; + mutable std::string mDisplayName; + void purgeItem(LLInventoryModel *model, const LLUUID &uuid); + virtual void buildDisplayName(); }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -209,7 +212,6 @@ public: virtual void restoreToWorld(); virtual void gotoItem(); virtual LLUIImagePtr getIcon() const; - virtual const std::string& getDisplayName() const; virtual std::string getLabelSuffix() const; virtual LLFontGL::StyleFlags getLabelStyle() const; virtual PermissionMask getPermissionMask() const; @@ -218,7 +220,7 @@ public: virtual BOOL renameItem(const std::string& new_name); virtual BOOL removeItem(); virtual BOOL isItemCopyable() const; - virtual BOOL hasChildren() const { return FALSE; } + virtual bool hasChildren() const { return FALSE; } virtual BOOL isUpToDate() const { return TRUE; } /*virtual*/ void clearDisplayName() { mDisplayName.clear(); } @@ -228,9 +230,8 @@ public: protected: BOOL confirmRemoveItem(const LLSD& notification, const LLSD& response); virtual BOOL isItemPermissive() const; - static void buildDisplayName(LLInventoryItem* item, std::string& name); + virtual void buildDisplayName(); - mutable std::string mDisplayName; }; class LLFolderBridge : public LLInvFVBridge @@ -248,7 +249,7 @@ public: BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg); BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg); - const std::string& getDisplayName() const; + virtual void buildDisplayName(); virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem(); @@ -271,7 +272,7 @@ public: virtual void pasteFromClipboard(); virtual void pasteLinkFromClipboard(); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); - virtual BOOL hasChildren() const; + virtual bool hasChildren() const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, @@ -331,6 +332,7 @@ public: static void staticFolderOptionsMenu(); private: + bool mCallingCards; bool mWearables; bool mIsLoading; @@ -365,7 +367,6 @@ public: const LLUUID& uuid) : LLItemBridge(inventory, root, uuid) {} virtual void openItem(); - virtual void previewItem(); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); static void openSoundPreview(void*); }; @@ -555,7 +556,6 @@ class LLMeshBridge : public LLItemBridge public: virtual LLUIImagePtr getIcon() const; virtual void openItem(); - virtual void previewItem(); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); protected: diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 5de3f0cb4e..1d25a7a1f9 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -29,7 +29,7 @@ #include "llinventoryfilter.h" // viewer includes -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" #include "llfolderviewitem.h" #include "llinventorymodel.h" #include "llinventorymodelbackgroundfetch.h" @@ -92,7 +92,7 @@ LLInventoryFilter::~LLInventoryFilter() BOOL LLInventoryFilter::check(const LLFolderViewItem* item) { // Clipboard cut items are *always* filtered so we need this value upfront - const LLFolderViewEventListener* listener = item->getListener(); + const LLFolderViewEventListener* listener = item->getViewModelItem(); const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE); // If it's a folder and we're showing all folders, return automatically. @@ -140,7 +140,7 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const return false; } - const LLFolderViewModelItemInventory* listener = folder->getListener(); + const LLFolderViewModelItemInventory* listener = folder->getViewModelItem(); if (!listener) { llwarns << "Folder view event listener not found." << llendl; @@ -155,6 +155,13 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const { + // when applying a filter, matching folders get their contents downloaded first + if (isNotDefault() + && !gInventory.isCategoryComplete(getUUID()))) + { + LLInventoryModelBackgroundFetch::instance().start(getViewModelItem()->getUUID()); + } + // Always check against the clipboard const BOOL passed_clipboard = checkAgainstClipboard(folder_id); @@ -181,7 +188,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const { - const LLFolderViewModelItemInventory* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = item->getViewModelItem(); if (!listener) return FALSE; LLInventoryType::EType object_type = listener->getInventoryType(); @@ -349,11 +356,11 @@ bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const { - const LLFolderViewModelItemInventory* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = item->getViewModelItem(); if (!listener) return FALSE; PermissionMask perm = listener->getPermissionMask(); - const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(item->getListener()); + const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(item->getViewModelItem()); if (bridge && bridge->isLink()) { const LLUUID& linked_uuid = gInventory.getLinkedItemID(bridge->getUUID()); @@ -377,7 +384,7 @@ bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) con BOOL LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const { - const LLFolderViewModelItemInventory* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = item->getViewModelItem(); if (!listener) return TRUE; const LLUUID object_id = listener->getUUID(); @@ -408,9 +415,9 @@ BOOL LLInventoryFilter::isDefault() const } // has user modified default filter params? -BOOL LLInventoryFilter::isNotDefault() const +bool LLInventoryFilter::isNotDefault() const { - BOOL not_default = FALSE; + bool not_default = FALSE; not_default |= (mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes); not_default |= (mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes); @@ -1125,6 +1132,12 @@ LLInventoryFilter& LLInventoryFilter::operator=( const LLInventoryFilter& othe fromParams(other.toParams()); } +bool LLInventoryFilter::showAllResults() const +{ + return hasFilterString(); +} + + bool LLInventoryFilter::FilterOps::DateRange::validateBlock( bool emit_errors /*= true*/ ) { diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 4434008958..746e9a2820 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -29,6 +29,7 @@ #include "llinventorytype.h" #include "llpermissionsflags.h" +#include "llfolderviewmodel.h" class LLFolderViewItem; class LLFolderViewFolder; @@ -44,14 +45,6 @@ public: SHOW_NO_FOLDERS }; - enum EFilterBehavior - { - FILTER_NONE, // nothing to do, already filtered - FILTER_RESTART, // restart filtering from scratch - FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter - FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one - }; - enum EFilterType { FILTERTYPE_NONE = 0, FILTERTYPE_OBJECT = 0x1 << 0, // normal default search-by-object-type @@ -89,7 +82,7 @@ public: max_date("max_date", time_max()) {} - bool validateBlock(bool emit_errors = true); + bool validateBlock(bool emit_errors = true) const; }; struct Params : public LLInitParam::Block<Params> @@ -200,6 +193,9 @@ public: bool checkAgainstFilterLinks(const LLFolderViewItem* item) const; bool checkAgainstClipboard(const LLUUID& object_id) const; + bool showAllResults() const; + + std::string::size_type getStringMatchOffset() const; std::string::size_type getStringMatchOffset(LLFolderViewItem* item) const; @@ -262,24 +258,6 @@ public: private: bool areDateLimitsSet(); - struct FilterOps - { - FilterOps(); - U32 mFilterTypes; - - U64 mFilterObjectTypes; // For _OBJECT - U64 mFilterWearableTypes; - U64 mFilterCategoryTypes; // For _CATEGORY - LLUUID mFilterUUID; // for UUID - - time_t mMinDate; - time_t mMaxDate; - U32 mHoursAgo; - EFolderShow mShowFolderState; - PermissionMask mPermissions; - U64 mFilterLinks; - }; - U32 mOrder; U32 mLastLogoff; @@ -287,7 +265,6 @@ private: FilterOps mFilterOps; FilterOps mDefaultFilterOps; - std::string::size_type mSubStringMatchOffset; std::string mFilterSubString; std::string mFilterSubStringOrig; const std::string mName; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index ab5b082915..1e494c3ef1 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -948,7 +948,7 @@ void LLSaveFolderState::setApply(BOOL apply) void LLSaveFolderState::doFolder(LLFolderViewFolder* folder) { LLMemType mt(LLMemType::MTYPE_INVENTORY_DO_FOLDER); - LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); + LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getViewModelItem(); if(!bridge) return; if(mApply) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index d60b819da8..401daf6353 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -59,7 +59,7 @@ static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; // // class LLFolderViewModelInventory // -void LLFolderViewModelInventory::requestSort(class LLFolderViewFolder* folder) +void LLFolderViewModelInventory::requestSort(class LLFolderViewFolder* folder) { base_t::requestSort(folder); if (getSorter().isByDate()) @@ -78,7 +78,7 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) if (!needsSort(folder)) return; - LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getListener()); + LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem()); if (modelp->getUUID().isNull()) return; for (std::list<LLFolderViewFolder*>::iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); @@ -91,8 +91,8 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) if (child_folderp->getFoldersCount() > 0) { time_t most_recent_folder_time = - static_cast<LLFolderViewModelItemInventory*>(child_folderp->getFoldersBegin()->getListener())->getCreationDate(); - LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getListener()); + static_cast<LLFolderViewModelItemInventory*>(child_folderp->getFoldersBegin()->getViewModelItem())->getCreationDate(); + LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); if (most_recent_folder_time > modelp->getCreationDate()) { modelp->setCreationDate(most_recent_folder_time); @@ -101,9 +101,9 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) if (child_folderp->getItemsCount() > 0) { time_t most_recent_item_time = - static_cast<LLFolderViewModelItemInventory*>(child_folderp->getItemsBegin()->getListener())->getCreationDate(); + static_cast<LLFolderViewModelItemInventory*>(child_folderp->getItemsBegin()->getViewModelItem())->getCreationDate(); - LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getListener()); + LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); if (most_recent_item_time > modelp->getCreationDate()) { modelp->setCreationDate(most_recent_item_time); @@ -474,7 +474,7 @@ void LLInventoryPanel::modelChanged(U32 mask) if (view_item) { // Request refresh on this item (also flags for filtering) - LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getListener(); + LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getViewModelItem(); if(bridge) { // Clear the display name first, so it gets properly re-built during refresh() bridge->clearDisplayName(); @@ -493,7 +493,7 @@ void LLInventoryPanel::modelChanged(U32 mask) if (model_item && view_item) { view_item->destroyView(); - removeItemID(view_item->getListener()->getUUID()); + removeItemID(view_item->getViewModelItem()->getUUID()); } view_item = buildNewViews(item_id); view_folder = dynamic_cast<LLFolderViewFolder *>(view_item); @@ -563,14 +563,14 @@ void LLInventoryPanel::modelChanged(U32 mask) // Item is to be moved and we found its new parent in the panel's directory, so move the item's UI. view_item->getParentFolder()->extractItem(view_item); view_item->addToFolder(new_parent); - addItemID(view_item->getListener()->getUUID(), view_item); + addItemID(view_item->getViewModelItem()->getUUID(), view_item); } else { // Item is to be moved outside the panel's directory (e.g. moved to trash for a panel that // doesn't include trash). Just remove the item's UI. view_item->destroyView(); - removeItemID(view_item->getListener()->getUUID()); + removeItemID(view_item->getViewModelItem()->getUUID()); } } } @@ -583,7 +583,7 @@ void LLInventoryPanel::modelChanged(U32 mask) { // Remove the item's UI. view_item->destroyView(); - removeItemID(view_item->getListener()->getUUID()); + removeItemID(view_item->getViewModelItem()->getUUID()); } } } @@ -615,7 +615,7 @@ void LLInventoryPanel::onIdle(void *userdata) const LLUUID& LLInventoryPanel::getRootFolderID() const { - return mFolderRoot->getListener()->getUUID(); + return mFolderRoot->getViewModelItem()->getUUID(); } void LLInventoryPanel::initializeViews() @@ -654,7 +654,7 @@ LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id) if (old_view) { old_view->destroyView(); - removeItemID(old_view->getListener()->getUUID()); + removeItemID(old_view->getViewModelItem()->getUUID()); } return buildNewViews(id); @@ -727,7 +727,7 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) { LLInventoryObject const* objectp = gInventory.getObject(id); - LLUUID root_id = mFolderRoot->getListener()->getUUID(); + LLUUID root_id = mFolderRoot->getViewModelItem()->getUUID(); LLFolderViewFolder* parent_folder = NULL; LLFolderViewItem* itemp = NULL; @@ -786,7 +786,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) if (itemp) { itemp->addToFolder(parent_folder); - addItemID(itemp->getListener()->getUUID(), itemp); + addItemID(itemp->getViewModelItem()->getUUID(), itemp); } } } @@ -836,8 +836,8 @@ void LLInventoryPanel::openStartFolderOrMyInventory() { LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child); if (fchild - && fchild->getListener() - && fchild->getListener()->getUUID() == gInventory.getRootFolderID()) + && fchild->getViewModelItem() + && fchild->getViewModelItem()->getUUID() == gInventory.getRootFolderID()) { fchild->setOpen(TRUE); break; @@ -854,7 +854,7 @@ void LLInventoryPanel::openSelected() { LLFolderViewItem* folder_item = mFolderRoot->getCurSelectedItem(); if(!folder_item) return; - LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); + LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem(); if(!bridge) return; bridge->openItem(); } @@ -980,7 +980,7 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it mCompletionObserver->reset(); for (std::deque<LLFolderViewItem*>::const_iterator it = items.begin(); it != items.end(); ++it) { - LLUUID id = (*it)->getListener()->getUUID(); + LLUUID id = (*it)->getViewModelItem()->getUUID(); LLViewerInventoryItem* inv_item = mInventory->getItem(id); if (inv_item && !inv_item->isFinished()) @@ -1028,11 +1028,11 @@ bool LLInventoryPanel::beginIMSession() if(folder_item) { - LLFolderViewEventListener* fve_listener = folder_item->getListener(); + LLFolderViewEventListener* fve_listener = folder_item->getViewModelItem(); if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY)) { - LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener(); + LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getViewModelItem(); if(!bridge) return true; LLViewerInventoryCategory* cat = bridge->getCategory(); if(!cat) return true; @@ -1066,7 +1066,7 @@ bool LLInventoryPanel::beginIMSession() } else { - LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener(); + LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getViewModelItem(); if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD) { @@ -1113,7 +1113,7 @@ bool LLInventoryPanel::attachObject(const LLSD& userdata) set_iter != selected_items.end(); ++set_iter) { - items.push_back((*set_iter)->getListener()->getUUID()); + items.push_back((*set_iter)->getItemViewModel()->getUUID()); } // Attach selected items. @@ -1292,7 +1292,7 @@ LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); LLFolderViewItem* LLInventoryPanel::getItemByID(const LLUUID& id) { LLFastTimer _(FTM_GET_ITEM_BY_ID); - if (id == mFolderRoot->getListener()->getUUID()) + if (id == mFolderRoot->getViewModelItem()->getUUID()) { return mFolderRoot; } @@ -1317,7 +1317,7 @@ LLFolderViewFolder* LLInventoryPanel::getFolderByID(const LLUUID& id) void LLInventoryPanel::setSelectionByID( const LLUUID& obj_id, BOOL take_keyboard_focus ) { LLFolderViewItem* itemp = getItemByID(obj_id); - if(itemp && itemp->getListener()) + if(itemp && itemp->getViewModelItem()) { itemp->arrangeAndSet(TRUE, take_keyboard_focus); mSelectThisID.setNull(); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 7cf82bf268..467c508aa0 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -39,25 +39,58 @@ #include "lluictrlfactory.h" #include <set> -class LLFolderView; -class LLFolderViewFolder; -class LLFolderViewItem; -class LLInventoryFilter; -class LLInventoryModel; class LLInvFVBridge; class LLInventoryFVBridgeBuilder; -class LLMenuBarGL; -class LLCheckBoxCtrl; -class LLSpinCtrl; -class LLTextBox; -class LLIconCtrl; -class LLSaveFolderState; -class LLFilterEditor; -class LLTabContainer; class LLInvPanelComplObserver; +class LLFolderViewModelItemInventory + : public LLFolderViewModelItemCommon +{ +public: + virtual const LLUUID& getUUID() const = 0; + virtual time_t getCreationDate() const = 0; // UTC seconds + virtual void setCreationDate(time_t creation_date_utc) = 0; + virtual PermissionMask getPermissionMask() const = 0; + virtual LLFolderType::EType getPreferredType() const = 0; + virtual void showProperties(void) = 0; + virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. + virtual BOOL isUpToDate() const = 0; + virtual bool hasChildren() const = 0; + virtual LLInventoryType::EType getInventoryType() const = 0; + virtual void performAction(LLInventoryModel* model, std::string action) = 0; + virtual LLWearableType::EType getWearableType() const = 0; + virtual EInventorySortGroup getSortGroup() const = 0; + virtual LLInventoryObject* getInventoryObject() const = 0; +}; + +class LLInventorySort +{ +public: + LLInventorySort(U32 order) + : mSortOrder(0), + mByDate(false), + mSystemToTop(false), + mFoldersByName(false) + { + mSortOrder = order; + mByDate = (order & LLInventoryFilter::SO_DATE); + mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); + mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); + } + + bool isByDate() { return mByDate; } + U32 getSortOrder() { return mSortOrder; } + + bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b); +private: + U32 mSortOrder; + bool mByDate; + bool mSystemToTop; + bool mFoldersByName; +}; + class LLFolderViewModelInventory -: public LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> + : public LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> { typedef LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> base_t; @@ -200,8 +233,8 @@ public: void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); void updateSelection(); - LLFolderViewModelInventory* getViewModel() { return &mViewModel; } - const LLFolderViewModelInventory* getViewModel() const { return &mViewModel; } + LLFolderViewModelInventory* getFolderViewModel() { return &mViewModel; } + const LLFolderViewModelInventory* getFolderViewModel() const { return &mViewModel; } protected: void openStartFolderOrMyInventory(); // open the first level of inventory @@ -276,25 +309,4 @@ private: LLUUID mStartFolderID; }; -class LLFolderViewModelItemInventory - : public LLFolderViewModelItemCommon -{ -public: - virtual const LLUUID& getUUID() const = 0; - virtual time_t getCreationDate() const = 0; // UTC seconds - virtual void setCreationDate(time_t creation_date_utc) = 0; - virtual PermissionMask getPermissionMask() const = 0; - virtual LLFolderType::EType getPreferredType() const = 0; - virtual void previewItem( void ) = 0; - virtual void showProperties(void) = 0; - virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. - virtual BOOL isUpToDate() const = 0; - virtual BOOL hasChildren() const = 0; - virtual LLInventoryType::EType getInventoryType() const = 0; - virtual void performAction(LLInventoryModel* model, std::string action) = 0; - virtual LLWearableType::EType getWearableType() const = 0; - virtual EInventorySortGroup getSortGroup() const; - virtual void requestSort(const LLInventorySort& sorter); -}; - #endif // LL_LLINVENTORYPANEL_H diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 234fa7590d..54ad2bcb76 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -102,7 +102,7 @@ void LLCheckFolderState::doFolder(LLFolderViewFolder* folder) // Counting only folders that pass the filter. // The listener check allow us to avoid counting the folder view // object itself because it has no listener assigned. - if (folder->hasFilteredDescendants() && folder->getListener()) + if (folder->hasFilteredDescendants() && folder->getViewModelItem()) { if (folder->isOpen()) { @@ -138,7 +138,7 @@ private: // virtual void LLOpenFolderByID::doFolder(LLFolderViewFolder* folder) { - if (folder->getListener() && folder->getListener()->getUUID() == mFolderID) + if (folder->getViewModelItem() && folder->getViewModelItem()->getUUID() == mFolderID) { if (!folder->isOpen()) { @@ -286,7 +286,7 @@ void LLLandmarksPanel::onShowProfile() if(!cur_item) return; - cur_item->getListener()->performAction(mCurrentSelectedList->getModel(),"about"); + cur_item->getViewModelItem()->performAction(mCurrentSelectedList->getModel(),"about"); } // virtual @@ -299,7 +299,7 @@ void LLLandmarksPanel::onTeleport() return; } - LLFolderViewModelItem* listenerp = current_item->getListener(); + LLFolderViewModelItem* listenerp = current_item->getViewModelItem(); if (listenerp && listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) { listenerp->openItem(); @@ -360,7 +360,7 @@ void LLLandmarksPanel::onSelectorButtonClicked() LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem(); if (!cur_item) return; - LLFolderViewModelItem* listenerp = cur_item->getListener(); + LLFolderViewModelItem* listenerp = cur_item->getViewModelItem(); if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) { LLSD key; @@ -418,7 +418,7 @@ void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_ bool LLLandmarksPanel::isLandmarkSelected() const { LLFolderViewItem* current_item = getCurSelectedItem(); - if(current_item && current_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) + if(current_item && current_item->getViewModelItem()->getInventoryType() == LLInventoryType::IT_LANDMARK) { return true; } @@ -441,9 +441,9 @@ bool LLLandmarksPanel::isReceivedFolderSelected() const void LLLandmarksPanel::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb) { LLFolderViewItem* cur_item = getCurSelectedItem(); - if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) + if(cur_item && cur_item->getViewModelItem()->getInventoryType() == LLInventoryType::IT_LANDMARK) { - LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID(), cb); + LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getViewModelItem()->getUUID(), cb); if (landmark) { cb(landmark); @@ -510,7 +510,7 @@ void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data) { LLFolderViewItem* cur_item = getCurSelectedItem(); if (!cur_item) return; - LLUUID id = cur_item->getListener()->getUUID(); + LLUUID id = cur_item->getViewModelItem()->getUUID(); LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id); doActionOnCurSelectedLandmark(boost::bind( &LLLandmarksPanel::doProcessParcelInfo, this, _1, cur_item, inv_item, parcel_data)); @@ -738,7 +738,7 @@ void LLLandmarksPanel::onActionsButtonClick() if(!cur_item) return; - LLFolderViewModelItem* listenerp = cur_item->getListener(); + LLFolderViewModelItem* listenerp = cur_item->getViewModelItem(); if(!listenerp) return; @@ -795,17 +795,17 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const if (item && mCurrentSelectedList == mLandmarksInventoryPanel) { LLFolderViewModelItem* folder_bridge = NULL; - if (item-> getListener()->getInventoryType() + if (item-> getViewModelItem()->getInventoryType() == LLInventoryType::IT_LANDMARK) { // for a landmark get parent folder bridge - folder_bridge = item->getParentFolder()->getListener(); + folder_bridge = item->getParentFolder()->getViewModelItem(); } - else if (item-> getListener()->getInventoryType() + else if (item-> getViewModelItem()->getInventoryType() == LLInventoryType::IT_CATEGORY) { // for a folder get its own bridge - folder_bridge = item->getListener(); + folder_bridge = item->getViewModelItem(); } menu_create_inventory_item(mCurrentSelectedList, @@ -836,7 +836,7 @@ void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const { LLFolderViewItem* cur_item = getCurSelectedItem(); if(cur_item) - LLLandmarkActions::copySLURLtoClipboard(cur_item->getListener()->getUUID()); + LLLandmarkActions::copySLURLtoClipboard(cur_item->getViewModelItem()->getUUID()); } else if ( "paste" == command_name) { @@ -1015,7 +1015,7 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const LLFolderViewItem* cur_item = root_folder_view->getCurSelectedItem(); if (!cur_item) return false; - LLViewerInventoryItem* inv_item = cur_item->getInventoryItem(); + LLViewerInventoryItem* inv_item = static_cast<LLViewerInventoryItem*>(static_cast<LLFolderViewModelItemInventory*>(cur_item->getViewModelItem())->getInventoryObject()); if (!inv_item) return false; LLUUID asset_uuid = inv_item->getAssetUUID(); @@ -1116,12 +1116,12 @@ void LLLandmarksPanel::onMenuVisibilityChange(LLUICtrl* ctrl, const LLSD& param) // If no item is found it might be a folder id. if (!item) continue; - LLFolderViewModelItem* listenerp = item->getListener(); + LLFolderViewModelItem* listenerp = item->getViewModelItem(); if(!listenerp) continue; // Trash category itself should not be included because it can't be // actually restored from trash. - are_all_items_in_trash &= listenerp->isItemInTrash() && (*iter)->getListener()->getUUID() != trash_id; + are_all_items_in_trash &= listenerp->isItemInTrash() && (*iter)->getItemViewModel()->getUUID() != trash_id; // If there are any selected items in Trash including the Trash category itself // we show "Restore Item" in context menu and hide other irrelevant items. @@ -1160,7 +1160,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold bool can_be_modified = false; // landmarks can be modified in any other accordion... - if (item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) + if (item->getViewModelItem()->getInventoryType() == LLInventoryType::IT_LANDMARK) { can_be_modified = true; @@ -1198,7 +1198,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold if (can_be_modified) { - LLFolderViewModelItemInventory* listenerp = item->getListener(); + LLFolderViewModelItemInventory* listenerp = item->getViewModelItem(); if ("cut" == command_name) { diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index a7970bde24..fbdbce61bd 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -977,7 +977,7 @@ void LLPanelMainInventory::saveTexture(const LLSD& userdata) return; } - const LLUUID& item_id = current_item->getListener()->getUUID(); + const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES); if (preview_texture) { @@ -1050,7 +1050,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { return; } - const LLUUID item_id = current_item->getListener()->getUUID(); + const LLUUID item_id = current_item->getViewModelItem()->getUUID(); LLViewerInventoryItem *item = gInventory.getItem(item_id); if (item) { @@ -1065,7 +1065,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { return; } - current_item->getListener()->performAction(getActivePanel()->getModel(), "goto"); + current_item->getViewModelItem()->performAction(getActivePanel()->getModel(), "goto"); } if (command_name == "find_links") @@ -1075,8 +1075,8 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { return; } - const LLUUID& item_id = current_item->getListener()->getUUID(); - const std::string &item_name = current_item->getListener()->getName(); + const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); + const std::string &item_name = current_item->getViewModelItem()->getName(); mFilterSubString = item_name; LLInventoryFilter *filter = mActivePanel->getFilter(); filter->setFilterSubString(item_name); @@ -1094,11 +1094,11 @@ bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata) LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (current_item) { - LLViewerInventoryItem *inv_item = current_item->getInventoryItem(); + LLViewerInventoryItem *inv_item = dynamic_cast<LLViewerInventoryItem*>(static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getInventoryObject()); if(inv_item) { bool can_save = inv_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); - LLInventoryType::EType curr_type = current_item->getListener()->getInventoryType(); + LLInventoryType::EType curr_type = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getInventoryType(); return can_save && (curr_type == LLInventoryType::IT_TEXTURE || curr_type == LLInventoryType::IT_SNAPSHOT); } } @@ -1123,7 +1123,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) { const LLUUID &item_id = (*iter); LLFolderViewItem *item = *iter; - const LLFolderViewModelItemInventory *listener = item->getListener(); + const LLFolderViewModelItemInventory *listener = item->getViewModelItem(); llassert(listener); if (!listener) return FALSE; can_delete &= listener->isItemRemovable(); @@ -1141,7 +1141,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) return FALSE; - const LLUUID& item_id = current_item->getListener()->getUUID(); + const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); const LLViewerInventoryItem *item = gInventory.getItem(item_id); if (item && item->getIsLinkType() && !item->getIsBrokenLink()) { @@ -1157,7 +1157,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) if (selection_set.size() != 1) return FALSE; LLFolderViewItem* current_item = root->getCurSelectedItem(); if (!current_item) return FALSE; - const LLUUID& item_id = current_item->getListener()->getUUID(); + const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); const LLInventoryObject *obj = gInventory.getObject(item_id); if (obj && !obj->getIsLinkType() && LLAssetType::lookupCanLink(obj->getType())) { @@ -1170,7 +1170,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) return FALSE; - const LLUUID& item_id = current_item->getListener()->getUUID(); + const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); const LLViewerInventoryItem *item = gInventory.getItem(item_id); if (item && item->getIsBrokenLink()) { diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index 6804342106..8a07d6d516 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -94,7 +94,7 @@ LLInventoryPanel * LLPanelMarketplaceInbox::setupInventoryPanel() mInventoryPanel->setShape(inventory_placeholder_rect); // Set the sort order newest to oldest - mInventoryPanel->getViewModel()->setSorter(LLInventoryFilter::SO_DATE); + mInventoryPanel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_DATE); mInventoryPanel->getFilter()->markDefault(); // Set selection callback for proper update of inventory status buttons diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp index b5c7c4ca88..7db01d9059 100644 --- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceoutboxinventory.cpp @@ -29,7 +29,7 @@ #include "llpanelmarketplaceoutboxinventory.h" #include "llfolderviewitem.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llpanellandmarks.h" diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 3d7d9d573e..240c5b2da4 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -113,7 +113,6 @@ public: virtual void openItem(); virtual BOOL canOpenItem() const { return FALSE; } virtual void closeItem() {} - virtual void previewItem(); virtual void selectItem() {} virtual BOOL isItemRenameable() const; virtual BOOL renameItem(const std::string& new_name); @@ -352,11 +351,6 @@ void LLTaskInvFVBridge::openItem() lldebugs << "LLTaskInvFVBridge::openItem()" << llendl; } -void LLTaskInvFVBridge::previewItem() -{ - openItem(); -} - BOOL LLTaskInvFVBridge::isItemRenameable() const { if(gAgent.isGodlike()) return TRUE; @@ -1754,7 +1748,7 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li view = LLUICtrlFactory::create<LLFolderViewItem> (params); } view->addToFolder(folder); - addItemID(view->getListener()->getUUID(), view); + addItemID(view->getViewModelItem()->getUUID(), view); } } diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 4abc7fea0e..a95d27f992 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -270,7 +270,7 @@ private: if (inventory_panel->getVisible()) { - inventory_panel->getViewModel()->setSorter(sort_order); + inventory_panel->getFolderViewModel()->setSorter(sort_order); } else { @@ -1310,7 +1310,7 @@ void LLPanelOutfitEdit::getCurrentItemUUID(LLUUID& selected_id) LLFolderViewItem* curr_item = mInventoryItemsPanel->getRootFolder()->getCurSelectedItem(); if (!curr_item) return; - LLFolderViewModelItemInventory* listenerp = curr_item->getListener(); + LLFolderViewModelItemInventory* listenerp = curr_item->getViewModelItem(); if (!listenerp) return; selected_id = listenerp->getUUID(); @@ -1332,7 +1332,7 @@ void LLPanelOutfitEdit::getSelectedItemsUUID(uuid_vec_t& uuid_list) it != end_it; ++it) { - uuid_list.push_back((*it)->getListener()->getUUID()); + uuid_list.push_back((*it)->getItemViewModel()->getUUID()); } } else if (mWearablesListViewPanel->getVisible()) @@ -1384,7 +1384,7 @@ void LLPanelOutfitEdit::saveListSelection() for (std::set<LLFolderViewItem*>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) { - mWearableItemsList->selectItemByUUID((*item_id)->getListener()->getUUID(), true); + mWearableItemsList->selectItemByUUID((*item_id)->getItemViewModel()->getUUID(), true); } mWearableItemsList->scrollToShowFirstSelectedItem(); } diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index 1de26660bc..da5ce7d4b7 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -30,7 +30,7 @@ #include "llplacesinventorypanel.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" #include "llfolderview.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" @@ -162,7 +162,7 @@ BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask) // then determine its type and set necessary menu handle if (getCurSelectedItem()) { - LLInventoryType::EType inventory_type = getCurSelectedItem()->getListener()->getInventoryType(); + LLInventoryType::EType inventory_type = getCurSelectedItem()->getViewModelItem()->getInventoryType(); inventory_type_menu_handle_t::iterator it_handle = mMenuHandlesByInventoryType.find(inventory_type); if (it_handle != mMenuHandlesByInventoryType.end()) diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index f069da5869..194aa7f71b 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -38,7 +38,7 @@ #include "llfiltereditor.h" #include "llfloaterreg.h" #include "llfloaterworldmap.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" #include "lloutfitobserver.h" #include "llpaneleditwearable.h" #include "llpaneloutfitsinventory.h" diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index cc578b5799..f3d32e7a67 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -473,7 +473,7 @@ void LLSidepanelInventory::performActionOnSelection(const std::string &action) } } - current_item->getListener()->performAction(mPanelMainInventory->getActivePanel()->getModel(), action); + current_item->getViewModelItem()->performAction(mPanelMainInventory->getActivePanel()->getModel(), action); } void LLSidepanelInventory::onWearButtonClicked() @@ -663,7 +663,7 @@ LLInventoryItem *LLSidepanelInventory::getSelectedItem() return NULL; } } - const LLUUID &item_id = current_item->getListener()->getUUID(); + const LLUUID &item_id = current_item->getViewModelItem()->getUUID(); LLInventoryItem *item = gInventory.getItem(item_id); return item; } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index ad2db966bd..a995f07df7 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -39,7 +39,7 @@ #include "llfocusmgr.h" #include "llviewertexture.h" #include "llfolderview.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" #include "llinventory.h" #include "llinventoryfunctions.h" #include "llinventorymodelbackgroundfetch.h" @@ -800,7 +800,7 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem if (items.size()) { LLFolderViewItem* first_item = items.front(); - LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID()); + LLInventoryItem* itemp = gInventory.getItem(first_item->getViewModelItem()->getUUID()); mNoCopyTextureSelected = FALSE; if (itemp) { -- cgit v1.2.3 From b64fc84707a0ab4c11e84cf5caec32bbc267f313 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 18 Jun 2012 08:21:42 -0700 Subject: CHUI-145 : WIP Always open the message pane when clicking on a conversation in the list --- indra/llui/llmultifloater.cpp | 2 +- indra/newview/llimfloatercontainer.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index 540ac74aee..6f0e691f10 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -173,7 +173,7 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, else if (floaterp->getHost()) { // floaterp is hosted by somebody else and - // this is adding it, so remove it from it's old host + // this is adding it, so remove it from its old host floaterp->getHost()->removeFloater(floaterp); } else if (floaterp->getParent() == gFloaterView) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index af5d587f20..e8eae331a1 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -431,6 +431,8 @@ LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLF // Virtual action callbacks void LLConversationItem::selectItem(void) { + // Always expand the message pane in that case + mContainer->collapseMessagesPane(false); // Switch to the conversation floater that is being selected mContainer->selectFloater(mFloater); } -- cgit v1.2.3 From bc5e0eda1b1b9c289734bebe6a533565aadfd3a2 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 18 Jun 2012 21:11:56 +0300 Subject: CHUI-119 fixed bug with creating multiply instances of the nearby chat; --- indra/newview/llimfloatercontainer.cpp | 3 +-- indra/newview/llnearbychat.cpp | 6 +----- indra/newview/llviewerwindow.cpp | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index af5d587f20..8493a0e7b8 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -96,8 +96,7 @@ void LLIMFloaterContainer::onOpen(const LLSD& key) // If there's *no* conversation open so far, we force the opening of the nearby chat conversation // *TODO: find a way to move this to XML as a default panel or something like that LLSD name("chat_bar"); - LLSD key(""); - LLFloaterReg::toggleInstanceOrBringToFront(name,key); + LLFloaterReg::toggleInstanceOrBringToFront(name); } /* if (key.isDefined()) diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index fbaf451412..e4b891889c 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -130,6 +130,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& key) mSpeakerMgr(NULL), mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) { + mKey = LLSD(); mIsNearbyChat = true; mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); } @@ -382,11 +383,6 @@ LLNearbyChat* LLNearbyChat::getInstance() return LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar"); } -//static -//LLNearbyChat* LLNearbyChat::findInstance() -//{ -// return LLFloaterReg::findTypedInstance<LLNearbyChat>("chat_bar"); -//} void LLNearbyChat::showHistory() { diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 7f14e021fd..016da1d994 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2555,7 +2555,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) { - LLLineEditor* chat_editor = LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar")->getChatBox(); + LLLineEditor* chat_editor = LLNearbyChat::getInstance()->getChatBox(); if (chat_editor) { // passing NULL here, character will be added later when it is handled by character handler. -- cgit v1.2.3 From 7edcbb1613d30f9fecf3ccbe342d45b7761f5b56 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 18 Jun 2012 23:20:17 +0300 Subject: CHUI-100 WIP Fix translate chat checkbox showing --- indra/newview/llimconversation.cpp | 7 +++++++ indra/newview/llimconversation.h | 3 +++ indra/newview/llnearbychat.cpp | 4 ---- indra/newview/llnearbychat.h | 1 - 4 files changed, 10 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 3e2b208874..ead87e3ed5 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -236,6 +236,13 @@ void LLIMConversation::updateHeaderAndToolbar() mCloseBtn->setVisible(is_hosted); enableDisableCallBtn(); + + showTranslationCheckbox(); +} + +void LLIMConversation::showTranslationCheckbox(BOOL show) +{ + getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(mIsNearbyChat? show : FALSE); } // static diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index d31ae0808a..66401b9a3c 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -56,6 +56,9 @@ public: */ static bool isChatMultiTab(); + // show/hide the translation check box + void showTranslationCheckbox(const BOOL visible = FALSE); + // LLFloater overrides /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ BOOL postBuild(); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index e4b891889c..1b2d9b6801 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -393,10 +393,6 @@ void LLNearbyChat::showHistory() storeRectControl(); } -void LLNearbyChat::showTranslationCheckbox(BOOL show) -{ - getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(show); -} BOOL LLNearbyChat::tick() { diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index bc0e54de15..3dc94ce0da 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -87,7 +87,6 @@ public: static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); void showHistory(); - void showTranslationCheckbox(BOOL show); protected: static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); -- cgit v1.2.3 From 06f142e974854854c91988b6a8bc5c6005a40731 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 18 Jun 2012 18:12:38 -0700 Subject: CHUI-145 : Select on list focus on relevant panel, torn off or not; torn off im stay in list; closed im suppressed from lits in all situations --- indra/newview/llimfloater.cpp | 10 +++ indra/newview/llimfloatercontainer.cpp | 117 +++++++++++++++++++-------------- indra/newview/llimfloatercontainer.h | 6 +- 3 files changed, 81 insertions(+), 52 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 30a9c29ec6..14fcd602fc 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -139,6 +139,16 @@ void LLIMFloater::onClose(bool app_quitting) // Last change: // EXT-3516 X Button should end IM session, _ button should hide gIMMgr->leaveSession(mSessionID); + + // Suppress the IM from the conversations list + if (LLIMConversation::isChatMultiTab()) + { + LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); + if (im_box) + { + im_box->removeConversationListItem(mSessionID); + } + } } /* static */ diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index e8eae331a1..bedf3315e8 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -129,24 +129,8 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, LLUUID session_id = floaterp->getKey(); - // CHUI-137 : Temporary implementation of conversations list - // Create a conversation item - LLConversationItem* item = new LLConversationItem(floaterp->getTitle(),session_id, floaterp, this); - mConversationsItems[session_id] = item; - // Create a widget from it - LLFolderViewItem* widget = createConversationItemWidget(item); - mConversationsWidgets[session_id] = widget; - // Add it to the UI - widget->setVisible(TRUE); - mConversationsListPanel->addChild(widget); - LLRect panel_rect = mConversationsListPanel->getRect(); - S32 item_height = 16; - S32 index = mConversationsWidgets.size() - 1; - widget->setRect(LLRect(0, - panel_rect.getHeight() - item_height*index, - panel_rect.getWidth(), - panel_rect.getHeight() - item_height*(index+1))); - // CHUI-137 : end + // Add a conversation list item in the left pane + addConversationListItem(floaterp->getTitle(), session_id, floaterp, this); LLView* floater_contents = floaterp->getChild<LLView>("contents_view"); @@ -184,35 +168,6 @@ void LLIMFloaterContainer::removeFloater(LLFloater* floaterp) { LLMultiFloater::removeFloater(floaterp); - // CHUI-137 : Temporary implementation of conversations list - // Clean up the conversations list - LLUUID session_id = floaterp->getKey(); - // Delete the widget and the associated conversation item - // Note : since the mConversationsItems is also the listener to the widget, deleting - // the widget will also delete its listener - conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(session_id); - if (widget_it != mConversationsWidgets.end()) - { - LLFolderViewItem* widget = widget_it->second; - delete widget; - } - // Suppress the conversation items and widgets from their respective maps - mConversationsItems.erase(session_id); - mConversationsWidgets.erase(session_id); - // Reposition the leftover conversation items - LLRect panel_rect = mConversationsListPanel->getRect(); - S32 item_height = 16; - int index = 0; - for (widget_it = mConversationsWidgets.begin(); widget_it != mConversationsWidgets.end(); ++widget_it, ++index) - { - LLFolderViewItem* widget = widget_it->second; - widget->setRect(LLRect(0, - panel_rect.getHeight() - item_height*index, - panel_rect.getWidth(), - panel_rect.getHeight() - item_height*(index+1))); - } - // CHUI-137 : end - LLRect contents_rect = floaterp->getRect(); // reduce the floater contents height by header height @@ -399,6 +354,60 @@ void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) } // CHUI-137 : Temporary implementation of conversations list +void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp) +{ + // Create a conversation item + LLConversationItem* item = new LLConversationItem(name, uuid, floaterp, containerp); + mConversationsItems[uuid] = item; + + // Create a widget from it + LLFolderViewItem* widget = createConversationItemWidget(item); + mConversationsWidgets[uuid] = widget; + + // Add it to the UI + widget->setVisible(TRUE); + mConversationsListPanel->addChild(widget); + LLRect panel_rect = mConversationsListPanel->getRect(); + S32 item_height = 16; + S32 index = mConversationsWidgets.size() - 1; + widget->setRect(LLRect(0, + panel_rect.getHeight() - item_height*index, + panel_rect.getWidth(), + panel_rect.getHeight() - item_height*(index+1))); + return; +} + +void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id) +{ + // Delete the widget and the associated conversation item + // Note : since the mConversationsItems is also the listener to the widget, deleting + // the widget will also delete its listener + conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(session_id); + if (widget_it != mConversationsWidgets.end()) + { + LLFolderViewItem* widget = widget_it->second; + delete widget; + } + + // Suppress the conversation items and widgets from their respective maps + mConversationsItems.erase(session_id); + mConversationsWidgets.erase(session_id); + + // Reposition the leftover conversation items + LLRect panel_rect = mConversationsListPanel->getRect(); + S32 item_height = 16; + int index = 0; + for (widget_it = mConversationsWidgets.begin(); widget_it != mConversationsWidgets.end(); ++widget_it, ++index) + { + LLFolderViewItem* widget = widget_it->second; + widget->setRect(LLRect(0, + panel_rect.getHeight() - item_height*index, + panel_rect.getWidth(), + panel_rect.getHeight() - item_height*(index+1))); + } + return; +} + LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) { LLFolderViewItem::Params params; @@ -431,10 +440,16 @@ LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLF // Virtual action callbacks void LLConversationItem::selectItem(void) { - // Always expand the message pane in that case - mContainer->collapseMessagesPane(false); - // Switch to the conversation floater that is being selected - mContainer->selectFloater(mFloater); + LLMultiFloater* host_floater = mFloater->getHost(); + if (host_floater == mContainer) + { + // Always expand the message pane if the panel is hosted by the container + mContainer->collapseMessagesPane(false); + // Switch to the conversation floater that is being selected + mContainer->selectFloater(mFloater); + } + // Set the focus on the selected floater + mFloater->setFocus(TRUE); } void LLConversationItem::performAction(LLInventoryModel* model, std::string action) diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index b5b60615b3..10268a5d79 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -142,7 +142,6 @@ public: void collapseMessagesPane(bool collapse); - LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; @@ -168,6 +167,11 @@ private: LLLayoutStack* mConversationsStack; // CHUI-137 : Temporary implementation of conversations list +public: + void removeConversationListItem(const LLUUID& session_id); +private: + void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp); + LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); // Conversation list data LLPanel* mConversationsListPanel; // This is the widget we add items to (i.e. clickable title for each conversation) conversations_items_map mConversationsItems; -- cgit v1.2.3 From 59987bb051ed39146ec9b3831eec81434779a73f Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Mon, 18 Jun 2012 19:01:59 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose continuing fixing build errors general cleanup --- indra/newview/llfolderview.cpp | 158 +++++++++++++-------------- indra/newview/llfolderview.h | 61 +++++++++++ indra/newview/llfolderviewitem.cpp | 2 +- indra/newview/llfolderviewitem.h | 5 + indra/newview/llfolderviewmodel.h | 25 +++-- indra/newview/llinventorybridge.cpp | 6 +- indra/newview/llinventoryfilter.cpp | 157 ++++++++++++++------------- indra/newview/llinventoryfilter.h | 20 ++-- indra/newview/llinventoryfunctions.h | 58 ---------- indra/newview/llinventorypanel.cpp | 181 ++++++++++++++----------------- indra/newview/llinventorypanel.h | 20 ++-- indra/newview/llpanelobjectinventory.cpp | 2 +- indra/newview/llsidepanelinventory.h | 3 +- 13 files changed, 342 insertions(+), 356 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 918e68e444..f0edbb638a 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -32,12 +32,8 @@ #include "llcallbacklist.h" #include "llinventorybridge.h" #include "llclipboard.h" // *TODO: remove this once hack below gone. -#include "llinventoryfilter.h" -#include "llinventoryfunctions.h" -#include "llinventorymodelbackgroundfetch.h" #include "llinventorypanel.h" #include "llfoldertype.h" -#include "llfloaterinventory.h"// hacked in for the bonus context menu items. #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" @@ -65,7 +61,6 @@ #include "llfontgl.h" #include "llgl.h" #include "llrender.h" -#include "llinventory.h" // Third-party library includes #include <algorithm> @@ -141,7 +136,7 @@ const LLRect LLFolderViewScrollContainer::getScrolledViewRect() const LLFolderView* folder_view = dynamic_cast<LLFolderView*>(mScrolledView); if (folder_view) { - S32 height = folder_view->mRunningHeight; + S32 height = folder_view->getRect().getHeight(); rect = mScrolledView->getRect(); rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); @@ -188,7 +183,7 @@ LLFolderView::LLFolderView(const Params& p) mNeedsAutoRename(FALSE), mDebugFilters(FALSE), mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME), // This gets overridden by a pref immediately - mFilter( new LLInventoryFilter(p.title) ), + mFilter(), mShowSelectionContext(FALSE), mShowSingleSelection(FALSE), mArrangeGeneration(0), @@ -304,7 +299,7 @@ BOOL LLFolderView::canFocusChildren() const BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { // enforce sort order of My Inventory followed by Library - if (folder->getViewModelItem()->getUUID() == gInventory.getLibraryRootFolderID()) + if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) { mFolders.push_back(folder); } @@ -364,7 +359,7 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen return llround(mTargetHeight); } -static LLFastTimer::DeclareTimer FTM_FILTER("Filter Inventory"); +static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View"); void LLFolderView::filter( LLFolderViewFilter& filter ) { @@ -392,7 +387,7 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) scroll_rect = mScrollContainer->getContentWindowRect(); } width = llmax(mMinWidth, scroll_rect.getWidth()); - height = llmax(mCurHeight, scroll_rect.getHeight()); + height = llmax(llround(mCurHeight), scroll_rect.getHeight()); // Restrict width within scroll container's width if (mUseEllipses && mScrollContainer) @@ -645,7 +640,6 @@ void LLFolderView::clearSelection() } mSelectedItems.clear(); - mSelectThisID.setNull(); } std::set<LLFolderViewItem*> LLFolderView::getSelectionList() const @@ -735,9 +729,9 @@ void LLFolderView::draw() } else if (mShowEmptyMessage) { - if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mCompletedFilterGeneration < mFilter->getFirstSuccessGeneration()) + if (!mViewModel->contentsReady() || mCompletedFilterGeneration < mFilter->getFirstSuccessGeneration()) { - RN: Get this from filter + // TODO RN: Get this from filter mStatusText = LLTrans::getString("Searching"); } else @@ -921,7 +915,7 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL else if (count > 1) { LLDynamicArray<LLFolderViewModelItem*> listeners; - LLFolderViewModelItemInventory* listener; + LLFolderViewModelItem* listener; LLFolderViewItem* last_item = items[count - 1]; LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); while(new_selection && new_selection->isSelected()) @@ -948,12 +942,12 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL for(S32 i = 0; i < count; ++i) { listener = items[i]->getViewModelItem(); - if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewModelItemInventory*>::FAIL)) + if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewModelItem*>::FAIL)) { listeners.put(listener); } } - listener = static_cast<LLFolderViewModelItemInventory*>(listeners.get(0)); + listener = static_cast<LLFolderViewModelItem*>(listeners.get(0)); if(listener) { listener->removeBatch(listeners); @@ -969,36 +963,37 @@ void LLFolderView::openSelectedItems( void ) { if(getVisible() && getEnabled()) { - if (mSelectedItems.size() == 1) - { - mSelectedItems.front()->openItem(); - } - else - { - LLMultiPreview* multi_previewp = new LLMultiPreview(); - LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - // IT_{OBJECT,ATTACHMENT} creates LLProperties - // floaters; others create LLPreviews. Put - // each one in the right type of container. - LLFolderViewModelItemInventory* listener = (*item_it)->getViewModelItem(); - bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); - if (is_prop) - LLFloater::setFloaterHost(multi_propertiesp); - else - LLFloater::setFloaterHost(multi_previewp); - (*item_it)->openItem(); - } - - LLFloater::setFloaterHost(NULL); - // *NOTE: LLMulti* will safely auto-delete when open'd - // without any children. - multi_previewp->openFloater(LLSD()); - multi_propertiesp->openFloater(LLSD()); - } + // TODO RN: move to LLFolderViewModelInventory + //if (mSelectedItems.size() == 1) + //{ + // mSelectedItems.front()->openItem(); + //} + //else + //{ + // LLMultiPreview* multi_previewp = new LLMultiPreview(); + // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + + // selected_items_t::iterator item_it; + // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + // { + // // IT_{OBJECT,ATTACHMENT} creates LLProperties + // // floaters; others create LLPreviews. Put + // // each one in the right type of container. + // LLFolderViewModelItemInventory* listener = (*item_it)->getViewModelItem(); + // bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); + // if (is_prop) + // LLFloater::setFloaterHost(multi_propertiesp); + // else + // LLFloater::setFloaterHost(multi_previewp); + // (*item_it)->openItem(); + // } + + // LLFloater::setFloaterHost(NULL); + // // *NOTE: LLMulti* will safely auto-delete when open'd + // // without any children. + // multi_previewp->openFloater(LLSD()); + // multi_propertiesp->openFloater(LLSD()); + //} } } @@ -1006,27 +1001,28 @@ void LLFolderView::propertiesSelectedItems( void ) { if(getVisible() && getEnabled()) { - if (mSelectedItems.size() == 1) - { - LLFolderViewItem* folder_item = mSelectedItems.front(); - if(!folder_item) return; - folder_item->getViewModelItem()->showProperties(); - } - else - { - LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + // TODO RN: move to LLFolderViewModelInventory + //if (mSelectedItems.size() == 1) + //{ + // LLFolderViewItem* folder_item = mSelectedItems.front(); + // if(!folder_item) return; + // folder_item->getViewModelItem()->showProperties(); + //} + //else + //{ + // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - LLFloater::setFloaterHost(multi_propertiesp); + // LLFloater::setFloaterHost(multi_propertiesp); - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - (*item_it)->getViewModelItem()->showProperties(); - } + // selected_items_t::iterator item_it; + // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + // { + // (*item_it)->getViewModelItem()->showProperties(); + // } - LLFloater::setFloaterHost(NULL); - multi_propertiesp->openFloater(LLSD()); - } + // LLFloater::setFloaterHost(NULL); + // multi_propertiesp->openFloater(LLSD()); + //} } } @@ -1140,7 +1136,7 @@ void LLFolderView::copy() S32 count = mSelectedItems.size(); if(getVisible() && getEnabled() && (count > 0)) { - LLFolderViewModelItemInventory* listener = NULL; + LLFolderViewModelItem* listener = NULL; selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { @@ -1164,7 +1160,7 @@ BOOL LLFolderView::canCut() const for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) { const LLFolderViewItem* item = *selected_it; - const LLFolderViewModelItemInventory* listener = item->getViewModelItem(); + const LLFolderViewModelItem* listener = item->getViewModelItem(); if (!listener || !listener->isItemRemovable()) { @@ -1181,7 +1177,7 @@ void LLFolderView::cut() S32 count = mSelectedItems.size(); if(getVisible() && getEnabled() && (count > 0)) { - LLFolderViewModelItemInventory* listener = NULL; + LLFolderViewModelItem* listener = NULL; selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { @@ -1210,7 +1206,7 @@ BOOL LLFolderView::canPaste() const { // *TODO: only check folders and parent folders of items const LLFolderViewItem* item = (*item_it); - const LLFolderViewModelItemInventory* listener = item->getViewModelItem(); + const LLFolderViewModelItem* listener = item->getViewModelItem(); if(!listener || !listener->isClipboardPasteable()) { const LLFolderViewFolder* folderp = item->getParentFolder(); @@ -1232,24 +1228,24 @@ void LLFolderView::paste() if(getVisible() && getEnabled()) { // find set of unique folders to paste into - std::set<LLFolderViewItem*> folder_set; + std::set<LLFolderViewFolder*> folder_set; selected_items_t::iterator selected_it; for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) { LLFolderViewItem* item = *selected_it; - LLFolderViewModelItemInventory* listener = item->getViewModelItem(); - if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY) + LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(item); + if (folder == NULL) { item = item->getParentFolder(); } - folder_set.insert(item); + folder_set.insert(folder); } - std::set<LLFolderViewItem*>::iterator set_iter; + std::set<LLFolderViewFolder*>::iterator set_iter; for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) { - LLFolderViewModelItemInventory* listener = (*set_iter)->getListener(); + LLFolderViewModelItem* listener = (*set_iter)->getViewModelItem(); if(listener && listener->isClipboardPasteable()) { listener->pasteFromClipboard(); @@ -1765,15 +1761,9 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, // when drop is not handled by child, it should be handled // by the folder which is the hierarchy root. - if (!handled - && getViewModelItem()->getUUID().notNull()) - { - handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - } - - if (handled) + if (!handled) { - lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl; + handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); } return handled; @@ -1996,7 +1986,7 @@ void LLFolderView::doIdle() // Open filtered folders for folder views with mAutoSelectOverride=TRUE. // Used by LLPlacesFolderView. - if (mAutoSelectOverride && !mFilter->getFilterSubString().empty()) + if (mAutoSelectOverride && mFilter->showAllResults()) { // these are named variables to get around gcc not binding non-const references to rvalues // and functor application is inherently non-const to allow for stateful functors @@ -2008,7 +1998,7 @@ void LLFolderView::doIdle() } BOOL filter_finished = mCompletedFilterGeneration >= mFilter->getCurrentGeneration() - && !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); + && mViewModel->contentsReady(); if (filter_finished || gFocusMgr.childHasKeyboardFocus(inventory_panel) || gFocusMgr.childHasMouseCapture(inventory_panel)) diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 9b8a629387..813b4d130f 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -337,6 +337,67 @@ public: }; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderViewFunctor +// +// Simple abstract base class for applying a functor to folders and +// items in a folder view hierarchy. This is suboptimal for algorithms +// that only work folders or only work on items, but I'll worry about +// that later when it's determined to be too slow. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLFolderViewFunctor +{ +public: + virtual ~LLFolderViewFunctor() {} + virtual void doFolder(LLFolderViewFolder* folder) = 0; + virtual void doItem(LLFolderViewItem* item) = 0; +}; + +class LLSelectFirstFilteredItem : public LLFolderViewFunctor +{ +public: + LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} + virtual ~LLSelectFirstFilteredItem() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); + BOOL wasItemSelected() { return mItemSelected; } +protected: + BOOL mItemSelected; +}; + +class LLOpenFilteredFolders : public LLFolderViewFunctor +{ +public: + LLOpenFilteredFolders() {} + virtual ~LLOpenFilteredFolders() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + +class LLSaveFolderState : public LLFolderViewFunctor +{ +public: + LLSaveFolderState() : mApply(FALSE) {} + virtual ~LLSaveFolderState() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item) {} + void setApply(BOOL apply); + void clearOpenFolders() { mOpenFolders.clear(); } +protected: + std::set<LLUUID> mOpenFolders; + BOOL mApply; +}; + +class LLOpenFoldersWithSelection : public LLFolderViewFunctor +{ +public: + LLOpenFoldersWithSelection() {} + virtual ~LLOpenFoldersWithSelection() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + // Flags for buildContextMenu() const U32 SUPPRESS_OPEN_ITEM = 0x1; const U32 FIRST_SELECTED_ITEM = 0x2; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 0a3c03e868..6e60ec5e1a 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -2529,7 +2529,7 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it return result; } -bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) +bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const { // ignore sort order for landmarks in the Favorites folder. // they should be always sorted as in Favorites bar. See EXT-719 diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 7bcc9dd0a2..9e024d7eea 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -475,6 +475,11 @@ public: LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items); + +public: + //WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead + template<typename SORT_FUNC> void sortFolders(SORT_FUNC& func) { mFolders.sort(func); } + template<typename SORT_FUNC> void sortItems(SORT_FUNC& func) { mItems.sort(func); } }; diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index b81a81f837..9bbd7f48cf 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -56,7 +56,7 @@ class LLFolderViewFolder; class LLFolderViewFilter { public: - enum EFilterBehavior + enum EFilterModified { FILTER_NONE, // nothing to do, already filtered FILTER_RESTART, // restart filtering from scratch @@ -78,7 +78,7 @@ public: virtual bool checkFolder(const LLUUID& folder_id) const = 0; virtual void setEmptyLookupMessage(const std::string& message) = 0; - const virtual std::string& getEmptyLookupMessage() const = 0; + virtual std::string getEmptyLookupMessage() const = 0; virtual bool showAllResults() const = 0; @@ -87,12 +87,11 @@ public: // +-------------------------------------------------------------------+ virtual bool isActive() const = 0; virtual bool isModified() const = 0; - virtual bool isModifiedAndClear() = 0; virtual void clearModified() = 0; virtual const std::string& getName() const = 0; virtual const std::string& getFilterText() = 0; //RN: this is public to allow system to externally force a global refilter - virtual void setModified(EFilterBehavior behavior = FILTER_RESTART) = 0; + virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0; // +-------------------------------------------------------------------+ // + Count @@ -125,6 +124,8 @@ public: virtual void sort(class LLFolderViewFolder*) = 0; virtual void filter(class LLFolderViewFolder*) = 0; + + virtual bool contentsReady() = 0; }; struct LLFolderViewModelCommon : public LLFolderViewModelInterface @@ -230,7 +231,7 @@ protected: template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE> class LLFolderViewModel : public LLFolderViewModelCommon { -protected: +public: LLFolderViewModel() {} virtual ~LLFolderViewModel() {} @@ -239,12 +240,14 @@ protected: typedef FOLDER_TYPE FolderType; typedef FILTER_TYPE FilterType; + virtual SortType& getSorter() { return mSorter; } virtual const SortType& getSorter() const { return mSorter; } virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } - virtual FilterType& getFilter() { return mFilter; } + virtual FilterType& getFilter() { return mFilter; } + virtual const FilterType& getFilter() const { return mFilter; } virtual void setFilter(const FilterType& filter) { mFilter = filter; } -public: + virtual bool contentsReady() { return true; } struct ViewModelCompare { @@ -252,12 +255,12 @@ public: : mSorter(sorter) {} - int operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) + bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) { return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); } - int operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) + bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) { return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); } @@ -269,8 +272,8 @@ public: { if (needsSort(folder->getViewModelItem())) { - std::sort(folder->getFoldersBegin(), folder->getFoldersEnd(), ViewModelCompare(getSorter())); - std::sort(folder->getItemsBegin(), folder->getItemsEnd(), ViewModelCompare(getSorter())); + folder->sortFolders(ViewModelCompare(getSorter())); + folder->sortItems(ViewModelCompare(getSorter())); folder->getViewModelItem()->setSortVersion(mTargetSortVersion); folder->requestArrange(); } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index b51bbf7bfe..312b7314a1 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -423,7 +423,7 @@ void LLInvFVBridge::removeBatchNoCheck(std::vector<LLFolderViewModelItem*>& ba for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.get(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); if(cat) @@ -1275,7 +1275,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const if (can_list) { - LLFolderViewFolder * object_folderp = mInventoryPanel->getFolderByID(object_id); + LLFolderViewFolder * object_folderp = mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(object_id) : NULL; if (object_folderp) { can_list = !object_folderp->isLoading(); @@ -1286,7 +1286,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const { // Get outbox id const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); - LLFolderViewItem * outbox_itemp = mInventoryPanel->getItemByID(outbox_id); + LLFolderViewItem * outbox_itemp = mInventoryPanel.get() ? mInventoryPanel.get()->getItemByID(outbox_id) : NULL; if (outbox_itemp) { diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 1d25a7a1f9..9c9b04d03d 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -42,6 +42,8 @@ #include "llclipboard.h" #include "lltrans.h" +//TODO RN: fix use of static cast as much as possible + LLFastTimer::DeclareTimer FT_FILTER_CLIPBOARD("Filter Clipboard"); LLInventoryFilter::FilterOps::FilterOps(const Params& p) @@ -62,37 +64,27 @@ LLInventoryFilter::FilterOps::FilterOps(const Params& p) ///---------------------------------------------------------------------------- /// Class LLInventoryFilter ///---------------------------------------------------------------------------- -LLInventoryFilter::LLInventoryFilter(const std::string& name, const Params& p) -: mName(name), - mModified(FALSE), - mNeedTextRebuild(TRUE), +LLInventoryFilter::LLInventoryFilter(const Params& p) +: mFilterModified(FILTER_NONE), mEmptyLookupMessage("InventoryNoMatchingItems"), - mFilterOps(p.filter_ops) + mFilterOps(p.filter_ops), + mOrder(p.sort_order), + mFilterSubString(p.substring), + mLastSuccessGeneration(0), + mLastFailGeneration(S32_MAX), + mFirstSuccessGeneration(0), + mFilterCount(0) { - mOrder = p.sort_order; // This gets overridden by a pref immediately - - mFilterSubString(p.substring); - mLastSuccessGeneration = 0; - mLastFailGeneration = S32_MAX; - getFirstSuccessGeneration = 0; - mFilterCount = 0; mNextFilterGeneration = mLastSuccessGeneration + 1; - mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff"); - mFilterBehavior = FILTER_NONE; - // copy mFilterOps into mDefaultFilterOps markDefault(); } -LLInventoryFilter::~LLInventoryFilter() -{ -} - -BOOL LLInventoryFilter::check(const LLFolderViewItem* item) +bool LLInventoryFilter::check(const LLFolderViewItem* item) { // Clipboard cut items are *always* filtered so we need this value upfront - const LLFolderViewEventListener* listener = item->getViewModelItem(); + const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE); // If it's a folder and we're showing all folders, return automatically. @@ -140,7 +132,7 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const return false; } - const LLFolderViewModelItemInventory* listener = folder->getViewModelItem(); + const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(folder->getViewModelItem()); if (!listener) { llwarns << "Folder view event listener not found." << llendl; @@ -157,9 +149,9 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const { // when applying a filter, matching folders get their contents downloaded first if (isNotDefault() - && !gInventory.isCategoryComplete(getUUID()))) + && !gInventory.isCategoryComplete(folder_id)) { - LLInventoryModelBackgroundFetch::instance().start(getViewModelItem()->getUUID()); + LLInventoryModelBackgroundFetch::instance().start(folder_id); } // Always check against the clipboard @@ -186,9 +178,9 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const return passed_clipboard; } -BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const { - const LLFolderViewModelItemInventory* listener = item->getViewModelItem(); + const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); if (!listener) return FALSE; LLInventoryType::EType object_type = listener->getInventoryType(); @@ -354,9 +346,9 @@ bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const return true; } -BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const { - const LLFolderViewModelItemInventory* listener = item->getViewModelItem(); + const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); if (!listener) return FALSE; PermissionMask perm = listener->getPermissionMask(); @@ -382,9 +374,9 @@ bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) con return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions; } -BOOL LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const { - const LLFolderViewModelItemInventory* listener = item->getViewModelItem(); + const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); if (!listener) return TRUE; const LLUUID object_id = listener->getUUID(); @@ -409,7 +401,7 @@ std::string::size_type LLInventoryFilter::getStringMatchOffset(LLFolderViewIte return mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; } -BOOL LLInventoryFilter::isDefault() const +bool LLInventoryFilter::isDefault() const { return !isNotDefault(); } @@ -417,7 +409,7 @@ BOOL LLInventoryFilter::isDefault() const // has user modified default filter params? bool LLInventoryFilter::isNotDefault() const { - bool not_default = FALSE; + S32 not_default = 0; not_default |= (mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes); not_default |= (mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes); @@ -430,10 +422,10 @@ bool LLInventoryFilter::isNotDefault() const not_default |= (mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate); not_default |= (mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo); - return not_default; + return not_default != 0; } -BOOL LLInventoryFilter::isActive() const +bool LLInventoryFilter::isActive() const { return mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL || mFilterOps.mFilterCategoryTypes != 0xffffffffffffffffULL @@ -447,16 +439,9 @@ BOOL LLInventoryFilter::isActive() const || mFilterOps.mHoursAgo != 0; } -BOOL LLInventoryFilter::isModified() const -{ - return mModified; -} - -BOOL LLInventoryFilter::isModifiedAndClear() +bool LLInventoryFilter::isModified() const { - BOOL ret = mModified; - mModified = FALSE; - return ret; + return mFilterModified != FILTER_NONE; } void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types) @@ -620,9 +605,10 @@ void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date) void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl) { + static LLCachedControl<U32> s_last_logoff(gSavedSettings, "LastLogoff", 0); if (sl && !isSinceLogoff()) { - setDateRange(mLastLogoff, time_max()); + setDateRange(s_last_logoff(), time_max()); setModified(); } if (!sl && isSinceLogoff()) @@ -641,17 +627,18 @@ void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl) } } -BOOL LLInventoryFilter::isSinceLogoff() const +bool LLInventoryFilter::isSinceLogoff() const { - return (mFilterOps.mMinDate == (time_t)mLastLogoff) && + static LLCachedControl<U32> s_last_logoff(gSavedSettings, "LastLogoff", 0); + + return (mFilterOps.mMinDate == (time_t)s_last_logoff()) && (mFilterOps.mMaxDate == time_max()) && (mFilterOps.mFilterTypes & FILTERTYPE_DATE); } void LLInventoryFilter::clearModified() { - mModified = FALSE; - mFilterBehavior = FILTER_NONE; + mFilterModified = FILTER_NONE; } void LLInventoryFilter::setHoursAgo(U32 hours) @@ -749,27 +736,26 @@ void LLInventoryFilter::resetDefault() setModified(); } -void LLInventoryFilter::setModified(EFilterBehavior behavior) +void LLInventoryFilter::setModified(EFilterModified behavior) { - mModified = TRUE; - mNeedTextRebuild = TRUE; + mFilterText.clear(); mLastSuccessGeneration = mNextFilterGeneration++; - if (mFilterBehavior == FILTER_NONE) + if (mFilterModified == FILTER_NONE) { - mFilterBehavior = behavior; + mFilterModified = behavior; } - else if (mFilterBehavior != behavior) + else if (mFilterModified != behavior) { // trying to do both less restrictive and more restrictive filter // basically means restart from scratch - mFilterBehavior = FILTER_RESTART; + mFilterModified = FILTER_RESTART; } if (isNotDefault()) { // if not keeping current filter results, update last valid as well - switch(mFilterBehavior) + switch(mFilterModified) { case FILTER_RESTART: mLastFailGeneration = mLastSuccessGeneration; @@ -791,29 +777,29 @@ void LLInventoryFilter::setModified(EFilterBehavior behavior) else { // shortcut disabled filters to show everything immediately - mMinRequiredGeneration = 0; - mMustPassGeneration = S32_MAX; + mLastFailGeneration = 0; + mFirstSuccessGeneration = S32_MAX; } } -BOOL LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const +bool LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const { return mFilterOps.mFilterObjectTypes & (1LL << t); } const std::string& LLInventoryFilter::getFilterText() { - if (!mNeedTextRebuild) + if (!mFilterText.empty()) { return mFilterText; } - mNeedTextRebuild = FALSE; std::string filtered_types; std::string not_filtered_types; BOOL filtered_by_type = FALSE; BOOL filtered_by_all_types = TRUE; S32 num_filter_types = 0; + mFilterText.clear(); if (isFilterObjectTypesWith(LLInventoryType::IT_ANIMATION)) @@ -998,9 +984,26 @@ const std::string& LLInventoryFilter::getFilterText() return mFilterText; } + +LLInventoryFilter& LLInventoryFilter::operator=( const LLInventoryFilter& other ) +{ + setFilterObjectTypes(other.getFilterObjectTypes()); + setDateRange(other.getMinDate(), other.getMaxDate()); + setHoursAgo(other.getHoursAgo()); + setShowFolderState(other.getShowFolderState()); + setFilterPermissions(other.getFilterPermissions()); + setFilterSubString(other.getFilterSubString()); + setSortOrder(other.getSortOrder()); + setDateRangeLastLogoff(other.isSinceLogoff()); + return *this; +} + + void LLInventoryFilter::toParams(Params& params) const - { +{ params.filter_ops.types = getFilterObjectTypes(); + params.filter_ops.category_types = getFilterCategoryTypes(); + params.filter_ops.wearable_types = getFilterWearableTypes(); params.filter_ops.date_range.min_date = getMinDate(); params.filter_ops.date_range.max_date = getMaxDate(); params.filter_ops.hours_ago = getHoursAgo(); @@ -1009,16 +1012,18 @@ void LLInventoryFilter::toParams(Params& params) const params.substring = getFilterSubString(); params.sort_order = getSortOrder(); params.since_logoff = isSinceLogoff(); - } +} -void LLInventoryFilter::fromParams(const Params& data) - { +void LLInventoryFilter::fromParams(const Params& params) +{ if (!params.validateBlock()) { return; } setFilterObjectTypes(params.filter_ops.types); + setFilterCategoryTypes(params.filter_ops.category_types); + setFilterWearableTypes(params.filter_ops.wearable_types); setDateRange(params.filter_ops.date_range.min_date, params.filter_ops.date_range.max_date); setHoursAgo(params.filter_ops.hours_ago); setShowFolderState(params.filter_ops.show_folder_state); @@ -1038,7 +1043,12 @@ U64 LLInventoryFilter::getFilterCategoryTypes() const return mFilterOps.mFilterCategoryTypes; } -BOOL LLInventoryFilter::hasFilterString() const +U64 LLInventoryFilter::getFilterWearableTypes() const +{ + return mFilterOps.mFilterWearableTypes; +} + +bool LLInventoryFilter::hasFilterString() const { return mFilterSubString.size() > 0; } @@ -1073,10 +1083,6 @@ U32 LLInventoryFilter::getSortOrder() const { return mOrder; } -const std::string& LLInventoryFilter::getName() const -{ - return mName; -} void LLInventoryFilter::setFilterCount(S32 count) { @@ -1110,8 +1116,8 @@ void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) mEmptyLookupMessage = message; } -RN: turn this into a param -const std::string& LLInventoryFilter::getEmptyLookupMessage() const +// TODO RN: turn this into a param and move to llfolderviewmodelinterface +std::string LLInventoryFilter::getEmptyLookupMessage() const { LLStringUtil::format_map_t args; args["[SEARCH_TERM]"] = LLURI::escape(getFilterSubStringOrig()); @@ -1127,11 +1133,6 @@ bool LLInventoryFilter::areDateLimitsSet() || mFilterOps.mHoursAgo != 0; } -LLInventoryFilter& LLInventoryFilter::operator=( const LLInventoryFilter& other ) -{ - fromParams(other.toParams()); -} - bool LLInventoryFilter::showAllResults() const { return hasFilterString(); @@ -1139,7 +1140,7 @@ bool LLInventoryFilter::showAllResults() const -bool LLInventoryFilter::FilterOps::DateRange::validateBlock( bool emit_errors /*= true*/ ) +bool LLInventoryFilter::FilterOps::DateRange::validateBlock( bool emit_errors /*= true*/ ) const { bool valid = LLInitParam::Block<DateRange>::validateBlock(emit_errors); if (valid) diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 746e9a2820..e0c3d7141b 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -144,16 +144,18 @@ public: {} }; - LLInventoryFilter(const std::string& name, const Params& p); - virtual ~LLInventoryFilter(); + LLInventoryFilter(const Params& p = Params()); + LLInventoryFilter(const LLInventoryFilter& other) { *this = other; } + virtual ~LLInventoryFilter() {} // +-------------------------------------------------------------------+ // + Parameters // +-------------------------------------------------------------------+ - void setFilterObjectTypes(U64 types); U64 getFilterObjectTypes() const; U64 getFilterCategoryTypes() const; + U64 getFilterWearableTypes() const; bool isFilterObjectTypesWith(LLInventoryType::EType t) const; + void setFilterObjectTypes(U64 types); void setFilterCategoryTypes(U64 types); void setFilterUUID(const LLUUID &object_id); void setFilterWearableTypes(U64 types); @@ -209,20 +211,19 @@ public: U32 getSortOrder() const; void setEmptyLookupMessage(const std::string& message); - const std::string& getEmptyLookupMessage() const; + std::string getEmptyLookupMessage() const; // +-------------------------------------------------------------------+ // + Status // +-------------------------------------------------------------------+ bool isActive() const; bool isModified() const; - bool isModifiedAndClear(); bool isSinceLogoff() const; void clearModified(); const std::string& getName() const; const std::string& getFilterText(); //RN: this is public to allow system to externally force a global refilter - void setModified(EFilterBehavior behavior = FILTER_RESTART); + void setModified(EFilterModified behavior = FILTER_RESTART); // +-------------------------------------------------------------------+ // + Count @@ -259,15 +260,12 @@ private: bool areDateLimitsSet(); U32 mOrder; - U32 mLastLogoff; - std::string::size_type mSubStringMatchOffset; FilterOps mFilterOps; FilterOps mDefaultFilterOps; std::string mFilterSubString; std::string mFilterSubStringOrig; - const std::string mName; S32 mLastSuccessGeneration; S32 mLastFailGeneration; @@ -275,10 +273,8 @@ private: S32 mNextFilterGeneration; S32 mFilterCount; - EFilterBehavior mFilterBehavior; + EFilterModified mFilterModified; - BOOL mModified; - BOOL mNeedTextRebuild; std::string mFilterText; std::string mEmptyLookupMessage; }; diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 5cf9c528b0..c6b1da0417 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -418,21 +418,6 @@ public: class LLFolderViewItem; class LLFolderViewFolder; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewFunctor -// -// Simple abstract base class for applying a functor to folders and -// items in a folder view hierarchy. This is suboptimal for algorithms -// that only work folders or only work on items, but I'll worry about -// that later when it's determined to be too slow. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLFolderViewFunctor -{ -public: - virtual ~LLFolderViewFunctor() {} - virtual void doFolder(LLFolderViewFolder* folder) = 0; - virtual void doItem(LLFolderViewItem* item) = 0; -}; class LLInventoryState { @@ -442,49 +427,6 @@ public: static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction }; -class LLSelectFirstFilteredItem : public LLFolderViewFunctor -{ -public: - LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} - virtual ~LLSelectFirstFilteredItem() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - BOOL wasItemSelected() { return mItemSelected; } -protected: - BOOL mItemSelected; -}; - -class LLOpenFilteredFolders : public LLFolderViewFunctor -{ -public: - LLOpenFilteredFolders() {} - virtual ~LLOpenFilteredFolders() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); -}; - -class LLSaveFolderState : public LLFolderViewFunctor -{ -public: - LLSaveFolderState() : mApply(FALSE) {} - virtual ~LLSaveFolderState() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item) {} - void setApply(BOOL apply); - void clearOpenFolders() { mOpenFolders.clear(); } -protected: - std::set<LLUUID> mOpenFolders; - BOOL mApply; -}; - -class LLOpenFoldersWithSelection : public LLFolderViewFunctor -{ -public: - LLOpenFoldersWithSelection() {} - virtual ~LLOpenFoldersWithSelection() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); -}; #endif // LL_LLINVENTORYFUNCTIONS_H diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 401daf6353..e739694fe0 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -76,7 +76,7 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) { LLFastTimer _(FTM_INVENTORY_SORT); - if (!needsSort(folder)) return; + if (!needsSort(folder->getViewModelItem())) return; LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem()); if (modelp->getUUID().isNull()) return; @@ -91,7 +91,7 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) if (child_folderp->getFoldersCount() > 0) { time_t most_recent_folder_time = - static_cast<LLFolderViewModelItemInventory*>(child_folderp->getFoldersBegin()->getViewModelItem())->getCreationDate(); + static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getFoldersBegin())->getViewModelItem())->getCreationDate(); LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); if (most_recent_folder_time > modelp->getCreationDate()) { @@ -101,7 +101,7 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) if (child_folderp->getItemsCount() > 0) { time_t most_recent_item_time = - static_cast<LLFolderViewModelItemInventory*>(child_folderp->getItemsBegin()->getViewModelItem())->getCreationDate(); + static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getItemsBegin())->getViewModelItem())->getCreationDate(); LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); if (most_recent_item_time > modelp->getCreationDate()) @@ -113,6 +113,12 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) base_t::sort(folder); } +bool LLFolderViewModelInventory::contentsReady() +{ + return !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); +} + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryPanelObserver // @@ -243,6 +249,7 @@ void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) root_id); mFolderRoot = createFolderView(new_listener, params.use_label_suffix()); + addItemID(root_id, mFolderRoot); } void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) @@ -314,11 +321,11 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) LLInventoryPanel::~LLInventoryPanel() { - U32 sort_order = getViewModel()->getSortOrder(); - if (mSortOrderSetting != INHERIT_SORT_ORDER) - { - gSavedSettings.setU32(mSortOrderSetting, sort_order); - } + U32 sort_order = getFolderViewModel()->getSorter().getSortOrder(); + if (mSortOrderSetting != INHERIT_SORT_ORDER) + { + gSavedSettings.setU32(mSortOrderSetting, sort_order); + } gIdleCallbacks.deleteFunction(onIdle, this); @@ -346,14 +353,9 @@ void LLInventoryPanel::draw() LLPanel::draw(); } -LLInventoryFilter* LLInventoryPanel::getFilter() -{ - return getViewModel()->getFilter(); -} - const LLInventoryFilter* LLInventoryPanel::getFilter() const { - return getViewModel()->getFilter(); + return &getFolderViewModel()->getFilter(); } void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type) @@ -400,9 +402,9 @@ void LLInventoryPanel::setSortOrder(U32 order) { LLInventorySort sorter(order); getFilter()->setSortOrder(order); - if (order != getViewModel()->getSortOrder()) + if (order != getFolderViewModel()->getSorter().getSortOrder()) { - getViewModel()->setSorter(LLInventorySort(order)); + getFolderViewModel()->setSorter(LLInventorySort(order)); // try to keep selection onscreen, even if it wasn't to start with mFolderRoot->scrollToShowSelection(); } @@ -410,7 +412,7 @@ void LLInventoryPanel::setSortOrder(U32 order) U32 LLInventoryPanel::getSortOrder() const { - return getViewModel()->getSortOrder(); + return getFolderViewModel()->getSorter().getSortOrder(); } void LLInventoryPanel::setSinceLogoff(BOOL sl) @@ -460,6 +462,8 @@ void LLInventoryPanel::modelChanged(U32 mask) const LLUUID& item_id = (*items_iter); const LLInventoryObject* model_item = model->getObject(item_id); LLFolderViewItem* view_item = getItemByID(item_id); + LLFolderViewModelItemInventory* viewmodel_item = + static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL); // LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item // to folder is the fast way to get a folder without searching through folders tree. @@ -493,9 +497,11 @@ void LLInventoryPanel::modelChanged(U32 mask) if (model_item && view_item) { view_item->destroyView(); - removeItemID(view_item->getViewModelItem()->getUUID()); + removeItemID(viewmodel_item->getUUID()); } view_item = buildNewViews(item_id); + viewmodel_item = + static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL); view_folder = dynamic_cast<LLFolderViewFolder *>(view_item); } @@ -563,14 +569,14 @@ void LLInventoryPanel::modelChanged(U32 mask) // Item is to be moved and we found its new parent in the panel's directory, so move the item's UI. view_item->getParentFolder()->extractItem(view_item); view_item->addToFolder(new_parent); - addItemID(view_item->getViewModelItem()->getUUID(), view_item); + addItemID(viewmodel_item->getUUID(), view_item); } else { // Item is to be moved outside the panel's directory (e.g. moved to trash for a panel that // doesn't include trash). Just remove the item's UI. view_item->destroyView(); - removeItemID(view_item->getViewModelItem()->getUUID()); + removeItemID(viewmodel_item->getUUID()); } } } @@ -583,7 +589,7 @@ void LLInventoryPanel::modelChanged(U32 mask) { // Remove the item's UI. view_item->destroyView(); - removeItemID(view_item->getViewModelItem()->getUUID()); + removeItemID(viewmodel_item->getUUID()); } } } @@ -613,16 +619,11 @@ void LLInventoryPanel::onIdle(void *userdata) } } -const LLUUID& LLInventoryPanel::getRootFolderID() const -{ - return mFolderRoot->getViewModelItem()->getUUID(); -} - void LLInventoryPanel::initializeViews() { if (!gInventory.isInventoryUsable()) return; - rebuildViewsFor(getRootFolderID()); + rebuildViewsFor(gInventory.getRootFolderID()); mViewsInitialized = true; @@ -654,7 +655,7 @@ LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id) if (old_view) { old_view->destroyView(); - removeItemID(old_view->getViewModelItem()->getUUID()); + removeItemID(static_cast<LLFolderViewModelItemInventory*>(old_view->getViewModelItem())->getUUID()); } return buildNewViews(id); @@ -727,75 +728,65 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) { LLInventoryObject const* objectp = gInventory.getObject(id); - LLUUID root_id = mFolderRoot->getViewModelItem()->getUUID(); - LLFolderViewFolder* parent_folder = NULL; - LLFolderViewItem* itemp = NULL; - if (id == root_id) - { - parent_folder = mFolderRoot; - } - else if (objectp) - { - const LLUUID &parent_id = objectp->getParentUUID(); - parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); - - if (parent_folder) + if (!objectp) return NULL; + + LLFolderViewItem* folder_view_item = getItemByID(id); + LLFolderViewFolder* parent_folder = folder_view_item->getParentFolder(); + + if (!folder_view_item && parent_folder) + { + if (objectp->getType() <= LLAssetType::AT_NONE || + objectp->getType() >= LLAssetType::AT_COUNT) { - if (objectp->getType() <= LLAssetType::AT_NONE || - objectp->getType() >= LLAssetType::AT_COUNT) - { - llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " - << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() - << llendl; - return NULL; - } + llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " + << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() + << llendl; + return NULL; + } - if ((objectp->getType() == LLAssetType::AT_CATEGORY) && - (objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)) + if ((objectp->getType() == LLAssetType::AT_CATEGORY) && + (objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)) + { + LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(), + objectp->getType(), + LLInventoryType::IT_CATEGORY, + this, + mFolderRoot, + objectp->getUUID()); + if (new_listener) { - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(), - objectp->getType(), - LLInventoryType::IT_CATEGORY, - this, - mFolderRoot, - objectp->getUUID()); - if (new_listener) - { - itemp = createFolderViewFolder(new_listener); - } + folder_view_item = createFolderViewFolder(new_listener); } - else - { - // Build new view for item. - LLInventoryItem* item = (LLInventoryItem*)objectp; - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(), - item->getActualType(), - item->getInventoryType(), - this, - mFolderRoot, - item->getUUID(), - item->getFlags()); + } + else + { + // Build new view for item. + LLInventoryItem* item = (LLInventoryItem*)objectp; + LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(), + item->getActualType(), + item->getInventoryType(), + this, + mFolderRoot, + item->getUUID(), + item->getFlags()); - if (new_listener) - { - itemp = createFolderViewItem(new_listener); - } + if (new_listener) + { + folder_view_item = createFolderViewItem(new_listener); } + } - if (itemp) - { - itemp->addToFolder(parent_folder); - addItemID(itemp->getViewModelItem()->getUUID(), itemp); - } - } + if (folder_view_item) + { + folder_view_item->addToFolder(parent_folder); + addItemID(id, folder_view_item); + } } // If this is a folder, add the children of the folder and recursively add any // child folders. - if (id.isNull() - || (objectp - && objectp->getType() == LLAssetType::AT_CATEGORY)) + if (folder_view_item && objectp->getType() == LLAssetType::AT_CATEGORY) { LLViewerInventoryCategory::cat_array_t* categories; LLViewerInventoryItem::item_array_t* items; @@ -812,7 +803,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) } } - if(items && parent_folder) + if(items) { for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin(); item_iter != items->end(); @@ -825,7 +816,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) mInventory->unlockDirectDescendentArrays(id); } - return itemp; + return folder_view_item; } // bit of a hack to make sure the inventory is open. @@ -837,7 +828,7 @@ void LLInventoryPanel::openStartFolderOrMyInventory() LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child); if (fchild && fchild->getViewModelItem() - && fchild->getViewModelItem()->getUUID() == gInventory.getRootFolderID()) + && fchild->getViewModelItem()->getName() == "My Inventory") { fchild->setOpen(TRUE); break; @@ -980,7 +971,7 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it mCompletionObserver->reset(); for (std::deque<LLFolderViewItem*>::const_iterator it = items.begin(); it != items.end(); ++it) { - LLUUID id = (*it)->getViewModelItem()->getUUID(); + LLUUID id = static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID(); LLViewerInventoryItem* inv_item = mInventory->getItem(id); if (inv_item && !inv_item->isFinished()) @@ -1028,7 +1019,7 @@ bool LLInventoryPanel::beginIMSession() if(folder_item) { - LLFolderViewEventListener* fve_listener = folder_item->getViewModelItem(); + LLFolderViewModelItemInventory* fve_listener = static_cast<LLFolderViewModelItemInventory*>(folder_item->getViewModelItem()); if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY)) { @@ -1107,13 +1098,13 @@ bool LLInventoryPanel::beginIMSession() bool LLInventoryPanel::attachObject(const LLSD& userdata) { // Copy selected item UUIDs to a vector. - std::set<LLFolderViewItem*> selected_items = mFolderRoot->getSelectionList(); + std::set<LLFolderViewItem*> selected_items = mFolderRoot->getSelectionList(); uuid_vec_t items; - for (std::set<LLFolderViewItem*>::const_iterator set_iter = selected_items.begin(); + for (std::set<LLFolderViewItem*>::const_iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) { - items.push_back((*set_iter)->getItemViewModel()->getUUID()); + items.push_back(static_cast<LLFolderViewModelItemInventory*>((*set_iter)->getViewModelItem())->getUUID()); } // Attach selected items. @@ -1292,10 +1283,6 @@ LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); LLFolderViewItem* LLInventoryPanel::getItemByID(const LLUUID& id) { LLFastTimer _(FTM_GET_ITEM_BY_ID); - if (id == mFolderRoot->getViewModelItem()->getUUID()) - { - return mFolderRoot; - } std::map<LLUUID, LLFolderViewItem*>::iterator map_it; map_it = mItemMap.find(id); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 467c508aa0..cd32b18779 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -66,22 +66,21 @@ public: class LLInventorySort { public: - LLInventorySort(U32 order) - : mSortOrder(0), + LLInventorySort(U32 order = 0) + : mSortOrder(order), mByDate(false), mSystemToTop(false), mFoldersByName(false) { - mSortOrder = order; mByDate = (order & LLInventoryFilter::SO_DATE); mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); } - bool isByDate() { return mByDate; } - U32 getSortOrder() { return mSortOrder; } + bool isByDate() const { return mByDate; } + U32 getSortOrder() const { return mSortOrder; } - bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b); + bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const; private: U32 mSortOrder; bool mByDate; @@ -92,12 +91,16 @@ private: class LLFolderViewModelInventory : public LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> { +public: typedef LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> base_t; virtual ~LLFolderViewModelInventory() {} void sort(LLFolderViewFolder* folder); void requestSort(LLFolderViewFolder* folder); + + bool contentsReady(); + }; @@ -234,7 +237,7 @@ public: void updateSelection(); LLFolderViewModelInventory* getFolderViewModel() { return &mViewModel; } - const LLFolderViewModelInventory* getFolderViewModel() const { return &mViewModel; } + const LLFolderViewModelInventory* getFolderViewModel() const { return &mViewModel; } protected: void openStartFolderOrMyInventory(); // open the first level of inventory @@ -287,8 +290,7 @@ public: void addHideFolderType(LLFolderType::EType folder_type); public: - BOOL getIsViewsInitialized() const { return mViewsInitialized; } - const LLUUID& getRootFolderID() const; + BOOL getIsViewsInitialized() const { return mViewsInitialized; } protected: // Builds the UI. Call this once the inventory is usable. void initializeViews(); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 240c5b2da4..ae68b5ce95 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1542,7 +1542,7 @@ void LLPanelObjectInventory::reset() p.folder_indentation = -14; // subtract space normally reserved for folder expanders mFolders = LLUICtrlFactory::create<LLFolderView>(p); // this ensures that we never say "searching..." or "no items found" - RN: make this happen by manipulating filter object directly + //TODO RN: make this happen by manipulating filter object directly //mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h index 6aa349f0f3..e8b2808d4f 100644 --- a/indra/newview/llsidepanelinventory.h +++ b/indra/newview/llsidepanelinventory.h @@ -63,8 +63,7 @@ public: BOOL isMainInventoryPanelActive() const; void clearSelections(bool clearMain, bool clearInbox); - std::set<LLFolderViewItem*> getInboxSelectionList(); - std::set<LLUUID> getInboxSelectionList(); + std::set<LLFolderViewItem*> getInboxSelectionList(); void showItemInfoPanel(); void showTaskInfoPanel(); -- cgit v1.2.3 From b882fe3b8dde9338c092922672015f975ca09587 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 18 Jun 2012 22:51:33 -0700 Subject: CHUI-146 : Refocus on the first conversation when closing another conversation, don't let focus falls out --- indra/newview/llimfloatercontainer.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index bedf3315e8..04fb2f3b9a 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -405,6 +405,15 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id) panel_rect.getWidth(), panel_rect.getHeight() - item_height*(index+1))); } + + // Don't let the focus fall IW, select and refocus on the first conversation in the list + setFocus(TRUE); + conversations_items_map::iterator item_it = mConversationsItems.begin(); + if (item_it != mConversationsItems.end()) + { + LLConversationItem* item = item_it->second; + item->selectItem(); + } return; } -- cgit v1.2.3 From 18aabdfd3d2efc1b5507e2fe001cfc36ee84b710 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Tue, 19 Jun 2012 09:44:40 +0300 Subject: CHUI-127 FIXED (Make chat field auto resizable) - Replaced LLLineEditor with newly created LLChatEntry - Moved some functionality (such as setting label) to the LLTextBase as it can be useful to the other derived classes --- indra/llui/CMakeLists.txt | 2 + indra/llui/llaccordionctrltab.cpp | 2 +- indra/llui/llchatentry.cpp | 198 +++++++++++++++++++++ indra/llui/llchatentry.h | 98 ++++++++++ indra/llui/lltextbase.cpp | 122 +++++++++++-- indra/llui/lltextbase.h | 52 +++++- indra/llui/lltexteditor.cpp | 32 ++-- indra/llui/lltexteditor.h | 9 +- indra/newview/llexpandabletextbox.cpp | 4 +- indra/newview/llgrouplist.cpp | 2 +- indra/newview/llimfloater.cpp | 34 ++-- indra/newview/llimfloater.h | 17 +- indra/newview/llpaneltopinfobar.cpp | 2 +- indra/newview/lltoastgroupnotifypanel.cpp | 2 +- indra/newview/lltoastpanel.cpp | 2 +- indra/newview/lltoastscripttextbox.cpp | 2 +- .../skins/default/xui/en/floater_im_session.xml | 9 +- .../newview/skins/default/xui/en/widgets/text.xml | 1 + 18 files changed, 529 insertions(+), 61 deletions(-) create mode 100644 indra/llui/llchatentry.cpp create mode 100644 indra/llui/llchatentry.h (limited to 'indra') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 772f173f17..b50ed2342d 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -34,6 +34,7 @@ set(llui_SOURCE_FILES llbadgeholder.cpp llbadgeowner.cpp llbutton.cpp + llchatentry.cpp llcheckboxctrl.cpp llclipboard.cpp llcombobox.cpp @@ -133,6 +134,7 @@ set(llui_HEADER_FILES llbadgeowner.h llbutton.h llcallbackmap.h + llchatentry.h llcheckboxctrl.h llclipboard.h llcombobox.h diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index c025cd7939..43462bd244 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -184,7 +184,7 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitleFontStyle(std::string if (mHeaderTextbox) { std::string text = mHeaderTextbox->getText(); - mStyleParams.font(mHeaderTextbox->getDefaultFont()); + mStyleParams.font(mHeaderTextbox->getFont()); mStyleParams.font.style(style); mHeaderTextbox->setText(text, mStyleParams); } diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp new file mode 100644 index 0000000000..6f51705b90 --- /dev/null +++ b/indra/llui/llchatentry.cpp @@ -0,0 +1,198 @@ +/** + * @file llchatentry.cpp + * @brief LLChatEntry implementation + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llchatentry.h" + +static LLDefaultChildRegistry::Register<LLChatEntry> r("text_editor"); + +LLChatEntry::LLChatEntry::Params::Params() +: has_history("has_history", true), + is_expandable("is_expandable", false), + expand_lines_count("expand_lines_count", 1) +{} + +LLChatEntry::LLChatEntry(const Params& p) +: LLTextEditor(p), + mTextExpandedSignal(NULL), + mHasHistory(p.has_history), + mIsExpandable(p.is_expandable), + mExpandLinesCount(p.expand_lines_count), + mPrevLinesCount(0) +{ + // Initialize current history line iterator + mCurrentHistoryLine = mLineHistory.begin(); + + mAutoIndent = false; +} + +LLChatEntry::~LLChatEntry() +{ + delete mTextExpandedSignal; +} + +void LLChatEntry::draw() +{ + LLTextEditor::draw(); + + if(mIsExpandable) + { + expandText(); + } +} + +void LLChatEntry::onCommit() +{ + updateHistory(); + LLTextEditor::onCommit(); +} + +boost::signals2::connection LLChatEntry::setTextExpandedCallback(const commit_signal_t::slot_type& cb) +{ + if (!mTextExpandedSignal) + { + mTextExpandedSignal = new commit_signal_t(); + } + return mTextExpandedSignal->connect(cb); +} + +void LLChatEntry::expandText() +{ + int visible_lines_count = llabs(getVisibleLines(true).first - getVisibleLines(true).second); + bool can_expand = getLineCount() <= mExpandLinesCount; + + // true if pasted text has more lines than expand height limit and expand limit is not reached yet + bool text_pasted = (getLineCount() > mExpandLinesCount) && (visible_lines_count < mExpandLinesCount); + + if (mIsExpandable && (can_expand || text_pasted) && getLineCount() != mPrevLinesCount) + { + int lines_height = 0; + if (text_pasted) + { + // text is pasted and now mLineInfoList.size() > mExpandLineCounts and mLineInfoList is not empty, + // so lines_height is the sum of the last 'mExpandLinesCount' lines height + lines_height = (mLineInfoList.end() - mExpandLinesCount)->mRect.mTop - mLineInfoList.back().mRect.mBottom; + } + else + { + lines_height = mLineInfoList.begin()->mRect.mTop - mLineInfoList.back().mRect.mBottom; + } + + int height = mVPad * 2 + lines_height; + + LLRect doc_rect = getRect(); + doc_rect.setOriginAndSize(doc_rect.mLeft, doc_rect.mBottom, doc_rect.getWidth(), height); + setShape(doc_rect); + + mPrevLinesCount = getLineCount(); + + if (mTextExpandedSignal) + { + (*mTextExpandedSignal)(this, LLSD() ); + } + } +} + +// line history support +void LLChatEntry::updateHistory() +{ + // On history enabled, remember committed line and + // reset current history line number. + // Be sure only to remember lines that are not empty and that are + // different from the last on the list. + if (mHasHistory && getLength()) + { + // Add text to history, ignoring duplicates + if (mLineHistory.empty() || getText() != mLineHistory.back()) + { + mLineHistory.push_back(getText()); + } + + mCurrentHistoryLine = mLineHistory.end(); + } +} + +BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask) +{ + BOOL handled = FALSE; + + LLTextEditor::handleSpecialKey(key, mask); + + switch(key) + { + case KEY_RETURN: + if (MASK_NONE == mask) + { + needsReflow(); + } + break; + + case KEY_UP: + if (mHasHistory && MASK_CONTROL == mask) + { + if (!mLineHistory.empty() && mCurrentHistoryLine > mLineHistory.begin()) + { + setText(*(--mCurrentHistoryLine)); + endOfDoc(); + } + else + { + LLUI::reportBadKeystroke(); + } + handled = TRUE; + } + break; + + case KEY_DOWN: + if (mHasHistory && MASK_CONTROL == mask) + { + if (!mLineHistory.empty() && ++mCurrentHistoryLine < mLineHistory.end()) + { + setText(*mCurrentHistoryLine); + endOfDoc(); + } + else if (!mLineHistory.empty() && mCurrentHistoryLine == mLineHistory.end()) + { + std::string empty(""); + setText(empty); + needsReflow(); + endOfDoc(); + } + else + { + LLUI::reportBadKeystroke(); + } + handled = TRUE; + } + break; + + default: + break; + } + + return handled; +} diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h new file mode 100644 index 0000000000..10a4594e83 --- /dev/null +++ b/indra/llui/llchatentry.h @@ -0,0 +1,98 @@ +/** + * @file llchatentry.h + * @author Paul Guslisty + * @brief Text editor widget which is used for user input + * + * Features: + * Optional line history so previous entries can be recalled by CTRL UP/DOWN + * Optional auto-resize behavior on input chat field + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLCHATENTRY_H_ +#define LLCHATENTRY_H_ + +#include "lltexteditor.h" + +class LLChatEntry : public LLTextEditor +{ +public: + + struct Params : public LLInitParam::Block<Params, LLTextEditor::Params> + { + Optional<bool> has_history, + is_expandable; + + Optional<int> expand_lines_count; + + Params(); + }; + + virtual ~LLChatEntry(); + +protected: + + friend class LLUICtrlFactory; + LLChatEntry(const Params& p); + +public: + + virtual void draw(); + virtual void onCommit(); + + boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb); + +private: + + /** + * Implements auto-resize behavior. + * When user's typing reaches the right edge of the chat field + * the chat field expands vertically by one line. The bottom of + * the chat field remains bottom-justified. The chat field does + * not expand beyond mExpandLinesCount. + */ + void expandText(); + + /** + * Implements line history so previous entries can be recalled by CTRL UP/DOWN + */ + void updateHistory(); + + BOOL handleSpecialKey(const KEY key, const MASK mask); + + + // Fired when text height expanded to mExpandLinesCount + commit_signal_t* mTextExpandedSignal; + + // line history support: + typedef std::vector<std::string> line_history_t; + line_history_t::iterator mCurrentHistoryLine; // currently browsed history line + line_history_t mLineHistory; // line history storage + bool mHasHistory; // flag for enabled/disabled line history + bool mIsExpandable; + + int mExpandLinesCount; + int mPrevLinesCount; +}; + +#endif /* LLCHATENTRY_H_ */ diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 7aeeae298f..c112a7e477 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -144,6 +144,7 @@ LLTextBase::Params::Params() : cursor_color("cursor_color"), text_color("text_color"), text_readonly_color("text_readonly_color"), + text_tentative_color("text_tentative_color"), bg_visible("bg_visible", false), border_visible("border_visible", false), bg_readonly_color("bg_readonly_color"), @@ -177,7 +178,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) : LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)), mURLClickSignal(NULL), mMaxTextByteLength( p.max_text_length ), - mDefaultFont(p.font), + mFont(p.font), mFontShadow(p.font_shadow), mPopupMenu(NULL), mReadOnly(p.read_only), @@ -185,6 +186,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mFgColor(p.text_color), mBorderVisible( p.border_visible ), mReadOnlyFgColor(p.text_readonly_color), + mTentativeFgColor(p.text_tentative_color()), mWriteableBgColor(p.bg_writeable_color), mReadOnlyBgColor(p.bg_readonly_color), mFocusBgColor(p.bg_focus_color), @@ -297,21 +299,21 @@ bool LLTextBase::truncate() return did_truncate; } -const LLStyle::Params& LLTextBase::getDefaultStyleParams() +const LLStyle::Params& LLTextBase::getStyleParams() { //FIXME: convert mDefaultStyle to a flyweight http://www.boost.org/doc/libs/1_40_0/libs/flyweight/doc/index.html //and eliminate color member values if (mStyleDirty) { - mDefaultStyle + mStyle .color(LLUIColor(&mFgColor)) // pass linked color instead of copy of mFGColor .readonly_color(LLUIColor(&mReadOnlyFgColor)) .selected_color(LLUIColor(&mTextSelectedColor)) - .font(mDefaultFont) + .font(mFont) .drop_shadow(mFontShadow); mStyleDirty = false; } - return mDefaultStyle; + return mStyle; } void LLTextBase::onValueChange(S32 start, S32 end) @@ -500,11 +502,17 @@ void LLTextBase::drawCursor() void LLTextBase::drawText() { - const S32 text_len = getLength(); - if( text_len <= 0 ) + S32 text_len = getLength(); + + if (text_len <= 0 && mLabel.empty()) { return; } + else if (text_len <= 0 && !mLabel.empty()) + { + text_len = mLabel.length(); + } + S32 selection_left = -1; S32 selection_right = -1; // Draw selection even if we don't have keyboard focus for search/replace @@ -624,7 +632,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s else { // create default editable segment to hold new text - LLStyleConstSP sp(new LLStyle(getDefaultStyleParams())); + LLStyleConstSP sp(new LLStyle(getStyleParams())); default_segment = new LLNormalTextSegment( sp, pos, pos + insert_len, *this); } @@ -749,7 +757,7 @@ void LLTextBase::createDefaultSegment() // ensures that there is always at least one segment if (mSegments.empty()) { - LLStyleConstSP sp(new LLStyle(getDefaultStyleParams())); + LLStyleConstSP sp(new LLStyle(getStyleParams())); LLTextSegmentPtr default_segment = new LLNormalTextSegment( sp, 0, getLength() + 1, *this); mSegments.insert(default_segment); default_segment->linkToDocument(this); @@ -1103,6 +1111,22 @@ void LLTextBase::deselect() mIsSelecting = FALSE; } +void LLTextBase::onFocusReceived() +{ + if (!getLength() && !mLabel.empty()) + { + // delete label which is LLLabelTextSegment + clearSegments(); + } +} + +void LLTextBase::onFocusLost() +{ + if (!getLength() && !mLabel.empty()) + { + resetLabel(); + } +} // Sets the scrollbar from the cursor position void LLTextBase::updateScrollFromCursor() @@ -1688,7 +1712,7 @@ static LLUIImagePtr image_from_icon_name(const std::string& icon_name) void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params) { LLStyle::Params style_params(input_params); - style_params.fillFrom(getDefaultStyleParams()); + style_params.fillFrom(getStyleParams()); S32 part = (S32)LLTextParser::WHOLE; if (mParseHTML && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358). @@ -1770,6 +1794,39 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c appendTextImpl(new_text,input_params); } +void LLTextBase::setLabel(const LLStringExplicit& label) +{ + mLabel = label; + resetLabel(); +} + +BOOL LLTextBase::setLabelArg(const std::string& key, const LLStringExplicit& text ) +{ + mLabel.setArg(key, text); + return TRUE; +} + +void LLTextBase::resetLabel() +{ + if (!getLength() && !mLabel.empty() && !hasFocus()) + { + clearSegments(); + + LLStyle* style = new LLStyle(getStyleParams()); + style->setColor(mTentativeFgColor); + LLStyleConstSP sp(style); + + LLTextSegmentPtr label = new LLLabelTextSegment(sp, 0, getLabel().length() + 1, *this); + insertSegment(label); + } +} + +void LLTextBase::setFont(const LLFontGL* font) +{ + mFont = font; + mStyleDirty = true; +} + void LLTextBase::needsReflow(S32 index) { lldebugs << "reflow on object " << (void*)this << " index = " << mReflowIndex << ", new index = " << index << llendl; @@ -2160,7 +2217,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const { // return default height rect in upper left local_rect = content_window_rect; - local_rect.mBottom = local_rect.mTop - mDefaultFont->getLineHeight(); + local_rect.mBottom = local_rect.mTop - mFont->getLineHeight(); return local_rect; } @@ -2665,7 +2722,7 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele { F32 alpha = LLViewDrawContext::getCurrentContext().mAlpha; - const LLWString &text = mEditor.getWText(); + const LLWString &text = getWText(); F32 right_x = rect.mLeft; if (!mStyle->isVisible()) @@ -2828,7 +2885,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt if (num_chars > 0) { height = mFontHeight; - const LLWString &text = mEditor.getWText(); + const LLWString &text = getWText(); // if last character is a newline, then return true, forcing line break width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars); } @@ -2837,7 +2894,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const { - const LLWString &text = mEditor.getWText(); + const LLWString &text = getWText(); return mStyle->getFont()->charFromPixelOffset(text.c_str(), mStart + start_offset, (F32)segment_local_x_coord, F32_MAX, @@ -2847,7 +2904,7 @@ S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { - const LLWString &text = mEditor.getWText(); + const LLWString &text = getWText(); LLUIImagePtr image = mStyle->getImage(); if( image.notNull()) @@ -2883,7 +2940,7 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin S32 last_char_in_run = mStart + segment_offset + num_chars; // check length first to avoid indexing off end of string if (last_char_in_run < mEnd - && (last_char_in_run >= mEditor.getLength() )) + && (last_char_in_run >= getLength())) { num_chars++; } @@ -2901,6 +2958,39 @@ void LLNormalTextSegment::dump() const llendl; } +/*virtual*/ +const LLWString& LLNormalTextSegment::getWText() const +{ + return mEditor.getWText(); +} + +/*virtual*/ +const S32 LLNormalTextSegment::getLength() const +{ + return mEditor.getLength(); +} + +LLLabelTextSegment::LLLabelTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor ) +: LLNormalTextSegment(style, start, end, editor) +{ +} + +LLLabelTextSegment::LLLabelTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible) +: LLNormalTextSegment(color, start, end, editor, is_visible) +{ +} + +/*virtual*/ +const LLWString& LLLabelTextSegment::getWText() const +{ + return mEditor.getWlabel(); +} +/*virtual*/ +const S32 LLLabelTextSegment::getLength() const +{ + return mEditor.getLabel().length(); +} + // // LLOnHoverChangeableTextSegment // diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 0549141b72..412272b352 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -105,7 +105,7 @@ class LLNormalTextSegment : public LLTextSegment public: LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor ); LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE); - ~LLNormalTextSegment(); + virtual ~LLNormalTextSegment(); /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const; @@ -130,6 +130,9 @@ public: protected: F32 drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, LLRect rect); + virtual const LLWString& getWText() const; + virtual const S32 getLength() const; + protected: class LLTextBase& mEditor; LLStyleConstSP mStyle; @@ -139,6 +142,21 @@ protected: boost::signals2::connection mImageLoadedConnection; }; +// This text segment is the same as LLNormalTextSegment, the only difference +// is that LLNormalTextSegment draws value of LLTextBase (LLTextBase::getWText()), +// but LLLabelTextSegment draws label of the LLTextBase (LLTextBase::mLabel) +class LLLabelTextSegment : public LLNormalTextSegment +{ +public: + LLLabelTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor ); + LLLabelTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE); + +protected: + + /*virtual*/ const LLWString& getWText() const; + /*virtual*/ const S32 getLength() const; +}; + // Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment) class LLOnHoverChangeableTextSegment : public LLNormalTextSegment { @@ -249,6 +267,7 @@ public: Optional<LLUIColor> cursor_color, text_color, text_readonly_color, + text_tentative_color, bg_readonly_color, bg_writeable_color, bg_focus_color, @@ -311,6 +330,9 @@ public: /*virtual*/ BOOL canDeselect() const; /*virtual*/ void deselect(); + virtual void onFocusReceived(); + virtual void onFocusLost(); + // used by LLTextSegment layout code bool getWordWrap() { return mWordWrap; } bool getUseEllipses() { return mUseEllipses; } @@ -330,6 +352,21 @@ public: const LLWString& getWText() const; void appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params = LLStyle::Params()); + + void setLabel(const LLStringExplicit& label); + virtual BOOL setLabelArg(const std::string& key, const LLStringExplicit& text ); + + const std::string& getLabel() { return mLabel.getString(); } + const LLWString& getWlabel() { return mLabel.getWString();} + + /** + * If label is set, draws text label (which is LLLabelTextSegment) + * that is visible when no user text provided and has no focus + */ + void resetLabel(); + + void setFont(const LLFontGL* font); + // force reflow of text void needsReflow(S32 index = 0); @@ -369,7 +406,7 @@ public: bool scrolledToStart(); bool scrolledToEnd(); - const LLFontGL* getDefaultFont() const { return mDefaultFont; } + const LLFontGL* getFont() const { return mFont; } virtual void appendLineBreakSegment(const LLStyle::Params& style_params); virtual void appendImageSegment(const LLStyle::Params& style_params); @@ -469,7 +506,7 @@ protected: void createDefaultSegment(); virtual void updateSegments(); void insertSegment(LLTextSegmentPtr segment_to_insert); - const LLStyle::Params& getDefaultStyleParams(); + const LLStyle::Params& getStyleParams(); // manage lines S32 getLineStart( S32 line ) const; @@ -514,15 +551,16 @@ protected: LLRect mTextBoundingRect; // default text style - LLStyle::Params mDefaultStyle; + LLStyle::Params mStyle; bool mStyleDirty; - const LLFontGL* const mDefaultFont; // font that is used when none specified, can only be set by constructor - const LLFontGL::ShadowType mFontShadow; // shadow style, can only be set by constructor + const LLFontGL* mFont; + const LLFontGL::ShadowType mFontShadow; // colors LLUIColor mCursorColor; LLUIColor mFgColor; LLUIColor mReadOnlyFgColor; + LLUIColor mTentativeFgColor; LLUIColor mWriteableBgColor; LLUIColor mReadOnlyBgColor; LLUIColor mFocusBgColor; @@ -558,6 +596,7 @@ protected: bool mClip; // clip text to widget rect bool mClipPartial; // false if we show lines that are partially inside bounding rect bool mPlainText; // didn't use Image or Icon segments + bool mAutoIndent; S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes // support widgets @@ -573,6 +612,7 @@ protected: // Fired when a URL link is clicked commit_signal_t* mURLClickSignal; + LLUIString mLabel; // text label that is visible when no user text provided }; #endif diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 9720dded6c..4fa6ea085e 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -235,6 +235,7 @@ LLTextEditor::Params::Params() embedded_items("embedded_items", false), ignore_tab("ignore_tab", true), show_line_numbers("show_line_numbers", false), + auto_indent("auto_indent", true), default_color("default_color"), commit_on_focus_lost("commit_on_focus_lost", false), show_context_menu("show_context_menu") @@ -249,6 +250,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : mLastCmd( NULL ), mDefaultColor( p.default_color() ), mShowLineNumbers ( p.show_line_numbers ), + mAutoIndent(p.auto_indent), mCommitOnFocusLost( p.commit_on_focus_lost), mAllowEmbeddedItems( p.embedded_items ), mMouseDownX(0), @@ -256,7 +258,8 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : mTabsToNextField(p.ignore_tab), mPrevalidateFunc(p.prevalidate_callback()), mContextMenu(NULL), - mShowContextMenu(p.show_context_menu) + mShowContextMenu(p.show_context_menu), + mPassDelete(FALSE) { mSourceID.generate(); @@ -1606,7 +1609,10 @@ BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask) { deleteSelection(FALSE); } - autoIndent(); // TODO: make this optional + if (mAutoIndent) + { + autoIndent(); + } } else { @@ -1746,7 +1752,7 @@ BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char) // virtual BOOL LLTextEditor::canDoDelete() const { - return !mReadOnly && ( hasSelection() || (mCursorPos < getLength()) ); + return !mReadOnly && ( !mPassDelete || ( hasSelection() || (mCursorPos < getLength())) ); } void LLTextEditor::doDelete() @@ -1984,7 +1990,7 @@ void LLTextEditor::drawPreeditMarker() return; } - const S32 line_height = mDefaultFont->getLineHeight(); + const S32 line_height = mFont->getLineHeight(); S32 line_start = getLineStart(cur_line); S32 line_y = mVisibleTextRect.mTop - line_height; @@ -2023,16 +2029,16 @@ void LLTextEditor::drawPreeditMarker() S32 preedit_left = mVisibleTextRect.mLeft; if (left > line_start) { - preedit_left += mDefaultFont->getWidth(text, line_start, left - line_start); + preedit_left += mFont->getWidth(text, line_start, left - line_start); } S32 preedit_right = mVisibleTextRect.mLeft; if (right < line_end) { - preedit_right += mDefaultFont->getWidth(text, line_start, right - line_start); + preedit_right += mFont->getWidth(text, line_start, right - line_start); } else { - preedit_right += mDefaultFont->getWidth(text, line_start, line_end - line_start); + preedit_right += mFont->getWidth(text, line_start, line_end - line_start); } if (mPreeditStandouts[i]) @@ -2707,11 +2713,11 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect const LLWString textString(getWText()); const llwchar * const text = textString.c_str(); - const S32 line_height = mDefaultFont->getLineHeight(); + const S32 line_height = mFont->getLineHeight(); if (coord) { - const S32 query_x = mVisibleTextRect.mLeft + mDefaultFont->getWidth(text, current_line_start, query - current_line_start); + const S32 query_x = mVisibleTextRect.mLeft + mFont->getWidth(text, current_line_start, query - current_line_start); const S32 query_y = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2; S32 query_screen_x, query_screen_y; localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y); @@ -2723,17 +2729,17 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect S32 preedit_left = mVisibleTextRect.mLeft; if (preedit_left_position > current_line_start) { - preedit_left += mDefaultFont->getWidth(text, current_line_start, preedit_left_position - current_line_start); + preedit_left += mFont->getWidth(text, current_line_start, preedit_left_position - current_line_start); } S32 preedit_right = mVisibleTextRect.mLeft; if (preedit_right_position < current_line_end) { - preedit_right += mDefaultFont->getWidth(text, current_line_start, preedit_right_position - current_line_start); + preedit_right += mFont->getWidth(text, current_line_start, preedit_right_position - current_line_start); } else { - preedit_right += mDefaultFont->getWidth(text, current_line_start, current_line_end - current_line_start); + preedit_right += mFont->getWidth(text, current_line_start, current_line_end - current_line_start); } const S32 preedit_top = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height; @@ -2810,7 +2816,7 @@ void LLTextEditor::markAsPreedit(S32 position, S32 length) S32 LLTextEditor::getPreeditFontSize() const { - return llround((F32)mDefaultFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); + return llround((F32)mFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); } BOOL LLTextEditor::isDirty() const diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 40821ae9fb..f8f636b876 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -64,7 +64,8 @@ public: ignore_tab, show_line_numbers, commit_on_focus_lost, - show_context_menu; + show_context_menu, + auto_indent; //colors Optional<LLUIColor> default_color; @@ -202,6 +203,8 @@ public: void setShowContextMenu(bool show) { mShowContextMenu = show; } bool getShowContextMenu() const { return mShowContextMenu; } + void setPassDelete(BOOL b) { mPassDelete = b; } + protected: void showContextMenu(S32 x, S32 y); void drawPreeditMarker(); @@ -214,8 +217,8 @@ protected: S32 indentLine( S32 pos, S32 spaces ); void unindentLineBeforeCloseBrace(); + virtual BOOL handleSpecialKey(const KEY key, const MASK mask); BOOL handleNavigationKey(const KEY key, const MASK mask); - BOOL handleSpecialKey(const KEY key, const MASK mask); BOOL handleSelectionKey(const KEY key, const MASK mask); BOOL handleControlKey(const KEY key, const MASK mask); @@ -279,6 +282,7 @@ protected: LLUIColor mDefaultColor; BOOL mShowLineNumbers; + bool mAutoIndent; /*virtual*/ void updateSegments(); void updateLinkSegments(); @@ -321,6 +325,7 @@ private: BOOL mAllowEmbeddedItems; bool mShowContextMenu; bool mParseOnTheFly; + bool mPassDelete; LLUUID mSourceID; diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index 935dcb74b0..a50184460b 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -150,7 +150,7 @@ void LLExpandableTextBox::LLTextBoxEx::showExpandText() std::pair<S32, S32> visible_lines = getVisibleLines(true); S32 last_line = visible_lines.second - 1; - LLStyle::Params expander_style(getDefaultStyleParams()); + LLStyle::Params expander_style(getStyleParams()); expander_style.font.style = "UNDERLINE"; expander_style.color = LLUIColorTable::instance().getColor("HTMLLinkColor"); LLExpanderSegment* expanderp = new LLExpanderSegment(new LLStyle(expander_style), getLineStart(last_line), getLength() + 1, mExpanderLabel, *this); @@ -166,7 +166,7 @@ void LLExpandableTextBox::LLTextBoxEx::hideExpandText() if (mExpanderVisible) { // this will overwrite the expander segment and all text styling with a single style - LLStyleConstSP sp(new LLStyle(getDefaultStyleParams())); + LLStyleConstSP sp(new LLStyle(getStyleParams())); LLNormalTextSegment* segmentp = new LLNormalTextSegment(sp, 0, getLength() + 1, *this); insertSegment(segmentp); diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 2de891565c..aba3d74d87 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -406,7 +406,7 @@ void LLGroupListItem::setActive(bool active) // *BUG: setName() overrides the style params. // Active group should be bold. - LLFontDescriptor new_desc(mGroupNameBox->getDefaultFont()->getFontDesc()); + LLFontDescriptor new_desc(mGroupNameBox->getFont()->getFontDesc()); // *NOTE dzaporozhan // On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 30a9c29ec6..dde7d248dd 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -44,7 +44,7 @@ #include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container #include "llinventoryfunctions.h" //#include "lllayoutstack.h" -#include "lllineeditor.h" +#include "llchatentry.h" #include "lllogchat.h" #include "llscreenchannel.h" #include "llsyswellwindow.h" @@ -64,6 +64,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mLastMessageIndex(-1), mDialog(IM_NOTHING_SPECIAL), mInputEditor(NULL), + mInputEditorTopPad(0), mSavedTitle(), mTypingStart(), mShouldSendTypingState(false), @@ -190,7 +191,9 @@ void LLIMFloater::sendMsg() { if (mInputEditor) { - LLWString text = mInputEditor->getConvertedText(); + LLWString text = mInputEditor->getWText(); + LLWStringUtil::trim(text); + LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. if(!text.empty()) { // Truncate and convert to UTF8 for transport @@ -287,26 +290,26 @@ BOOL LLIMFloater::postBuild() { LLIMConversation::postBuild(); - mInputEditor = getChild<LLLineEditor>("chat_editor"); + mInputEditor = getChild<LLChatEntry>("chat_editor"); mInputEditor->setMaxTextLength(1023); // enable line history support for instant message bar - mInputEditor->setEnableLineHistory(TRUE); LLFontGL* font = LLViewerChat::getChatFont(); mInputEditor->setFont(font); mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) ); mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) ); - mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this ); + mInputEditor->setKeystrokeCallback( boost::bind(onInputEditorKeystroke, _1, this) ); mInputEditor->setCommitOnFocusLost( FALSE ); - mInputEditor->setRevertOnEsc( FALSE ); - mInputEditor->setReplaceNewlinesWithSpaces( FALSE ); mInputEditor->setPassDelete( TRUE ); - childSetCommitCallback("chat_editor", onSendMsg, this); + mInputEditor->setCommitCallback(boost::bind(onSendMsg, _1, this)); + mInputEditor->setTextExpandedCallback(boost::bind(&LLIMFloater::reshapeChatHistory, this)); mChatHistory = getChild<LLChatHistory>("chat_history"); + mInputEditorTopPad = mChatHistory->getRect().mBottom - mInputEditor->getRect().mTop; + setDocked(true); mTypingStart = LLTrans::getString("IM_typing_start_string"); @@ -880,7 +883,7 @@ void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userd } // static -void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata) +void LLIMFloater::onInputEditorKeystroke(LLTextEditor* caller, void* userdata) { LLIMFloater* self = (LLIMFloater*) userdata; std::string text = self->mInputEditor->getText(); @@ -1077,7 +1080,7 @@ private: BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) { LLViewerRegion* region = gAgent.getRegion(); - bool is_region_exist = !!region; + bool is_region_exist = region != NULL; if (is_region_exist) { @@ -1158,6 +1161,17 @@ void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info) } } +void LLIMFloater::reshapeChatHistory() +{ + LLRect chat_rect = mChatHistory->getRect(); + LLRect input_rect = mInputEditor->getRect(); + + int delta_height = chat_rect.mBottom - (input_rect.mTop + mInputEditorTopPad); + + chat_rect.setLeftTopAndSize(chat_rect.mLeft, chat_rect.mTop, chat_rect.getWidth(), chat_rect.getHeight() + delta_height); + mChatHistory->setShape(chat_rect); +} + // static void LLIMFloater::closeHiddenIMToasts() { diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 333340c696..1992bd930c 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -37,7 +37,9 @@ class LLAvatarName; class LLButton; -class LLLineEditor; +class LLChatEntry; +class LLTextEditor; +class LLPanelChatControlPanel; class LLChatHistory; class LLInventoryItem; class LLInventoryCategory; @@ -142,7 +144,7 @@ private: void appendMessage(const LLChat& chat, const LLSD &args = 0); static void onInputEditorFocusReceived( LLFocusableElement* caller,void* userdata ); static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); - static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); + static void onInputEditorKeystroke(LLTextEditor* caller, void* userdata); void setTyping(bool typing); void onAddButtonClicked(); void onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names); @@ -161,6 +163,13 @@ private: // Remove the "User is typing..." indicator. void removeTypingIndicator(const LLIMInfo* im_info = NULL); + /** + * Adjusts chat history height to fit vertically with input chat field + * and avoid overlapping, since input chat field can be vertically expanded. + * Implementation: chat history bottom "follows" top+top_pad of input chat field + */ + void reshapeChatHistory(); + static void closeHiddenIMToasts(); static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); @@ -171,9 +180,11 @@ private: LLChatHistory* mChatHistory; + int mInputEditorTopPad; // padding between input field and chat history + EInstantMessage mDialog; LLUUID mOtherParticipantUUID; - LLLineEditor* mInputEditor; + LLChatEntry* mInputEditor; bool mPositioned; std::string mSavedTitle; diff --git a/indra/newview/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp index 280cc11179..854deb00d0 100644 --- a/indra/newview/llpaneltopinfobar.cpp +++ b/indra/newview/llpaneltopinfobar.cpp @@ -230,7 +230,7 @@ void LLPanelTopInfoBar::buildLocationString(std::string& loc_str, bool show_coor void LLPanelTopInfoBar::setParcelInfoText(const std::string& new_text) { LLRect old_rect = getRect(); - const LLFontGL* font = mParcelInfoText->getDefaultFont(); + const LLFontGL* font = mParcelInfoText->getFont(); S32 new_text_width = font->getWidth(new_text); mParcelInfoText->setText(new_text); diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index 707d2d9765..ed350ea144 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -112,7 +112,7 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(const LLNotificationPtr& notifi style.font = date_font; pMessageText->appendText(timeStr + "\n", TRUE, style); - style.font = pMessageText->getDefaultFont(); + style.font = pMessageText->getFont(); pMessageText->appendText(message, TRUE, style); //attachment diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index e20d516392..09f8dcf83c 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -68,7 +68,7 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount) if (message->getVisible()) { S32 heightDelta = 0; - S32 maxTextHeight = message->getDefaultFont()->getLineHeight() * maxLineCount; + S32 maxTextHeight = message->getFont()->getLineHeight() * maxLineCount; LLRect messageRect = message->getRect(); S32 oldTextHeight = messageRect.getHeight(); diff --git a/indra/newview/lltoastscripttextbox.cpp b/indra/newview/lltoastscripttextbox.cpp index 2529ec865a..45fbabad59 100644 --- a/indra/newview/lltoastscripttextbox.cpp +++ b/indra/newview/lltoastscripttextbox.cpp @@ -65,7 +65,7 @@ LLToastScriptTextbox::LLToastScriptTextbox(const LLNotificationPtr& notification pMessageText->clear(); LLStyle::Params style; - style.font = pMessageText->getDefaultFont(); + style.font = pMessageText->getFont(); pMessageText->appendText(message, TRUE, style); //submit button diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index a4695b8c09..f6d5b20a65 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -242,18 +242,21 @@ bottom="-1" follows="left|right|bottom" tab_group="1"> - <line_editor + <text_editor bottom="0" + expand_lines_count="5" follows="left|right|bottom" font="SansSerifSmall" visible="true" height="20" + is_expandable="true" label="To" layout="bottomleft" name="chat_editor" tab_group="3" - width="220"> - </line_editor> + width="240" + wrap="true"> + </text_editor> </panel> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/en/widgets/text.xml b/indra/newview/skins/default/xui/en/widgets/text.xml index 134f2d7522..2102074674 100644 --- a/indra/newview/skins/default/xui/en/widgets/text.xml +++ b/indra/newview/skins/default/xui/en/widgets/text.xml @@ -9,6 +9,7 @@ h_pad="0" allow_scroll="false" text_readonly_color="LabelTextColor" + text_tentative_color="TextFgTentativeColor" bg_writeable_color="FloaterDefaultBackgroundColor" use_ellipses="false" bg_visible="false" -- cgit v1.2.3 From ad4ae5583534197cb00c13d769e504fcde4d19d5 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Tue, 19 Jun 2012 20:37:07 +0300 Subject: Win build fix --- indra/llui/llchatentry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index 6f51705b90..1da7900f59 100644 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -30,7 +30,7 @@ static LLDefaultChildRegistry::Register<LLChatEntry> r("text_editor"); -LLChatEntry::LLChatEntry::Params::Params() +LLChatEntry::Params::Params() : has_history("has_history", true), is_expandable("is_expandable", false), expand_lines_count("expand_lines_count", 1) -- cgit v1.2.3 From c0842339e72b15331a5bbb6bd41324c28916d678 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 19 Jun 2012 15:05:20 -0700 Subject: CHUI-138 : Suppress chiclets for conversations when using tabbed UI; Make sure list is cleaned up on close --- indra/newview/llchicletbar.cpp | 9 ++++++++- indra/newview/llimfloater.cpp | 20 ++++++++++---------- 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index 8701b602ce..54a49ca49c 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -102,6 +102,13 @@ void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& nam // no need to spawn chiclets for participants in P2P calls called through Avaline if (session->isP2P() && session->isOtherParticipantAvaline()) return; + // Do not spawn chiclet when using the new multitab conversation UI + if (LLIMConversation::isChatMultiTab()) + { + LLIMFloater::addToHost(session_id); + return; + } + if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return; LLIMChiclet* chiclet = createIMChiclet(session_id); @@ -109,7 +116,7 @@ void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& nam { chiclet->setIMSessionName(name); chiclet->setOtherParticipantId(other_participant_id); - + LLIMFloater::onIMChicletCreated(session_id); } diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 882637151d..4b954de738 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -109,6 +109,16 @@ void LLIMFloater::onFocusReceived() // virtual void LLIMFloater::onClose(bool app_quitting) { + // Always suppress the IM from the conversations list on close if present for any reason + if (LLIMConversation::isChatMultiTab()) + { + LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); + if (im_box) + { + im_box->removeConversationListItem(mSessionID); + } + } + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( mSessionID); @@ -140,16 +150,6 @@ void LLIMFloater::onClose(bool app_quitting) // Last change: // EXT-3516 X Button should end IM session, _ button should hide gIMMgr->leaveSession(mSessionID); - - // Suppress the IM from the conversations list - if (LLIMConversation::isChatMultiTab()) - { - LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); - if (im_box) - { - im_box->removeConversationListItem(mSessionID); - } - } } /* static */ -- cgit v1.2.3 From 49596f4b7fca83dbd7e49ee0780ac6f5574a5746 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 19 Jun 2012 16:41:08 -0700 Subject: CHUI-148 : Fix reattaching on a hidden message panel; also prevents recreation of list items (eventually lead to crashes). --- indra/newview/llimfloatercontainer.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 10188febab..fb5697e2f2 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -123,7 +123,11 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, openFloater(floaterp->getKey()); return; } + + // Make sure the message panel is open when adding a floater or it stays mysteriously hidden + collapseMessagesPane(false); + // Add the floater LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); LLUUID session_id = floaterp->getKey(); @@ -355,6 +359,14 @@ void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) // CHUI-137 : Temporary implementation of conversations list void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp) { + // Check if the item is not already in the list, exit if it is (nothing to do) + // Note: this happens often, when reattaching a torn off conversation for instance + conversations_items_map::iterator item_it = mConversationsItems.find(uuid); + if (item_it != mConversationsItems.end()) + { + return; + } + // Create a conversation item LLConversationItem* item = new LLConversationItem(name, uuid, floaterp, containerp); mConversationsItems[uuid] = item; -- cgit v1.2.3 From c8857cc72270479ed3a5a04b14be3361b2eafea9 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 19 Jun 2012 19:25:58 -0700 Subject: CHUI-142 : Changes to chat related preferences --- indra/newview/app_settings/settings.xml | 15 +----- indra/newview/llfloaterpreference.cpp | 6 --- indra/newview/llimconversation.cpp | 3 +- .../default/xui/en/panel_preferences_chat.xml | 58 ---------------------- 4 files changed, 3 insertions(+), 79 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 46c29e32e2..feb80a3611 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1538,7 +1538,7 @@ <key>Type</key> <string>S32</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>ChatBubbleOpacity</key> <map> @@ -1617,17 +1617,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>ChatWindow</key> - <map> - <key>Comment</key> - <string>Show chat in multiple windows(by default) or in one multi-tabbed window(requires restart)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>0</integer> - </map> <key>CheesyBeacon</key> <map> <key>Comment</key> @@ -9809,7 +9798,7 @@ <key>ShowScriptErrorsLocation</key> <map> <key>Comment</key> - <string>Show script error in chat or window</string> + <string>Show script error in chat (0) or window (1).</string> <key>Persist</key> <integer>1</integer> <key>Type</key> diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 18ab9dc264..996cf1e212 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -423,8 +423,6 @@ void LLFloaterPreference::saveAvatarProperties( void ) BOOL LLFloaterPreference::postBuild() { -// gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); - gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLViewerChat::signalChatFontChanged)); @@ -542,8 +540,6 @@ void LLFloaterPreference::apply() // LLWString busy_response = utf8str_to_wstring(getChild<LLUICtrl>("busy_response")->getValue().asString()); // LLWStringUtil::replaceTabsWithSpaces(busy_response, 4); - - gSavedSettings.setBOOL("PlainTextChatHistory", getChild<LLUICtrl>("plain_text_chat_history")->getValue().asBoolean()); if (mGotPersonalInfo) { @@ -1412,8 +1408,6 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im getChild<LLUICtrl>("online_visibility")->setLabelArg("[DIR_VIS]", mDirectoryVisibility); getChildView("send_im_to_email")->setEnabled(TRUE); getChild<LLUICtrl>("send_im_to_email")->setValue(im_via_email); - getChildView("plain_text_chat_history")->setEnabled(TRUE); - getChild<LLUICtrl>("plain_text_chat_history")->setValue(gSavedSettings.getBOOL("PlainTextChatHistory")); getChildView("log_instant_messages")->setEnabled(TRUE); // getChildView("log_chat")->setEnabled(TRUE); // getChildView("busy_response")->setEnabled(TRUE); diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index ead87e3ed5..c3dba3e49e 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -321,6 +321,5 @@ void LLIMConversation::onTearOffClicked() bool LLIMConversation::isChatMultiTab() { // Restart is required in order to change chat window type. - static bool is_single_window = gSavedSettings.getS32("ChatWindow") == 1; - return is_single_window; + return true; } diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index caf7fc85f5..d7a7f7d735 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -75,15 +75,6 @@ name="send_im_to_email" top_pad="5" width="400" /> - <check_box - enabled="false" - height="16" - label="Enable plain text IM and chat history" - layout="topleft" - left_delta="0" - name="plain_text_chat_history" - top_pad="5" - width="400" /> <check_box control_name="UseChatBubbles" follows="left|top" @@ -94,55 +85,6 @@ top_pad="5" name="bubble_text_chat" width="150" /> - <text - name="show_ims_in_label" - follows="left|top" - layout="topleft" - left="30" - height="20" - width="170" - top_pad="15"> - Show IMs in: - </text> - <text - name="requires_restart_label" - follows="left|top" - layout="topleft" - top_delta="0" - left="170" - height="20" - width="130" - text_color="White_25"> - (requires restart) - </text> - <radio_group - follows="left|top" - height="30" - left="40" - control_name="ChatWindow" - name="chat_window" - top_pad="0" - tool_tip="Show your Instant Messages in separate floaters, or in one floater with many tabs (Requires restart)" - width="150"> - <radio_item - height="16" - label="Separate Windows" - layout="topleft" - left="0" - name="radio" - value="0" - top="0" - width="150" /> - <radio_item - height="16" - label="Tabs" - layout="topleft" - left_delta="0" - name="radio2" - value="1" - top_pad="5" - width="150" /> - </radio_group> <text name="disable_toast_label" follows="left|top" -- cgit v1.2.3 From 9e49fb558f894a1960d208114b8c051536f58c9e Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 19 Jun 2012 22:36:12 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose added more casts to LLFolderViewModelItemInventory, etc. to fix compile errors --- indra/newview/llavataractions.cpp | 4 +- indra/newview/llinventorybridge.cpp | 42 +++------- indra/newview/llinventorybridge.h | 11 +-- indra/newview/llinventorypanel.cpp | 6 ++ indra/newview/llinventorypanel.h | 1 + indra/newview/llpanellandmarks.cpp | 94 +++++++++++----------- indra/newview/llpanellandmarks.h | 2 + indra/newview/llpanelmaininventory.cpp | 6 +- indra/newview/llpanelmarketplaceinbox.cpp | 8 +- indra/newview/llpanelmarketplaceinboxinventory.cpp | 2 +- indra/newview/llpanelobjectinventory.cpp | 21 +++-- indra/newview/lltexturectrl.cpp | 2 +- 12 files changed, 103 insertions(+), 96 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 68dc7681cc..b154dd458c 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -733,7 +733,7 @@ std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs() it != end_it; ++it) { - inventory_selected_uuids.insert((*it)->getListener()->getUUID()); + inventory_selected_uuids.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); } return inventory_selected_uuids; } @@ -778,7 +778,7 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL const std::set<LLFolderViewItem*>::const_iterator it_end = inventory_selected.end(); for (; it != it_end; ++it) { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory((*it)->getItemViewModel()->getUUID()); + LLViewerInventoryCategory* inv_cat = gInventory.getCategory(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); // any category can be offered. if (inv_cat) { diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 312b7314a1..44d0fdd3dd 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -895,7 +895,7 @@ LLInventoryModel* LLInvFVBridge::getInventoryModel() const return panel ? panel->getModel() : NULL; } -LLInventoryFilter* getInventoryFilter() const +LLInventoryFilter* LLInvFVBridge::getInventoryFilter() const { LLInventoryPanel* panel = mInventoryPanel.get(); return panel ? panel->getFilter() : NULL; @@ -1278,7 +1278,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const LLFolderViewFolder * object_folderp = mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(object_id) : NULL; if (object_folderp) { - can_list = !object_folderp->isLoading(); + can_list = !static_cast<LLFolderBridge*>(object_folderp->getViewModelItem())->isLoading(); } } @@ -1319,7 +1319,7 @@ LLToolDragAndDrop::ESource LLInvFVBridge::getDragSource() const return LLToolDragAndDrop::SOURCE_LIBRARY; } - return SOURCE_VIEWER; + return LLToolDragAndDrop::SOURCE_VIEWER; } @@ -1534,7 +1534,7 @@ PermissionMask LLItemBridge::getPermissionMask() const return perm_mask; } -void LLItemBridge::buildDisplayName() +void LLItemBridge::buildDisplayName() const { if(getItem()) { @@ -1817,7 +1817,7 @@ void LLFolderBridge::selectItem() LLInventoryModelBackgroundFetch::instance().start(getUUID(), true); } -void LLFolderBridge::buildDisplayName() +void LLFolderBridge::buildDisplayName() const { LLFolderType::EType preferred_type = getPreferredType(); @@ -1845,7 +1845,7 @@ void LLFolderBridge::buildDisplayName() //can not be detected as protected with LLFolderType::lookupIsProtectedType if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) { - LLTrans::findString(mDisplayName, "InvFolder " + getName()); + LLTrans::findString(mDisplayName, std::string("InvFolder ") + getName(), LLSD()); }; } @@ -1859,7 +1859,7 @@ void LLFolderBridge::update() possibly_has_children = true; } - BOOL loading = (possibly_has_children + bool loading = (possibly_has_children && !up_to_date ); if (loading != mIsLoading) @@ -3415,7 +3415,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items // Do not call execute() or done() here as if the folder is here, there's likely no point drilling down // This saves lots of time as buildContextMenu() is called a lot delete fetch; - buildContextMenuFolderOptions(flags); + buildContextMenuFolderOptions(flags, items, disabled_items); } else { @@ -3628,23 +3628,6 @@ void LLFolderBridge::pasteClipboard(void* user_data) if(self) self->pasteFromClipboard(); } -void LLFolderBridge::createNewCategory(void* user_data) -{ - LLFolderBridge* bridge = (LLFolderBridge*)user_data; - if(!bridge) return; - LLInventoryModel* model = bridge->getInventoryModel(); - if(!model) return; - LLUUID id; - id = model->createNewCategory(bridge->getUUID(), - LLFolderType::FT_NONE, - LLStringUtil::null); - model->notifyObservers(); - - // At this point, the bridge has probably been deleted, but the - // view is still there. - panel->setSelection(id, TAKE_FOCUS_YES); -} - void LLFolderBridge::createNewShirt(void* user_data) { LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SHIRT); @@ -3830,9 +3813,10 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item) LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback(); LLInventoryPanel* panel = mInventoryPanel.get(); LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; - if (drag_over_item && drag_over_item->getViewModelItem()) + LLFolderViewModelItemInventory* view_model = drag_over_item ? static_cast<LLFolderViewModelItemInventory*>(drag_over_item->getViewModelItem()) : NULL; + if (view_model) { - cb.get()->setTargetLandmarkId(drag_over_item->getViewModelItem()->getUUID()); + cb.get()->setTargetLandmarkId(view_model->getUUID()); } copy_inventory_item( @@ -4032,7 +4016,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, if (itemp) { LLUUID srcItemId = inv_item->getUUID(); - LLUUID destItemId = itemp->getViewModelItem()->getUUID(); + LLUUID destItemId = static_cast<LLFolderViewModelItemInventory*>(itemp->getViewModelItem())->getUUID(); gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); } } @@ -6119,7 +6103,7 @@ void LLLinkFolderBridge::gotoItem() const LLUUID &cat_uuid = getFolderID(); if (!cat_uuid.isNull()) { - LLFolderViewItem *base_folder = mInventoryPanel.get()->getItemByID(cat_uuid) + LLFolderViewItem *base_folder = mInventoryPanel.get()->getItemByID(cat_uuid); if (base_folder) { if (LLInventoryModel* model = getInventoryModel()) diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index bc5ac24c70..d303e8377d 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -176,7 +176,7 @@ protected: mutable std::string mDisplayName; void purgeItem(LLInventoryModel *model, const LLUUID &uuid); - virtual void buildDisplayName(); + virtual void buildDisplayName() const; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -230,7 +230,7 @@ public: protected: BOOL confirmRemoveItem(const LLSD& notification, const LLSD& response); virtual BOOL isItemPermissive() const; - virtual void buildDisplayName(); + virtual void buildDisplayName() const; }; @@ -249,7 +249,7 @@ public: BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg); BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg); - virtual void buildDisplayName(); + virtual void buildDisplayName() const; virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem(); @@ -293,6 +293,8 @@ public: LLViewerInventoryCategory* getCategory() const; LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; } + bool isLoading() { return mIsLoading; } + protected: void buildContextMenuOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items); void buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items); @@ -301,7 +303,6 @@ protected: // Menu callbacks //-------------------------------------------------------------------- static void pasteClipboard(void* user_data); - static void createNewCategory(void* user_data); static void createNewShirt(void* user_data); static void createNewPants(void* user_data); static void createNewShoes(void* user_data); @@ -337,7 +338,7 @@ private: bool mWearables; bool mIsLoading; LLTimer mTimeSinceRequestStart; - std::string mDisplayName; + mutable std::string mDisplayName; LLRootHandle<LLFolderBridge> mHandle; }; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index e739694fe0..d3f6474392 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -600,6 +600,11 @@ LLFolderView* LLInventoryPanel::getRootFolder() return mFolderRoot; } +LLUUID LLInventoryPanel::getRootFolderID() +{ + return static_cast<LLFolderViewModelItemInventory*>(mFolderRoot->getViewModelItem())->getUUID(); +} + // static void LLInventoryPanel::onIdle(void *userdata) @@ -1146,6 +1151,7 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open) if (!floater_inventory) { llwarns << "Could not find My Inventory floater" << llendl; + return FALSE; } diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index cd32b18779..2aa05e1b61 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -203,6 +203,7 @@ public: // This method is called when something has changed about the inventory. void modelChanged(U32 mask); LLFolderView* getRootFolder(); + LLUUID getRootFolderID(); LLScrollContainer* getScrollableContainer() { return mScroller; } void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 54ad2bcb76..901c6379de 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -138,7 +138,7 @@ private: // virtual void LLOpenFolderByID::doFolder(LLFolderViewFolder* folder) { - if (folder->getViewModelItem() && folder->getViewModelItem()->getUUID() == mFolderID) + if (folder->getViewModelItem() && static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem())->getUUID() == mFolderID) { if (!folder->isOpen()) { @@ -281,28 +281,21 @@ void LLLandmarksPanel::onShowOnMap() //virtual void LLLandmarksPanel::onShowProfile() { - LLFolderViewItem* cur_item = getCurSelectedItem(); + LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem(); if(!cur_item) return; - cur_item->getViewModelItem()->performAction(mCurrentSelectedList->getModel(),"about"); + cur_item->performAction(mCurrentSelectedList->getModel(),"about"); } // virtual void LLLandmarksPanel::onTeleport() { - LLFolderViewItem* current_item = getCurSelectedItem(); - if (!current_item) - { - llwarns << "There are no selected list. No actions are performed." << llendl; - return; - } - - LLFolderViewModelItem* listenerp = current_item->getViewModelItem(); - if (listenerp && listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) + LLFolderViewModelItemInventory* view_model_item = getCurSelectedViewModelItem(); + if (view_model_item && view_model_item->getInventoryType() == LLInventoryType::IT_LANDMARK) { - listenerp->openItem(); + view_model_item->openItem(); } } @@ -360,7 +353,7 @@ void LLLandmarksPanel::onSelectorButtonClicked() LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem(); if (!cur_item) return; - LLFolderViewModelItem* listenerp = cur_item->getViewModelItem(); + LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(cur_item->getViewModelItem()); if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) { LLSD key; @@ -417,8 +410,9 @@ void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_ bool LLLandmarksPanel::isLandmarkSelected() const { - LLFolderViewItem* current_item = getCurSelectedItem(); - if(current_item && current_item->getViewModelItem()->getInventoryType() == LLInventoryType::IT_LANDMARK) + LLFolderViewModelItemInventory* current_item = getCurSelectedViewModelItem(); + + if(current_item && current_item->getInventoryType() == LLInventoryType::IT_LANDMARK) { return true; } @@ -440,10 +434,10 @@ bool LLLandmarksPanel::isReceivedFolderSelected() const void LLLandmarksPanel::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb) { - LLFolderViewItem* cur_item = getCurSelectedItem(); - if(cur_item && cur_item->getViewModelItem()->getInventoryType() == LLInventoryType::IT_LANDMARK) + LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem(); + if(cur_item && cur_item->getInventoryType() == LLInventoryType::IT_LANDMARK) { - LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getViewModelItem()->getUUID(), cb); + LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getUUID(), cb); if (landmark) { cb(landmark); @@ -456,6 +450,17 @@ LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem() const return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL; } +LLFolderViewModelItemInventory* LLLandmarksPanel::getCurSelectedViewModelItem() const +{ + LLFolderViewItem* cur_item = getCurSelectedItem(); + if (cur_item) + { + return static_cast<LLFolderViewModelItemInventory*>(cur_item->getViewModelItem()); + } + return NULL; +} + + LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list, const std::string& tab_name, const LLUUID& obj_id, @@ -508,12 +513,12 @@ void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data) // We have to make request to sever to get parcel_id and snaption_id. if(isLandmarkSelected()) { - LLFolderViewItem* cur_item = getCurSelectedItem(); + LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem(); if (!cur_item) return; - LLUUID id = cur_item->getViewModelItem()->getUUID(); + LLUUID id = cur_item->getUUID(); LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id); doActionOnCurSelectedLandmark(boost::bind( - &LLLandmarksPanel::doProcessParcelInfo, this, _1, cur_item, inv_item, parcel_data)); + &LLLandmarksPanel::doProcessParcelInfo, this, _1, getCurSelectedItem(), inv_item, parcel_data)); } } @@ -646,7 +651,7 @@ void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesI // Start background fetch, mostly for My Inventory and Library if (expanded) { - const LLUUID &cat_id = inventory_list->getRootFolderID(); + const LLUUID &cat_id = mCurrentSelectedList->getRootFolderID(); // Just because the category itself has been fetched, doesn't mean its child folders have. /* if (!gInventory.isCategoryComplete(cat_id)) @@ -731,14 +736,9 @@ void LLLandmarksPanel::onActionsButtonClick() { LLToggleableMenu* menu = mGearFolderMenu; - LLFolderViewItem* cur_item = NULL; if(mCurrentSelectedList) { - cur_item = mCurrentSelectedList->getRootFolder()->getCurSelectedItem(); - if(!cur_item) - return; - - LLFolderViewModelItem* listenerp = cur_item->getViewModelItem(); + LLFolderViewModelItemInventory* listenerp = getCurSelectedViewModelItem(); if(!listenerp) return; @@ -776,6 +776,9 @@ void LLLandmarksPanel::onTrashButtonClick() const void LLLandmarksPanel::onAddAction(const LLSD& userdata) const { + LLFolderViewModelItemInventory* view_model = getCurSelectedViewModelItem(); + LLFolderViewItem* item = getCurSelectedItem(); + std::string command_name = userdata.asString(); if("add_landmark" == command_name) { @@ -791,21 +794,21 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const } else if ("category" == command_name) { - LLFolderViewItem* item = getCurSelectedItem(); if (item && mCurrentSelectedList == mLandmarksInventoryPanel) { LLFolderViewModelItem* folder_bridge = NULL; - if (item-> getViewModelItem()->getInventoryType() + + if (view_model->getInventoryType() == LLInventoryType::IT_LANDMARK) { // for a landmark get parent folder bridge folder_bridge = item->getParentFolder()->getViewModelItem(); } - else if (item-> getViewModelItem()->getInventoryType() + else if (view_model->getInventoryType() == LLInventoryType::IT_CATEGORY) { // for a folder get its own bridge - folder_bridge = item->getViewModelItem(); + folder_bridge = view_model; } menu_create_inventory_item(mCurrentSelectedList, @@ -834,9 +837,9 @@ void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const std::string command_name = userdata.asString(); if("copy_slurl" == command_name) { - LLFolderViewItem* cur_item = getCurSelectedItem(); + LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem(); if(cur_item) - LLLandmarkActions::copySLURLtoClipboard(cur_item->getViewModelItem()->getUUID()); + LLLandmarkActions::copySLURLtoClipboard(cur_item->getUUID()); } else if ( "paste" == command_name) { @@ -984,11 +987,6 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const { LLFolderViewItem* item = *iter; - // If no item is found it might be a folder id. - if (!item) - { - item = root_folder_view->getFolderByID(*iter); - } if (!item) return false; if (!canItemBeModified(command_name, item)) return false; @@ -1012,10 +1010,10 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const if ("show_on_map" == command_name) { - LLFolderViewItem* cur_item = root_folder_view->getCurSelectedItem(); + LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem(); if (!cur_item) return false; - LLViewerInventoryItem* inv_item = static_cast<LLViewerInventoryItem*>(static_cast<LLFolderViewModelItemInventory*>(cur_item->getViewModelItem())->getInventoryObject()); + LLViewerInventoryItem* inv_item = dynamic_cast<LLViewerInventoryItem*>(cur_item->getInventoryObject()); if (!inv_item) return false; LLUUID asset_uuid = inv_item->getAssetUUID(); @@ -1105,23 +1103,23 @@ void LLLandmarksPanel::onMenuVisibilityChange(LLUICtrl* ctrl, const LLSD& param) { const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - std::set<LLFolderViewItem*> selected_uuids = root_folder_view->getSelectionList(); + std::set<LLFolderViewItem*> selected_items = root_folder_view->getSelectionList(); // Iterate through selected items to find out if any of these items are in Trash // or all the items are in Trash category. - for (std::set<LLFolderViewItem*>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) + for (std::set<LLFolderViewItem*>::const_iterator iter = selected_items.begin(); iter != selected_items.end(); ++iter) { LLFolderViewItem* item = *iter; // If no item is found it might be a folder id. if (!item) continue; - LLFolderViewModelItem* listenerp = item->getViewModelItem(); + LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem()); if(!listenerp) continue; // Trash category itself should not be included because it can't be // actually restored from trash. - are_all_items_in_trash &= listenerp->isItemInTrash() && (*iter)->getItemViewModel()->getUUID() != trash_id; + are_all_items_in_trash &= listenerp->isItemInTrash() && listenerp->getUUID() != trash_id; // If there are any selected items in Trash including the Trash category itself // we show "Restore Item" in context menu and hide other irrelevant items. @@ -1160,7 +1158,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold bool can_be_modified = false; // landmarks can be modified in any other accordion... - if (item->getViewModelItem()->getInventoryType() == LLInventoryType::IT_LANDMARK) + if (static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem())->getInventoryType() == LLInventoryType::IT_LANDMARK) { can_be_modified = true; @@ -1198,7 +1196,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold if (can_be_modified) { - LLFolderViewModelItemInventory* listenerp = item->getViewModelItem(); + LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem()); if ("cut" == command_name) { diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index b2f4e92473..aa5f69739d 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -44,6 +44,7 @@ class LLMenuGL; class LLToggleableMenu; class LLInventoryPanel; class LLPlacesInventoryPanel; +class LLFolderViewModelItemInventory; class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver { @@ -87,6 +88,7 @@ protected: bool isReceivedFolderSelected() const; void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb); LLFolderViewItem* getCurSelectedItem() const; + LLFolderViewModelItemInventory* getCurSelectedViewModelItem() const; /** * Selects item with "obj_id" in "inventory_list" and scrolls accordion diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index fbdbce61bd..565a7408c2 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -47,6 +47,7 @@ #include "llresmgr.h" #include "llscrollcontainer.h" #include "llsdserialize.h" +#include "llsdparam.h" #include "llspinctrl.h" #include "lltoggleablemenu.h" #include "lltooldraganddrop.h" @@ -230,7 +231,10 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) if (filter) { LLSD filterState; - filter->toLLSD(filterState); + LLInventoryFilter::Params p; + filter->toParams(p); + LLParamSDParser parser; + parser.writeSD(filterState, p); filterRoot[filter->getName()] = filterState; } diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index 8a07d6d516..3547156197 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -143,8 +143,8 @@ U32 LLPanelMarketplaceInbox::getFreshItemCount() const if (inbox_folder) { - LLFolderViewFolder::folders_t::iterator folders_it = inbox_folder->getFoldersBegin(); - LLFolderViewFolder::folders_t::iterator folders_end = inbox_folder->getFoldersEnd(); + LLFolderViewFolder::folders_t::const_iterator folders_it = inbox_folder->getFoldersBegin(); + LLFolderViewFolder::folders_t::const_iterator folders_end = inbox_folder->getFoldersEnd(); for (; folders_it != folders_end; ++folders_it) { @@ -157,8 +157,8 @@ U32 LLPanelMarketplaceInbox::getFreshItemCount() const } } - LLFolderViewFolder::items_t::iterator items_it = inbox_folder->getItemsBegin(); - LLFolderViewFolder::items_t::iterator items_end = inbox_folder->getItemsEnd(); + LLFolderViewFolder::items_t::const_iterator items_it = inbox_folder->getItemsBegin(); + LLFolderViewFolder::items_t::const_iterator items_end = inbox_folder->getItemsEnd(); for (; items_it != items_end; ++items_it) { diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index 1d079adfd3..2947be3c2e 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -30,7 +30,7 @@ #include "llfolderview.h" #include "llfolderviewitem.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llpanellandmarks.h" diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index ae68b5ce95..56df01e150 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -109,6 +109,8 @@ public: /*virtual*/ LLFolderType::EType getPreferredType() const { return LLFolderType::FT_NONE; } virtual const LLUUID& getUUID() const { return mUUID; } virtual time_t getCreationDate() const; + virtual void setCreationDate(time_t creation_date_utc); + virtual LLUIImagePtr getIcon() const; virtual void openItem(); virtual BOOL canOpenItem() const { return FALSE; } @@ -130,11 +132,15 @@ public: virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual void performAction(LLInventoryModel* model, std::string action); virtual BOOL isUpToDate() const { return TRUE; } - virtual BOOL hasChildren() const { return FALSE; } + virtual bool hasChildren() const { return FALSE; } virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; } virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } + virtual EInventorySortGroup getSortGroup() const { return SG_ITEM; } + virtual LLInventoryObject* getInventoryObject() const { return findInvObject(); } + // LLDragAndDropBridge functionality + virtual LLToolDragAndDrop::ESource getDragSource() const { return LLToolDragAndDrop::SOURCE_WORLD; } virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, @@ -338,6 +344,10 @@ time_t LLTaskInvFVBridge::getCreationDate() const return 0; } +void LLTaskInvFVBridge::setCreationDate(time_t creation_date_utc) +{} + + LLUIImagePtr LLTaskInvFVBridge::getIcon() const { const BOOL item_is_multi = (mFlags & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS); @@ -461,7 +471,7 @@ BOOL LLTaskInvFVBridge::removeItem() return FALSE; } -void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewModelItem*>& batch) +void LLTaskInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch) { if (!mPanel) { @@ -703,7 +713,7 @@ public: virtual BOOL renameItem(const std::string& new_name); virtual BOOL isItemRemovable() const; virtual void buildContextMenu(LLMenuGL& menu, U32 flags); - virtual BOOL hasChildren() const; + virtual bool hasChildren() const; virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, @@ -711,6 +721,7 @@ public: std::string& tooltip_msg); virtual BOOL canOpenItem() const { return TRUE; } virtual void openItem(); + virtual EInventorySortGroup getSortGroup() const { return SG_NORMAL_FOLDER; } }; LLTaskCategoryBridge::LLTaskCategoryBridge( @@ -761,7 +772,7 @@ void LLTaskCategoryBridge::buildContextMenu(LLMenuGL& menu, U32 flags) hide_context_entries(menu, items, disabled_items); } -BOOL LLTaskCategoryBridge::hasChildren() const +bool LLTaskCategoryBridge::hasChildren() const { // return TRUE if we have or do know know if we have children. // *FIX: For now, return FALSE - we will know for sure soon enough. @@ -1748,7 +1759,7 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li view = LLUICtrlFactory::create<LLFolderViewItem> (params); } view->addToFolder(folder); - addItemID(view->getViewModelItem()->getUUID(), view); + addItemID(view->getViewModelItem()->getUUID(), view); } } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index a995f07df7..b7fa283dd2 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -623,7 +623,7 @@ void LLFloaterTexturePicker::draw() LLFolderView* folder_view = mInventoryPanel->getRootFolder(); if (!folder_view) return; - LLInventoryFilter* filter = folder_view->getFilter(); + LLInventoryFilter* filter = static_cast<LLInventoryFilter*>(folder_view->getFilter()); if (!filter) return; bool is_filter_active = folder_view->getCompletedFilterGeneration() < filter->getCurrentGeneration() && -- cgit v1.2.3 From 3882e9c177190b22276e1ef3fc39e4cb910820fd Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 20 Jun 2012 00:19:05 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose more compilation fixes, just need to add getName() back to LLInventoryFilter et al --- indra/llinventory/llinventory.cpp | 6 ++++++ indra/newview/llfolderview.cpp | 8 +++++++- indra/newview/llfolderviewitem.cpp | 6 ++++++ indra/newview/llfolderviewitem.h | 4 ++-- indra/newview/llfolderviewmodel.h | 9 --------- indra/newview/llinventorybridge.h | 2 +- indra/newview/llinventoryfilter.h | 1 - indra/newview/llinventorypanel.cpp | 5 +++++ indra/newview/llpanelmaininventory.cpp | 17 ++++++++-------- indra/newview/llpanelmarketplaceinboxinventory.cpp | 23 +++++++++++----------- indra/newview/llpanelobjectinventory.cpp | 1 - indra/newview/llpaneloutfitedit.cpp | 8 ++++---- indra/newview/llplacesinventorypanel.cpp | 2 +- indra/newview/llsidepanelinventory.cpp | 4 ++-- indra/newview/lltexturectrl.cpp | 2 +- indra/newview/llviewerinventory.cpp | 2 +- indra/newview/llviewermessage.cpp | 4 ++-- 17 files changed, 58 insertions(+), 46 deletions(-) (limited to 'indra') diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 784e20ad46..6e54f9d78a 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -509,6 +509,12 @@ U32 LLInventoryItem::getFlags() const return mFlags; } +time_t LLInventoryItem::getCreationDate() const +{ + return mCreationDate; +} + + // virtual void LLInventoryItem::packMessage(LLMessageSystem* msg) const { diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index f0edbb638a..78f4bc1119 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -1976,7 +1976,7 @@ void LLFolderView::doIdle() LLFastTimer t3(FTM_AUTO_SELECT); // select new item only if a filtered item not currently selected LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); - if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->potentiallyFiltered())) + if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->potentiallyHidden())) { // these are named variables to get around gcc not binding non-const references to rvalues // and functor application is inherently non-const to allow for stateful functors @@ -2293,3 +2293,9 @@ S32 LLFolderView::getItemHeight() } return debug_height; } + +//TODO RN: move to llfolderviewmodel.cpp file +bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) +{ + return item->getSortVersion() < mTargetSortVersion; +} diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 6e60ec5e1a..5b73a34d29 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -221,6 +221,12 @@ BOOL LLFolderViewItem::potentiallyVisible() || getLastFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration(); // or we don't know yet } +BOOL LLFolderViewItem::potentiallyHidden() +{ + return !mPassedFilter // didn't pass the filter + || getLastFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration(); // or we don't know yet +} + BOOL LLFolderViewItem::getFiltered() { return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getFirstSuccessGeneration(); diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 9e024d7eea..1f8c12cf73 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -245,8 +245,8 @@ public: BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); S32 getIndentation() { return mIndentation; } - virtual BOOL potentiallyVisible(); // do we know for a fact that this item won't be displayed? - virtual BOOL potentiallyFiltered(); // do we know for a fact that this item has been filtered out? + virtual BOOL potentiallyVisible(); // is the item definitely visible or we haven't made up our minds yet? + virtual BOOL potentiallyHidden(); // did this item not pass the filter or do we not know yet? virtual BOOL getFiltered(); virtual BOOL getFiltered(S32 filter_generation); diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 9bbd7f48cf..631e3eec1c 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -88,7 +88,6 @@ public: virtual bool isActive() const = 0; virtual bool isModified() const = 0; virtual void clearModified() = 0; - virtual const std::string& getName() const = 0; virtual const std::string& getFilterText() = 0; //RN: this is public to allow system to externally force a global refilter virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0; @@ -305,12 +304,4 @@ protected: FilterType mFilter; }; - -bool LLFolderViewModelCommon::needsSort(class LLFolderViewModelItem* item) -{ - return item->getSortVersion() < mTargetSortVersion; -} - - - #endif diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index d303e8377d..111735e198 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -176,7 +176,7 @@ protected: mutable std::string mDisplayName; void purgeItem(LLInventoryModel *model, const LLUUID &uuid); - virtual void buildDisplayName() const; + virtual void buildDisplayName() const {} }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index e0c3d7141b..175a16c401 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -220,7 +220,6 @@ public: bool isModified() const; bool isSinceLogoff() const; void clearModified(); - const std::string& getName() const; const std::string& getFilterText(); //RN: this is public to allow system to externally force a global refilter void setModified(EFilterModified behavior = FILTER_RESTART); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index d3f6474392..f6861d83de 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -358,6 +358,11 @@ const LLInventoryFilter* LLInventoryPanel::getFilter() const return &getFolderViewModel()->getFilter(); } +LLInventoryFilter* LLInventoryPanel::getFilter() +{ + return &getFolderViewModel()->getFilter(); +} + void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type) { if (filter_type == LLInventoryFilter::FILTERTYPE_OBJECT) diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 565a7408c2..e3446fdb3a 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -981,7 +981,7 @@ void LLPanelMainInventory::saveTexture(const LLSD& userdata) return; } - const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); + const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES); if (preview_texture) { @@ -1054,7 +1054,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { return; } - const LLUUID item_id = current_item->getViewModelItem()->getUUID(); + const LLUUID item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); LLViewerInventoryItem *item = gInventory.getItem(item_id); if (item) { @@ -1069,7 +1069,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { return; } - current_item->getViewModelItem()->performAction(getActivePanel()->getModel(), "goto"); + static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->performAction(getActivePanel()->getModel(), "goto"); } if (command_name == "find_links") @@ -1079,7 +1079,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { return; } - const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); + const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); const std::string &item_name = current_item->getViewModelItem()->getName(); mFilterSubString = item_name; LLInventoryFilter *filter = mActivePanel->getFilter(); @@ -1125,9 +1125,8 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) iter != selection_set.end(); ++iter) { - const LLUUID &item_id = (*iter); LLFolderViewItem *item = *iter; - const LLFolderViewModelItemInventory *listener = item->getViewModelItem(); + const LLFolderViewModelItemInventory *listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); llassert(listener); if (!listener) return FALSE; can_delete &= listener->isItemRemovable(); @@ -1145,7 +1144,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) return FALSE; - const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); + const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); const LLViewerInventoryItem *item = gInventory.getItem(item_id); if (item && item->getIsLinkType() && !item->getIsBrokenLink()) { @@ -1161,7 +1160,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) if (selection_set.size() != 1) return FALSE; LLFolderViewItem* current_item = root->getCurSelectedItem(); if (!current_item) return FALSE; - const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); + const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); const LLInventoryObject *obj = gInventory.getObject(item_id); if (obj && !obj->getIsLinkType() && LLAssetType::lookupCanLink(obj->getType())) { @@ -1174,7 +1173,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) return FALSE; - const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); + const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); const LLViewerInventoryItem *item = gInventory.getItem(item_id); if (item && item->getIsBrokenLink()) { diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index 2947be3c2e..d2143783ad 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -208,7 +208,7 @@ void LLInboxFolderViewFolder::computeFreshness() if (last_expansion_utc > 0) { - mFresh = (mCreationDate > last_expansion_utc); + mFresh = (static_cast<LLFolderViewModelItemInventory*>(getViewModelItem())->getCreationDate() > last_expansion_utc); #if DEBUGGING_FRESHNESS if (mFresh) @@ -230,15 +230,16 @@ void LLInboxFolderViewFolder::deFreshify() gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); } -void LLInboxFolderViewFolder::setCreationDate(time_t creation_date_utc) -{ - mCreationDate = creation_date_utc; - - if (mParentFolder == mRoot) - { - computeFreshness(); - } -} +// TODO RN: move this behavior to modelview? +//void LLInboxFolderViewFolder::setCreationDate(time_t creation_date_utc) +//{ +// mCreationDate = creation_date_utc; +// +// if (LLFolderViewItem::mParentFolder == mRoot) +// { +// computeFreshness(); +// } +//} // // LLInboxFolderViewItem Implementation @@ -304,7 +305,7 @@ void LLInboxFolderViewItem::computeFreshness() if (last_expansion_utc > 0) { - mFresh = (mCreationDate > last_expansion_utc); + mFresh = (static_cast<LLFolderViewModelItemInventory*>(getViewModelItem())->getCreationDate() > last_expansion_utc); #if DEBUGGING_FRESHNESS if (mFresh) diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 56df01e150..0ba8c1ce6d 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1759,7 +1759,6 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li view = LLUICtrlFactory::create<LLFolderViewItem> (params); } view->addToFolder(folder); - addItemID(view->getViewModelItem()->getUUID(), view); } } diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index a95d27f992..d690a18477 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -891,7 +891,7 @@ LLPanelOutfitEdit::selection_info_t LLPanelOutfitEdit::getAddMorePanelSelectionT if (result.second == 1) { - result.first = getWearableTypeByItemUUID((*selected_items.begin())->getListener()->getUUID()); + result.first = getWearableTypeByItemUUID(static_cast<LLFolderViewModelItemInventory*>((*selected_items.begin())->getViewModelItem())->getUUID()); } } else if (mWearableItemsList != NULL && mWearableItemsList->getVisible()) @@ -1310,7 +1310,7 @@ void LLPanelOutfitEdit::getCurrentItemUUID(LLUUID& selected_id) LLFolderViewItem* curr_item = mInventoryItemsPanel->getRootFolder()->getCurSelectedItem(); if (!curr_item) return; - LLFolderViewModelItemInventory* listenerp = curr_item->getViewModelItem(); + LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(curr_item->getViewModelItem()); if (!listenerp) return; selected_id = listenerp->getUUID(); @@ -1332,7 +1332,7 @@ void LLPanelOutfitEdit::getSelectedItemsUUID(uuid_vec_t& uuid_list) it != end_it; ++it) { - uuid_list.push_back((*it)->getItemViewModel()->getUUID()); + uuid_list.push_back(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); } } else if (mWearablesListViewPanel->getVisible()) @@ -1384,7 +1384,7 @@ void LLPanelOutfitEdit::saveListSelection() for (std::set<LLFolderViewItem*>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) { - mWearableItemsList->selectItemByUUID((*item_id)->getItemViewModel()->getUUID(), true); + mWearableItemsList->selectItemByUUID(static_cast<LLFolderViewModelItemInventory*>((*item_id)->getViewModelItem())->getUUID(), true); } mWearableItemsList->scrollToShowFirstSelectedItem(); } diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index da5ce7d4b7..1c2d75d88c 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -162,7 +162,7 @@ BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask) // then determine its type and set necessary menu handle if (getCurSelectedItem()) { - LLInventoryType::EType inventory_type = getCurSelectedItem()->getViewModelItem()->getInventoryType(); + LLInventoryType::EType inventory_type = static_cast<LLFolderViewModelItemInventory*>(getCurSelectedItem()->getViewModelItem())->getInventoryType(); inventory_type_menu_handle_t::iterator it_handle = mMenuHandlesByInventoryType.find(inventory_type); if (it_handle != mMenuHandlesByInventoryType.end()) diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index f3d32e7a67..47bd620fc6 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -473,7 +473,7 @@ void LLSidepanelInventory::performActionOnSelection(const std::string &action) } } - current_item->getViewModelItem()->performAction(mPanelMainInventory->getActivePanel()->getModel(), action); + static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->performAction(mPanelMainInventory->getActivePanel()->getModel(), action); } void LLSidepanelInventory::onWearButtonClicked() @@ -663,7 +663,7 @@ LLInventoryItem *LLSidepanelInventory::getSelectedItem() return NULL; } } - const LLUUID &item_id = current_item->getViewModelItem()->getUUID(); + const LLUUID &item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); LLInventoryItem *item = gInventory.getItem(item_id); return item; } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index b7fa283dd2..50d63911ad 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -800,7 +800,7 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem if (items.size()) { LLFolderViewItem* first_item = items.front(); - LLInventoryItem* itemp = gInventory.getItem(first_item->getViewModelItem()->getUUID()); + LLInventoryItem* itemp = gInventory.getItem(static_cast<LLFolderViewModelItemInventory*>(first_item->getViewModelItem())->getUUID()); mNoCopyTextureSelected = FALSE; if (itemp) { diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d827b2b8aa..749a6d22e0 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1375,7 +1375,7 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, llwarns << "Can't create unrecognized type " << type_name << llendl; } } - panel->getRoot()->->setNeedsAutoRename(TRUE); + panel->getRootFolder()->setNeedsAutoRename(TRUE); } LLAssetType::EType LLViewerInventoryItem::getType() const diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 90d144b458..b0e36d756d 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -821,7 +821,7 @@ private: it != end_it; ++it) { - mSelectedItems.insert((*it)->getListener()->getUUID()); + mSelectedItems.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); } } mSelectedItems.erase(mMoveIntoFolderID); @@ -864,7 +864,7 @@ private: it != end_it; ++it) { - selected_items.insert((*it)->getListener()->getUUID()); + selected_items.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); } selected_items.erase(mMoveIntoFolderID); -- cgit v1.2.3 From fd247320ceab3ab6dc6abdf17008618cf3f6a8ff Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 20 Jun 2012 17:51:56 +0300 Subject: CHUI-125 FIXED if a call is accept then open im-session's floater --- indra/newview/llchiclet.h | 7 ++++--- indra/newview/llchicletbar.cpp | 19 ++++++++++++------- indra/newview/llchicletbar.h | 7 ++++--- indra/newview/llimfloatercontainer.cpp | 13 +++++++++++++ indra/newview/llimfloatercontainer.h | 11 ++++++++++- indra/newview/llimview.cpp | 15 +++++++++++++-- indra/newview/llimview.h | 2 ++ indra/newview/llsyswellwindow.h | 1 + 8 files changed, 59 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 3973b6547a..f51d7b622c 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -873,9 +873,10 @@ class LLIMWellChiclet : public LLSysWellChiclet, LLIMSessionObserver { friend class LLUICtrlFactory; public: - virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} - virtual void sessionRemoved(const LLUUID& session_id) { messageCountChanged(LLSD()); } - virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {} + /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} + /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; + /*virtual*/ void sessionRemoved(const LLUUID& session_id) { messageCountChanged(LLSD()); } + /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {} ~LLIMWellChiclet(); protected: diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index 8701b602ce..66c93bd18b 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -57,19 +57,24 @@ LLChicletBar::LLChicletBar(const LLSD&) : mChicletPanel(NULL), mToolbarStack(NULL) { - // Firstly add our self to IMSession observers, so we catch session events - // before chiclets do that. - LLIMMgr::getInstance()->addSessionObserver(this); + // IM floaters are from now managed by LLIMFloaterContainer. + // See LLIMFloaterContainer::sessionVoiceOrIMStarted() and CHUI-125 + +// // Firstly add our self to IMSession observers, so we catch session events +// // before chiclets do that. +// LLIMMgr::getInstance()->addSessionObserver(this); buildFromFile("panel_chiclet_bar.xml"); } LLChicletBar::~LLChicletBar() { - if (!LLSingleton<LLIMMgr>::destroyed()) - { - LLIMMgr::getInstance()->removeSessionObserver(this); - } + // IM floaters are from now managed by LLIMFloaterContainer. + // See LLIMFloaterContainer::sessionVoiceOrIMStarted() and CHUI-125 +// if (!LLSingleton<LLIMMgr>::destroyed()) +// { +// LLIMMgr::getInstance()->removeSessionObserver(this); +// } } LLIMChiclet* LLChicletBar::createIMChiclet(const LLUUID& session_id) diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h index 1427bf95e0..7d0d904810 100644 --- a/indra/newview/llchicletbar.h +++ b/indra/newview/llchicletbar.h @@ -50,9 +50,10 @@ public: LLChicletPanel* getChicletPanel() { return mChicletPanel; } // LLIMSessionObserver observe triggers - virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); - virtual void sessionRemoved(const LLUUID& session_id); - void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); + /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; + /*virtual*/ void sessionRemoved(const LLUUID& session_id); + /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); S32 getTotalUnreadIMCount(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 8493a0e7b8..deeb0e9e0b 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -50,6 +50,9 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) : LLMultiFloater(seed) ,mExpandCollapseBtn(NULL) { + // Firstly add our self to IMSession observers, so we catch session events + LLIMMgr::getInstance()->addSessionObserver(this); + mAutoResize = FALSE; LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); } @@ -61,8 +64,18 @@ LLIMFloaterContainer::~LLIMFloaterContainer() gSavedPerAccountSettings.setBOOL("ConversationsListPaneCollapsed", mConversationsPane->isCollapsed()); gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed()); + + if (!LLSingleton<LLIMMgr>::destroyed()) + { + LLIMMgr::getInstance()->removeSessionObserver(this); + } } +void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) +{ + LLIMFloater::show(session_id); +}; + BOOL LLIMFloaterContainer::postBuild() { mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLIMFloaterContainer::onNewMessageReceived, this, _1)); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index b5b60615b3..239d6a08a3 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -30,6 +30,7 @@ #include <map> #include <vector> +#include "llimview.h" #include "llfloater.h" #include "llmultifloater.h" #include "llavatarpropertiesprocessor.h" @@ -117,7 +118,9 @@ private: }; // CHUI-137 : End -class LLIMFloaterContainer : public LLMultiFloater +class LLIMFloaterContainer + : public LLMultiFloater + , public LLIMSessionObserver { public: LLIMFloaterContainer(const LLSD& seed); @@ -144,6 +147,12 @@ public: LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); + // LLIMSessionObserver observe triggers + /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; + /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id); + /*virtual*/ void sessionRemoved(const LLUUID& session_id) {}; + /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {}; + private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; avatarID_panel_map_t mSessions; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 0d2b1f06b5..4b82596f37 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2582,7 +2582,9 @@ LLUUID LLIMMgr::addSession( { LLDynamicArray<LLUUID> ids; ids.put(other_participant_id); - return addSession(name, dialog, other_participant_id, ids, voice); + LLUUID session_id = addSession(name, dialog, other_participant_id, ids, voice); + notifyObserverSessionVoiceOrIMStarted(session_id); + return session_id; } // Adds a session using the given session_id. If the session already exists @@ -2609,7 +2611,8 @@ LLUUID LLIMMgr::addSession( if (floater_id.notNull()) { - LLIMFloater* im_floater = LLIMFloater::findInstance(floater_id); + LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); + if (im_floater && im_floater->getStartConferenceInSameFloater()) { // The IM floater should be initialized with a new session_id @@ -2936,6 +2939,14 @@ void LLIMMgr::notifyObserverSessionAdded(const LLUUID& session_id, const std::st } } +void LLIMMgr::notifyObserverSessionVoiceOrIMStarted(const LLUUID& session_id) +{ + for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++) + { + (*it)->sessionVoiceOrIMStarted(session_id); + } +} + void LLIMMgr::notifyObserverSessionRemoved(const LLUUID& session_id) { for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++) diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 58a2ac5162..80bf315aa8 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -298,6 +298,7 @@ class LLIMSessionObserver public: virtual ~LLIMSessionObserver() {} virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0; + virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) = 0; virtual void sessionRemoved(const LLUUID& session_id) = 0; virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) = 0; }; @@ -462,6 +463,7 @@ private: static void onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& name, bool is_group); void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + void notifyObserverSessionVoiceOrIMStarted(const LLUUID& session_id); void notifyObserverSessionRemoved(const LLUUID& session_id); void notifyObserverSessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index f497f546aa..8758c8c4e5 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -169,6 +169,7 @@ public: // LLIMSessionObserver observe triggers /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; /*virtual*/ void sessionRemoved(const LLUUID& session_id); /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); -- cgit v1.2.3 From 84c8050ca0a39fe16a40d3fb9870160ad3fbee84 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 20 Jun 2012 21:26:56 +0300 Subject: CHUI-149 [WIP] Add the participant list to the nearby chat as IM-conversation --- indra/newview/llimconversation.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index c3dba3e49e..f12821352b 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -120,8 +120,11 @@ BOOL LLIMConversation::tick() } void LLIMConversation::buildParticipantList() -{ if (mIsNearbyChat) +{ + if (mIsNearbyChat) { + LLLocalSpeakerMgr* speaker_manager = LLLocalSpeakerMgr::getInstance(); + mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false); } else { @@ -212,8 +215,7 @@ void LLIMConversation::updateHeaderAndToolbar() bool is_participant_list_visible = !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel") - && !mIsP2PChat - && !mIsNearbyChat; // *TODO: temporarily disabled for Nearby chat + && !mIsP2PChat; mParticipantListPanel->setVisible(is_participant_list_visible); @@ -223,7 +225,7 @@ void LLIMConversation::updateHeaderAndToolbar() mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); // The button (>>) should be disabled for torn off P2P conversations. - mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat && !mIsNearbyChat); + mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat); if (mDragHandle) { -- cgit v1.2.3 From 316d8fc875d54bfcc7e7eb8d215a4810947bcb71 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 20 Jun 2012 14:58:02 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose fixed final build errors --- indra/newview/llfolderview.cpp | 2 +- indra/newview/llfolderviewmodel.h | 1 + indra/newview/llinventoryfilter.cpp | 3 ++- indra/newview/llinventoryfilter.h | 6 +++++- 4 files changed, 9 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 78f4bc1119..2bc6f26c85 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -183,7 +183,7 @@ LLFolderView::LLFolderView(const Params& p) mNeedsAutoRename(FALSE), mDebugFilters(FALSE), mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME), // This gets overridden by a pref immediately - mFilter(), + mFilter(new LLInventoryFilter(LLInventoryFilter::Params().name(p.title))), mShowSelectionContext(FALSE), mShowSingleSelection(FALSE), mArrangeGeneration(0), diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 631e3eec1c..946943530a 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -88,6 +88,7 @@ public: virtual bool isActive() const = 0; virtual bool isModified() const = 0; virtual void clearModified() = 0; + virtual const std::string& getName() const = 0; virtual const std::string& getFilterText() = 0; //RN: this is public to allow system to externally force a global refilter virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0; diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 9c9b04d03d..c13bb5123e 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -65,7 +65,8 @@ LLInventoryFilter::FilterOps::FilterOps(const Params& p) /// Class LLInventoryFilter ///---------------------------------------------------------------------------- LLInventoryFilter::LLInventoryFilter(const Params& p) -: mFilterModified(FILTER_NONE), +: mName(p.name), + mFilterModified(FILTER_NONE), mEmptyLookupMessage("InventoryNoMatchingItems"), mFilterOps(p.filter_ops), mOrder(p.sort_order), diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 175a16c401..5b92c21a85 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -131,13 +131,15 @@ public: struct Params : public LLInitParam::Block<Params> { + Optional<std::string> name; Optional<FilterOps::Params> filter_ops; Optional<std::string> substring; Optional<U32> sort_order; Optional<bool> since_logoff; Params() - : filter_ops(""), + : name("name"), + filter_ops(""), substring("substring"), sort_order("sort_order"), since_logoff("since_logoff") @@ -220,6 +222,7 @@ public: bool isModified() const; bool isSinceLogoff() const; void clearModified(); + const std::string& getName() const { return mName; } const std::string& getFilterText(); //RN: this is public to allow system to externally force a global refilter void setModified(EFilterModified behavior = FILTER_RESTART); @@ -265,6 +268,7 @@ private: std::string mFilterSubString; std::string mFilterSubStringOrig; + const std::string mName; S32 mLastSuccessGeneration; S32 mLastFailGeneration; -- cgit v1.2.3 From c517863b9c0e19507eafc8842e1e68379e6122a9 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 20 Jun 2012 19:17:54 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose build fix for gcc --- indra/newview/llfolderviewitem.h | 5 ++--- indra/newview/llfolderviewmodel.h | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 1f8c12cf73..feba32e31d 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -464,7 +464,6 @@ public: std::string& tooltip_msg); virtual void draw(); - folders_t::iterator getFoldersBegin() { return mFolders.begin(); } folders_t::iterator getFoldersEnd() { return mFolders.end(); } folders_t::size_type getFoldersCount() const { return mFolders.size(); } @@ -478,8 +477,8 @@ public: public: //WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead - template<typename SORT_FUNC> void sortFolders(SORT_FUNC& func) { mFolders.sort(func); } - template<typename SORT_FUNC> void sortItems(SORT_FUNC& func) { mItems.sort(func); } + template<typename SORT_FUNC> void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); } + template<typename SORT_FUNC> void sortItems(const SORT_FUNC& func) { mItems.sort(func); } }; diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 946943530a..930c26384c 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -255,12 +255,12 @@ public: : mSorter(sorter) {} - bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) + bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const { return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); } - bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) + bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const { return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); } -- cgit v1.2.3 From a02f2e63f20021d007a6a20c33cc961500b14236 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 21 Jun 2012 10:11:55 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose one more gcc build fix --- indra/newview/llfolderview.cpp | 7 +++++-- indra/newview/llinventorypanel.cpp | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 2bc6f26c85..6bae1d5644 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -289,6 +289,9 @@ LLFolderView::~LLFolderView( void ) delete mFilter; mFilter = NULL; + + delete mViewModel; + mViewModel = NULL; } BOOL LLFolderView::canFocusChildren() const @@ -345,12 +348,12 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen LLFolderViewFolder::arrange(&mMinWidth, &target_height, mFilter->getFirstSuccessGeneration()); LLRect scroll_rect = mScrollContainer->getContentWindowRect(); - reshape( llmax(scroll_rect.getWidth(), mMinWidth), mCurHeight ); + reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); LLRect new_scroll_rect = mScrollContainer->getContentWindowRect(); if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) { - reshape( llmax(scroll_rect.getWidth(), mMinWidth), mCurHeight ); + reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); } // move item renamer text field to item's new position diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index f6861d83de..d576160277 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -685,7 +685,8 @@ LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool u p.rect = folder_rect; p.parent_panel = this; p.tool_tip = p.name; - p.listener = bridge; + p.listener = bridge; + p.view_model = new LLFolderViewModelInventory(); p.use_label_suffix = useLabelSuffix; p.allow_multiselect = mAllowMultiSelect; p.show_empty_message = mShowEmptyMessage; -- cgit v1.2.3 From 4775084000233ec9f0770f421771215397b987e7 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 21 Jun 2012 23:28:24 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose inventory item labels and icons displaying again --- indra/newview/llfavoritesbar.cpp | 308 ++++++++++++++++++- indra/newview/llfavoritesbar.h | 111 +++++++ indra/newview/llfolderview.cpp | 2 + indra/newview/llfolderview.h | 6 +- indra/newview/llfolderviewitem.cpp | 71 ++--- indra/newview/llfolderviewitem.h | 11 +- indra/newview/llfolderviewmodel.h | 38 ++- indra/newview/llinventorybridge.cpp | 24 +- indra/newview/llinventorybridge.h | 7 +- indra/newview/llinventorymodel.cpp | 61 ---- indra/newview/llinventorymodel.h | 9 - indra/newview/llinventorypanel.cpp | 44 +-- indra/newview/llinventorypanel.h | 2 +- indra/newview/llpanelmarketplaceinboxinventory.cpp | 16 - .../newview/llpanelmarketplaceoutboxinventory.cpp | 16 - indra/newview/llpanelobjectinventory.cpp | 16 +- indra/newview/llviewerinventory.cpp | 341 --------------------- indra/newview/llviewerinventory.h | 17 +- 18 files changed, 512 insertions(+), 588 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 575b613ccf..4a96de942d 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -38,6 +38,7 @@ #include "lltooltip.h" #include "llagent.h" +#include "llavatarnamecache.h" #include "llclipboard.h" #include "llclipboard.h" #include "llinventorybridge.h" @@ -45,12 +46,14 @@ #include "llfloatersidepanelcontainer.h" #include "llfloaterworldmap.h" #include "lllandmarkactions.h" +#include "lllogininstance.h" #include "llnotificationsutil.h" #include "lltoggleablemenu.h" #include "llviewerinventory.h" #include "llviewermenu.h" #include "llviewermenu.h" #include "lltooldraganddrop.h" +#include "llsdserialize.h" static LLDefaultChildRegistry::Register<LLFavoritesBarCtrl> r("favorites_bar"); @@ -317,7 +320,8 @@ public: if (item) { - item->setSortField(mSortField); + LLFavoritesOrderStorage::instance().setSortIndex(item, mSortField); + item->setComplete(TRUE); item->updateServer(FALSE); @@ -339,8 +343,8 @@ struct LLFavoritesSort // TODO - made it customizible using gSavedSettings bool operator()(const LLViewerInventoryItem* const& a, const LLViewerInventoryItem* const& b) { - S32 sortField1 = a->getSortField(); - S32 sortField2 = b->getSortField(); + S32 sortField1 = LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID()); + S32 sortField2 = LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID()); if (!(sortField1 < 0 && sortField2 < 0)) { @@ -528,7 +532,7 @@ void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y) mItems.push_back(gInventory.getItem(mDragItemId)); } - gInventory.saveItemsOrder(mItems); + LLFavoritesOrderStorage::instance().saveItemsOrder(mItems); LLToggleableMenu* menu = (LLToggleableMenu*) mOverflowMenuHandle.get(); @@ -587,7 +591,8 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con } else { - currItem->setSortField(++sortField); + LLFavoritesOrderStorage::instance().setSortIndex(currItem, ++sortField); + currItem->setComplete(TRUE); currItem->updateServer(FALSE); @@ -640,7 +645,7 @@ void LLFavoritesBarCtrl::changed(U32 mask) for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) { - (*i)->getSLURL(); + LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID()); } updateButtons(); } @@ -909,7 +914,7 @@ BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &it S32 sortField = 0; for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) { - (*i)->setSortField(++sortField); + LLFavoritesOrderStorage::instance().setSortIndex((*i), ++sortField); } } @@ -1355,7 +1360,7 @@ BOOL LLFavoritesBarCtrl::needToSaveItemsOrder(const LLInventoryModel::item_array // if there is an item without sort order field set, we need to save items order for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) { - if ((*i)->getSortField() < 0) + if (LLFavoritesOrderStorage::instance().getSortIndex((*i)->getUUID()) < 0) { result = TRUE; break; @@ -1390,4 +1395,291 @@ void LLFavoritesBarCtrl::insertItem(LLInventoryModel::item_array_t& items, const } } +const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml"; +const S32 LLFavoritesOrderStorage::NO_INDEX = -1; + +void LLFavoritesOrderStorage::setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index) +{ + mSortIndexes[inv_item->getUUID()] = sort_index; + mIsDirty = true; + getSLURL(inv_item->getAssetUUID()); +} + +S32 LLFavoritesOrderStorage::getSortIndex(const LLUUID& inv_item_id) +{ + sort_index_map_t::const_iterator it = mSortIndexes.find(inv_item_id); + if (it != mSortIndexes.end()) + { + return it->second; + } + return NO_INDEX; +} + +void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id) +{ + mSortIndexes.erase(inv_item_id); + mIsDirty = true; +} + +void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id) +{ + slurls_map_t::iterator slurl_iter = mSLURLs.find(asset_id); + if (slurl_iter != mSLURLs.end()) return; // SLURL for current landmark is already cached + + LLLandmark* lm = gLandmarkList.getAsset(asset_id, + boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1)); + if (lm) + { + onLandmarkLoaded(asset_id, lm); + } +} + +// static +void LLFavoritesOrderStorage::destroyClass() +{ + LLFavoritesOrderStorage::instance().cleanup(); + if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) + { + LLFavoritesOrderStorage::instance().saveFavoritesSLURLs(); + } + else + { + LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser(); + } +} + +void LLFavoritesOrderStorage::load() +{ + // load per-resident sorting information + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); + + LLSD settings_llsd; + llifstream file; + file.open(filename); + if (file.is_open()) + { + LLSDSerialize::fromXML(settings_llsd, file); + } + + for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); + iter != settings_llsd.endMap(); ++iter) + { + mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); + } +} + +void LLFavoritesOrderStorage::saveFavoritesSLURLs() +{ + // Do not change the file if we are not logged in yet. + if (!LLLoginInstance::getInstance()->authSuccess()) + { + llwarns << "Cannot save favorites: not logged in" << llendl; + return; + } + + std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); + if (user_dir.empty()) + { + llwarns << "Cannot save favorites: empty user dir name" << llendl; + return; + } + + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); + llifstream in_file; + in_file.open(filename); + LLSD fav_llsd; + if (in_file.is_open()) + { + LLSDSerialize::fromXML(fav_llsd, in_file); + } + + const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); + + LLSD user_llsd; + for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) + { + LLSD value; + value["name"] = (*it)->getName(); + value["asset_id"] = (*it)->getAssetUUID(); + + slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); + if (slurl_iter != mSLURLs.end()) + { + lldebugs << "Saving favorite: idx=" << LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID()) << ", SLURL=" << slurl_iter->second << ", value=" << value << llendl; + value["slurl"] = slurl_iter->second; + user_llsd[LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID())] = value; + } + else + { + llwarns << "Not saving favorite " << value["name"] << ": no matching SLURL" << llendl; + } + } + + LLAvatarName av_name; + LLAvatarNameCache::get( gAgentID, &av_name ); + lldebugs << "Saved favorites for " << av_name.getLegacyName() << llendl; + fav_llsd[av_name.getLegacyName()] = user_llsd; + + llofstream file; + file.open(filename); + LLSDSerialize::toPrettyXML(fav_llsd, file); +} + +void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() +{ + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); + LLSD fav_llsd; + llifstream file; + file.open(filename); + if (!file.is_open()) return; + LLSDSerialize::fromXML(fav_llsd, file); + + LLAvatarName av_name; + LLAvatarNameCache::get( gAgentID, &av_name ); + lldebugs << "Removed favorites for " << av_name.getLegacyName() << llendl; + if (fav_llsd.has(av_name.getLegacyName())) + { + fav_llsd.erase(av_name.getLegacyName()); + } + + llofstream out_file; + out_file.open(filename); + LLSDSerialize::toPrettyXML(fav_llsd, out_file); + +} + +void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark) +{ + if (!landmark) return; + + LLVector3d pos_global; + if (!landmark->getGlobalPos(pos_global)) + { + // If global position was unknown on first getGlobalPos() call + // it should be set for the subsequent calls. + landmark->getGlobalPos(pos_global); + } + + if (!pos_global.isExactlyZero()) + { + LLLandmarkActions::getSLURLfromPosGlobal(pos_global, + boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1)); + } +} + +void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl) +{ + lldebugs << "Saving landmark SLURL: " << slurl << llendl; + mSLURLs[asset_id] = slurl; +} + +void LLFavoritesOrderStorage::save() +{ + // nothing to save if clean + if (!mIsDirty) return; + + // If we quit from the login screen we will not have an SL account + // name. Don't try to save, otherwise we'll dump a file in + // C:\Program Files\SecondLife\ or similar. JC + std::string user_dir = gDirUtilp->getLindenUserDir(); + if (!user_dir.empty()) + { + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); + LLSD settings_llsd; + + for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter) + { + settings_llsd[iter->first.asString()] = iter->second; + } + + llofstream file; + file.open(filename); + LLSDSerialize::toPrettyXML(settings_llsd, file); + } +} + +void LLFavoritesOrderStorage::cleanup() +{ + // nothing to clean + if (!mIsDirty) return; + + const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); + + IsNotInFavorites is_not_in_fav(items); + + sort_index_map_t aTempMap; + //copy unremoved values from mSortIndexes to aTempMap + std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(), + inserter(aTempMap, aTempMap.begin()), + is_not_in_fav); + + //Swap the contents of mSortIndexes and aTempMap + mSortIndexes.swap(aTempMap); +} + +void LLFavoritesOrderStorage::saveItemsOrder( const LLInventoryModel::item_array_t& items ) +{ + int sortField = 0; + + // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field + for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) + { + LLViewerInventoryItem* item = *i; + + setSortIndex(item, ++sortField); + + item->setComplete(TRUE); + item->updateServer(FALSE); + + gInventory.updateItem(item); + + // Tell the parent folder to refresh its sort order. + gInventory.addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); + } + + gInventory.notifyObservers(); +} + +// See also LLInventorySort where landmarks in the Favorites folder are sorted. +class LLViewerInventoryItemSort +{ +public: + bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) + { + return LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID()) + < LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID()); + } +}; + +// * @param source_item_id - LLUUID of the source item to be moved into new position +// * @param target_item_id - LLUUID of the target item before which source item should be placed. +void LLFavoritesOrderStorage::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLIsType is_type(LLAssetType::AT_LANDMARK); + LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + + // ensure items are sorted properly before changing order. EXT-3498 + std::sort(items.begin(), items.end(), LLViewerInventoryItemSort()); + + // update order + gInventory.updateItemsOrder(items, source_item_id, target_item_id); + + saveItemsOrder(items); +} + +void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id) +{ + if (mTargetLandmarkId.isNull()) return; + + LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId); +} // EOF diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 2f75b3bb0e..60e02b661e 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -33,6 +33,7 @@ #include "llinventoryobserver.h" #include "llinventorymodel.h" +#include "llviewerinventory.h" class LLMenuItemCallGL; class LLToggleableMenu; @@ -161,5 +162,115 @@ private: boost::signals2::connection mEndDragConnection; }; +class AddFavoriteLandmarkCallback : public LLInventoryCallback +{ +public: + AddFavoriteLandmarkCallback() : mTargetLandmarkId(LLUUID::null) {} + void setTargetLandmarkId(const LLUUID& target_uuid) { mTargetLandmarkId = target_uuid; } + +private: + void fire(const LLUUID& inv_item); + + LLUUID mTargetLandmarkId; +}; + +/** + * Class to store sorting order of favorites landmarks in a local file. EXT-3985. + * It replaced previously implemented solution to store sort index in landmark's name as a "<N>@" prefix. + * Data are stored in user home directory. + */ +class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage> + , public LLDestroyClass<LLFavoritesOrderStorage> +{ + LOG_CLASS(LLFavoritesOrderStorage); +public: + /** + * Sets sort index for specified with LLUUID favorite landmark + */ + void setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index); + + /** + * Gets sort index for specified with LLUUID favorite landmark + */ + S32 getSortIndex(const LLUUID& inv_item_id); + void removeSortIndex(const LLUUID& inv_item_id); + + void getSLURL(const LLUUID& asset_id); + + // Saves current order of the passed items using inventory item sort field. + // Resets 'items' sort fields and saves them on server. + // Is used to save order for Favorites folder. + void saveItemsOrder(const LLInventoryModel::item_array_t& items); + + void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id); + + /** + * Implementation of LLDestroyClass. Calls cleanup() instance method. + * + * It is important this callback is called before gInventory is cleaned. + * For now it is called from LLAppViewer::cleanup() -> LLAppViewer::disconnectViewer(), + * Inventory is cleaned later from LLAppViewer::cleanup() after LLAppViewer::disconnectViewer() is called. + * @see cleanup() + */ + static void destroyClass(); + + const static S32 NO_INDEX; +private: + friend class LLSingleton<LLFavoritesOrderStorage>; + LLFavoritesOrderStorage() : mIsDirty(false) { load(); } + ~LLFavoritesOrderStorage() { save(); } + + /** + * Removes sort indexes for items which are not in Favorites bar for now. + */ + void cleanup(); + + const static std::string SORTING_DATA_FILE_NAME; + + void load(); + void save(); + + void saveFavoritesSLURLs(); + + // Remove record of current user's favorites from file on disk. + void removeFavoritesRecordOfUser(); + + void onLandmarkLoaded(const LLUUID& asset_id, class LLLandmark* landmark); + void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl); + + typedef std::map<LLUUID, S32> sort_index_map_t; + sort_index_map_t mSortIndexes; + + typedef std::map<LLUUID, std::string> slurls_map_t; + slurls_map_t mSLURLs; + + bool mIsDirty; + + struct IsNotInFavorites + { + IsNotInFavorites(const LLInventoryModel::item_array_t& items) + : mFavoriteItems(items) + { + + } + + /** + * Returns true if specified item is not found among inventory items + */ + bool operator()(const sort_index_map_t::value_type& id_index_pair) const + { + LLPointer<LLViewerInventoryItem> item = gInventory.getItem(id_index_pair.first); + if (item.isNull()) return true; + + LLInventoryModel::item_array_t::const_iterator found_it = + std::find(mFavoriteItems.begin(), mFavoriteItems.end(), item); + + return found_it == mFavoriteItems.end(); + } + private: + LLInventoryModel::item_array_t mFavoriteItems; + }; + +}; #endif // LL_LLFAVORITESBARCTRL_H diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 6bae1d5644..ee8c94a2dd 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -195,8 +195,10 @@ LLFolderView::LLFolderView(const Params& p) mUseEllipses(p.use_ellipses), mDraggingOverItem(NULL), mStatusTextBox(NULL), + mShowItemLinkOverlays(p.show_item_link_overlays), mViewModel(p.view_model) { + mViewModel->setFolderView(this); mRoot = this; LLRect rect = p.rect; diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 813b4d130f..8b58da9f45 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -96,7 +96,8 @@ public: Optional<bool> use_label_suffix, allow_multiselect, show_empty_message, - use_ellipses; + use_ellipses, + show_item_link_overlays; Mandatory<LLFolderViewModelInterface*> view_model; Params(); @@ -239,6 +240,8 @@ public: void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; } void setAutoSelectOverride(BOOL val) { mAutoSelectOverride = val; } + bool showItemLinkOverlays() { return mShowItemLinkOverlays; } + void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } BOOL getDebugFilters() { return mDebugFilters; } @@ -294,6 +297,7 @@ protected: BOOL mAutoSelectOverride; BOOL mNeedsAutoRename; bool mUseLabelSuffix; + bool mShowItemLinkOverlays; BOOL mDebugFilters; U32 mSortOrder; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 5b73a34d29..3f0b493986 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -91,10 +91,7 @@ void LLFolderViewItem::cleanupClass() // NOTE: Optimize this, we call it a *lot* when opening a large inventory LLFolderViewItem::Params::Params() -: icon(), - icon_open(), - icon_overlay(), - root(), +: root(), listener(), folder_arrow_image("folder_arrow_image"), folder_indentation("folder_indentation"), @@ -125,12 +122,10 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mDragAndDropTarget(FALSE), mLabel(p.name), mRoot(p.root), - mIcon(p.icon), - mIconOpen(p.icon_open), - mIconOverlay(p.icon_overlay), mListener(p.listener), mIsMouseOverTitle(false) { + mListener->setFolderViewItem(this); } BOOL LLFolderViewItem::postBuild() @@ -243,11 +238,6 @@ void LLFolderViewItem::setFiltered(BOOL filtered, S32 filter_generation) mLastFilterGeneration = filter_generation; } -void LLFolderViewItem::setIcon(LLUIImagePtr icon) -{ - mIcon = icon; -} - void LLFolderViewItem::refresh() { if(!getViewModelItem()) return; @@ -255,7 +245,10 @@ void LLFolderViewItem::refresh() mLabel = getViewModelItem()->getDisplayName(); setToolTip(mLabel); - setIcon(getViewModelItem()->getIcon()); + mIcon = getViewModelItem()->getIcon(); + mIconOpen = getViewModelItem()->getIconOpen(); + mIconOverlay = getViewModelItem()->getIconOverlay(); + if (mRoot->useLabelSuffix()) { mLabelStyle = getViewModelItem()->getLabelStyle(); @@ -907,27 +900,23 @@ void LLFolderViewItem::draw() mDragAndDropTarget = FALSE; } - //TODO RN: implement this in terms of getIcon() and getIconOverlay() - - //const LLViewerInventoryItem *item = getInventoryItem(); - //const BOOL highlight_link = mIconOverlay && item && item->getIsLinkType(); - ////--------------------------------------------------------------------------------// - //// Draw open icon - //// - //const S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; - //if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders - // { - // mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); - //} - //else if (mIcon) - //{ - // mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - // } + //--------------------------------------------------------------------------------// + // Draw open icon + // + const S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; + if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders + { + mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); + } + else if (mIcon) + { + mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + } - //if (highlight_link) - //{ - // mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - //} + if (mIconOverlay && getRoot()->showItemLinkOverlays()) + { + mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + } //--------------------------------------------------------------------------------// // Exit if no label to draw @@ -1242,7 +1231,7 @@ BOOL LLFolderViewFolder::needsArrange() void LLFolderViewFolder::requestSort() { - getRoot()->getFolderViewModel()->requestSort(this); + getViewModelItem()->requestSort(); } void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up) @@ -2007,13 +1996,13 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) addChild( folder ); folder->dirtyFilter(); // rearrange all descendants too, as our indentation level might have changed - folder->requestArrange(TRUE); + folder->requestArrange(); requestSort(); return TRUE; } -void LLFolderViewFolder::requestArrange(BOOL include_descendants) +void LLFolderViewFolder::requestArrange() { mLastArrangeGeneration = -1; // flag all items up to root @@ -2021,16 +2010,6 @@ void LLFolderViewFolder::requestArrange(BOOL include_descendants) { mParentFolder->requestArrange(); } - - if (include_descendants) - { - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end(); - ++iter) - { - (*iter)->requestArrange(TRUE); - } - } } void LLFolderViewFolder::toggleOpen() diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index feba32e31d..fd2948f34e 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -51,10 +51,7 @@ public: struct Params : public LLInitParam::Block<Params, LLView::Params> { - Optional<LLUIImage*> icon, - icon_open, // used for folders - icon_overlay, // for links - folder_arrow_image, + Optional<LLUIImage*> folder_arrow_image, selection_image; Optional<LLFolderView*> root; Mandatory<LLFolderViewModelItem*> listener; @@ -252,9 +249,6 @@ public: virtual BOOL getFiltered(S32 filter_generation); virtual void setFiltered(BOOL filtered, S32 filter_generation); - // change the icon - void setIcon(LLUIImagePtr icon); - // refresh information from the object being viewed. virtual void refresh(); @@ -416,8 +410,7 @@ public: virtual void setOpen(BOOL openitem = TRUE); // Called when a child is refreshed. - // don't rearrange child folder contents unless explicitly requested - virtual void requestArrange(BOOL include_descendants = FALSE); + virtual void requestArrange(); virtual void requestSort(); diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 930c26384c..c3dcfed97c 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -120,18 +120,20 @@ class LLFolderViewModelInterface { public: virtual void requestSortAll() = 0; - virtual void requestSort(class LLFolderViewFolder*) = 0; virtual void sort(class LLFolderViewFolder*) = 0; virtual void filter(class LLFolderViewFolder*) = 0; virtual bool contentsReady() = 0; + virtual void setFolderView(LLFolderView* folder_view) = 0; }; -struct LLFolderViewModelCommon : public LLFolderViewModelInterface +class LLFolderViewModelCommon : public LLFolderViewModelInterface { +public: LLFolderViewModelCommon() - : mTargetSortVersion(0) + : mTargetSortVersion(0), + mFolderView(NULL) {} virtual void requestSortAll() @@ -140,15 +142,14 @@ struct LLFolderViewModelCommon : public LLFolderViewModelInterface mTargetSortVersion++; } - virtual void requestSort(class LLFolderViewFolder* folder) - { - folder->requestSort(); - } - + void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} + protected: bool needsSort(class LLFolderViewModelItem* item); S32 mTargetSortVersion; + LLFolderView* mFolderView; + }; // This is am abstract base class that users of the folderview classes @@ -156,6 +157,10 @@ protected: class LLFolderViewModelItem { public: + LLFolderViewModelItem() + : mFolderViewItem(NULL) + {} + virtual ~LLFolderViewModelItem( void ) {}; virtual void update() {} //called when drawing @@ -163,7 +168,8 @@ public: virtual const std::string& getDisplayName() const = 0; virtual LLPointer<LLUIImage> getIcon() const = 0; - virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } + virtual LLPointer<LLUIImage> getIconOpen() const { return getIcon(); } + virtual LLPointer<LLUIImage> getIconOverlay() const { return NULL; } virtual LLFontGL::StyleFlags getLabelStyle() const = 0; virtual std::string getLabelSuffix() const = 0; @@ -211,6 +217,11 @@ public: virtual void requestSort() = 0; virtual S32 getSortVersion() = 0; virtual void setSortVersion(S32 version) = 0; +protected: + friend LLFolderViewItem; + void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} + LLFolderViewItem* mFolderViewItem; + }; class LLFolderViewModelItemCommon : public LLFolderViewModelItem @@ -225,6 +236,7 @@ public: void setSortVersion(S32 version) { mSortVersion = version;} protected: + S32 mSortVersion; }; @@ -232,7 +244,7 @@ template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename class LLFolderViewModel : public LLFolderViewModelCommon { public: - LLFolderViewModel() {} + LLFolderViewModel(){} virtual ~LLFolderViewModel() {} typedef SORT_TYPE SortType; @@ -247,6 +259,8 @@ public: virtual const FilterType& getFilter() const { return mFilter; } virtual void setFilter(const FilterType& filter) { mFilter = filter; } + // TODO RN: remove this and put all filtering logic in view model + // add getStatusText and isFiltering() virtual bool contentsReady() { return true; } struct ViewModelCompare @@ -301,8 +315,8 @@ public: } protected: - SortType mSorter; - FilterType mFilter; + SortType mSorter; + FilterType mFilter; }; #endif diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 44d0fdd3dd..c0670b71d4 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -37,6 +37,7 @@ #include "llappearancemgr.h" #include "llattachmentsmgr.h" #include "llavataractions.h" +#include "llfavoritesbar.h" // management of favorites folder #include "llfloateropenobject.h" #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" @@ -1846,7 +1847,11 @@ void LLFolderBridge::buildDisplayName() const if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) { LLTrans::findString(mDisplayName, std::string("InvFolder ") + getName(), LLSD()); - }; + } + else + { + mDisplayName.assign(getName()); + } } @@ -2993,17 +2998,24 @@ LLUIImagePtr LLFolderBridge::getIcon() const LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type) { return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE)); - /*case LLAssetType::AT_MESH: - control = "inv_folder_mesh.tga"; - break;*/ } -LLUIImagePtr LLFolderBridge::getOpenIcon() const +LLUIImagePtr LLFolderBridge::getIconOpen() const { return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE)); } +LLUIImagePtr LLFolderBridge::getIconOverlay() const +{ + if (getInventoryObject() && getInventoryObject()->getIsLinkType()) + { + return LLUI::getUIImage("Inv_Link"); + } + return NULL; +} + + BOOL LLFolderBridge::renameItem(const std::string& new_name) { rename_category(getInventoryModel(), mUUID, new_name); @@ -4017,7 +4029,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { LLUUID srcItemId = inv_item->getUUID(); LLUUID destItemId = static_cast<LLFolderViewModelItemInventory*>(itemp->getViewModelItem())->getUUID(); - gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); + LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(srcItemId, destItemId); } } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 111735e198..26789627f7 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -260,7 +260,9 @@ public: virtual LLFolderType::EType getPreferredType() const; virtual LLUIImagePtr getIcon() const; - virtual LLUIImagePtr getOpenIcon() const; + virtual LLUIImagePtr getIconOpen() const; + virtual LLUIImagePtr getIconOverlay() const; + static LLUIImagePtr getIcon(LLFolderType::EType preferred_type); virtual BOOL renameItem(const std::string& new_name); @@ -338,8 +340,7 @@ private: bool mWearables; bool mIsLoading; LLTimer mTimeSinceRequestStart; - mutable std::string mDisplayName; - LLRootHandle<LLFolderBridge> mHandle; + LLRootHandle<LLFolderBridge> mHandle; }; class LLTextureBridge : public LLItemBridge diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 85ecb133d0..9b0d12b353 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -3201,68 +3201,7 @@ void LLInventoryModel::updateItemsOrder(LLInventoryModel::item_array_t& items, c } } -//* @param[in] items vector of items in order to be saved. -void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& items) -{ - int sortField = 0; - - // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field - for (item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) - { - LLViewerInventoryItem* item = *i; - - item->setSortField(++sortField); - item->setComplete(TRUE); - item->updateServer(FALSE); - - updateItem(item); - - // Tell the parent folder to refresh its sort order. - addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); - } - - notifyObservers(); -} - -// See also LLInventorySort where landmarks in the Favorites folder are sorted. -class LLViewerInventoryItemSort -{ -public: - bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) - { - return a->getSortField() < b->getSortField(); - } -}; -/** - * Sorts passed items by LLViewerInventoryItem sort field. - * - * @param[in, out] items - array of items, not sorted. - */ -static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items) -{ - static LLViewerInventoryItemSort sort_functor; - std::sort(items.begin(), items.end(), sort_functor); -} - -// * @param source_item_id - LLUUID of the source item to be moved into new position -// * @param target_item_id - LLUUID of the target item before which source item should be placed. -void LLInventoryModel::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) -{ - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLIsType is_type(LLAssetType::AT_LANDMARK); - LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); - - // ensure items are sorted properly before changing order. EXT-3498 - rearrange_item_order_by_sort_field(items); - - // update order - updateItemsOrder(items, source_item_id, target_item_id); - - saveItemsOrder(items); -} //---------------------------------------------------------------------------- diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 8382e875b4..3613bc4917 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -362,15 +362,6 @@ public: // Returns end() of the vector if not found. static LLInventoryModel::item_array_t::iterator findItemIterByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id); - // Saves current order of the passed items using inventory item sort field. - // Resets 'items' sort fields and saves them on server. - // Is used to save order for Favorites folder. - void saveItemsOrder(const LLInventoryModel::item_array_t& items); - - // Rearranges Landmarks inside Favorites folder. - // Moves source landmark before target one. - void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id); - //-------------------------------------------------------------------- // Creation //-------------------------------------------------------------------- diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index d576160277..74492e0005 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -59,17 +59,6 @@ static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; // // class LLFolderViewModelInventory // -void LLFolderViewModelInventory::requestSort(class LLFolderViewFolder* folder) -{ - base_t::requestSort(folder); - if (getSorter().isByDate()) - { - // sort by date potentially affects parent folders which use a date - // derived from newest item in them - requestSort(folder->getParentFolder()); - } -} - static LLFastTimer::DeclareTimer FTM_INVENTORY_SORT("Sort"); void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) @@ -690,6 +679,7 @@ LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool u p.use_label_suffix = useLabelSuffix; p.allow_multiselect = mAllowMultiSelect; p.show_empty_message = mShowEmptyMessage; + p.show_item_link_overlays = mShowItemLinkOverlays; return LLUICtrlFactory::create<LLFolderView>(p); } @@ -699,14 +689,6 @@ LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * br LLFolderViewFolder::Params params; params.name = bridge->getDisplayName(); - params.icon = bridge->getIcon(); - params.icon_open = bridge->getOpenIcon(); - - if (mShowItemLinkOverlays) // if false, then links show up just like normal items - { - params.icon_overlay = LLUI::getUIImage("Inv_Link"); - } - params.root = mFolderRoot; params.listener = bridge; params.tool_tip = params.name; @@ -719,14 +701,6 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge LLFolderViewItem::Params params; params.name = bridge->getDisplayName(); - params.icon = bridge->getIcon(); - params.icon_open = bridge->getOpenIcon(); - - if (mShowItemLinkOverlays) // if false, then links show up just like normal items - { - params.icon_overlay = LLUI::getUIImage("Inv_Link"); - } - params.creation_date = bridge->getCreationDate(); params.root = mFolderRoot; params.listener = bridge; @@ -743,7 +717,9 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) if (!objectp) return NULL; LLFolderViewItem* folder_view_item = getItemByID(id); - LLFolderViewFolder* parent_folder = folder_view_item->getParentFolder(); + + const LLUUID &parent_id = objectp->getParentUUID(); + LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); if (!folder_view_item && parent_folder) { @@ -1370,3 +1346,15 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params) mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER; } + +void LLFolderViewModelItemInventory::requestSort() +{ + LLFolderViewModelItemCommon::requestSort(); + //TODO RN: need better way to get to root viewmodel, also consider reflecting hierarchy in viewmodel space as well + if (static_cast<LLFolderViewModelInventory*>(mFolderViewItem->getRoot()->getFolderViewModel())->getSorter().isByDate()) + { + // sort by date potentially affects parent folders which use a date + // derived from newest item in them + mFolderViewItem->getParentFolder()->getViewModelItem()->requestSort(); + } +} diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 2aa05e1b61..645e2f6d76 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -61,6 +61,7 @@ public: virtual LLWearableType::EType getWearableType() const = 0; virtual EInventorySortGroup getSortGroup() const = 0; virtual LLInventoryObject* getInventoryObject() const = 0; + virtual void requestSort(); }; class LLInventorySort @@ -97,7 +98,6 @@ public: virtual ~LLFolderViewModelInventory() {} void sort(LLFolderViewFolder* folder); - void requestSort(LLFolderViewFolder* folder); bool contentsReady(); diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index d2143783ad..f3096e862d 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -122,14 +122,6 @@ LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge LLInboxFolderViewFolder::Params params; params.name = bridge->getDisplayName(); - params.icon = bridge->getIcon(); - params.icon_open = bridge->getOpenIcon(); - - if (mShowItemLinkOverlays) // if false, then links show up just like normal items - { - params.icon_overlay = LLUI::getUIImage("Inv_Link"); - } - params.root = mFolderRoot; params.listener = bridge; params.tool_tip = params.name; @@ -142,14 +134,6 @@ LLFolderViewItem * LLInboxInventoryPanel::createFolderViewItem(LLInvFVBridge * b LLInboxFolderViewItem::Params params; params.name = bridge->getDisplayName(); - params.icon = bridge->getIcon(); - params.icon_open = bridge->getOpenIcon(); - - if (mShowItemLinkOverlays) // if false, then links show up just like normal items - { - params.icon_overlay = LLUI::getUIImage("Inv_Link"); - } - params.creation_date = bridge->getCreationDate(); params.root = mFolderRoot; params.listener = bridge; diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp index 7db01d9059..783eeb11b8 100644 --- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceoutboxinventory.cpp @@ -88,14 +88,6 @@ LLFolderViewFolder * LLOutboxInventoryPanel::createFolderViewFolder(LLInvFVBridg LLOutboxFolderViewFolder::Params params; params.name = bridge->getDisplayName(); - params.icon = bridge->getIcon(); - params.icon_open = bridge->getOpenIcon(); - - if (mShowItemLinkOverlays) // if false, then links show up just like normal items - { - params.icon_overlay = LLUI::getUIImage("Inv_Link"); - } - params.root = mFolderRoot; params.listener = bridge; params.tool_tip = params.name; @@ -108,14 +100,6 @@ LLFolderViewItem * LLOutboxInventoryPanel::createFolderViewItem(LLInvFVBridge * LLFolderViewItem::Params params; params.name = bridge->getDisplayName(); - params.icon = bridge->getIcon(); - params.icon_open = bridge->getOpenIcon(); - - if (mShowItemLinkOverlays) // if false, then links show up just like normal items - { - params.icon_overlay = LLUI::getUIImage("Inv_Link"); - } - params.creation_date = bridge->getCreationDate(); params.root = mFolderRoot; params.listener = bridge; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 0ba8c1ce6d..da82d70f22 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1551,6 +1551,7 @@ void LLPanelObjectInventory::reset() p.tool_tip= LLTrans::getString("PanelContentsTooltip"); p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL); p.folder_indentation = -14; // subtract space normally reserved for folder expanders + p.view_model = new LLFolderViewModelInventory(); mFolders = LLUICtrlFactory::create<LLFolderView>(p); // this ensures that we never say "searching..." or "no items found" //TODO RN: make this happen by manipulating filter object directly @@ -1693,18 +1694,6 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root bridge = LLTaskInvFVBridge::createObjectBridge(this, inventory_root); if(bridge) { - //LLFolderViewFolder* new_folder = NULL; - //LLFolderViewFolder::Params p; - //p.name = inventory_root->getName(); - //p.icon = LLUI::getUIImage("Inv_FolderClosed"); - //p.icon_open = LLUI::getUIImage("Inv_FolderOpen"); - //p.root = mFolders; - //p.listener = bridge; - //p.tool_tip = p.name; - //new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); - //new_folder->addToFolder(mFolders, mFolders); - //new_folder->toggleOpen(); - createViewsForCategory(&contents, inventory_root, mFolders); } } @@ -1737,8 +1726,6 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li { LLFolderViewFolder::Params p; p.name = obj->getName(); - p.icon = LLUI::getUIImage("Inv_FolderClosed"); - p.icon_open = LLUI::getUIImage("Inv_FolderOpen"); p.root = mFolders; p.listener = bridge; p.tool_tip = p.name; @@ -1750,7 +1737,6 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li { LLFolderViewItem::Params params; params.name(obj->getName()); - params.icon(bridge->getIcon()); params.creation_date(bridge->getCreationDate()); params.root(mFolders); params.listener(bridge); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 749a6d22e0..d81b016fc1 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1030,12 +1030,7 @@ void CreateGestureCallback::fire(const LLUUID& inv_item) gFloaterView->adjustToFitScreen(preview, FALSE); } -void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id) -{ - if (mTargetLandmarkId.isNull()) return; - gInventory.rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId); -} LLInventoryCallbackManager gInventoryCallbacks; @@ -1449,342 +1444,6 @@ const std::string& LLViewerInventoryItem::getName() const return LLInventoryItem::getName(); } -/** - * Class to store sorting order of favorites landmarks in a local file. EXT-3985. - * It replaced previously implemented solution to store sort index in landmark's name as a "<N>@" prefix. - * Data are stored in user home directory. - */ -class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage> - , public LLDestroyClass<LLFavoritesOrderStorage> -{ - LOG_CLASS(LLFavoritesOrderStorage); -public: - /** - * Sets sort index for specified with LLUUID favorite landmark - */ - void setSortIndex(const LLUUID& inv_item_id, S32 sort_index); - - /** - * Gets sort index for specified with LLUUID favorite landmark - */ - S32 getSortIndex(const LLUUID& inv_item_id); - void removeSortIndex(const LLUUID& inv_item_id); - - void getSLURL(const LLUUID& asset_id); - - /** - * Implementation of LLDestroyClass. Calls cleanup() instance method. - * - * It is important this callback is called before gInventory is cleaned. - * For now it is called from LLAppViewer::cleanup() -> LLAppViewer::disconnectViewer(), - * Inventory is cleaned later from LLAppViewer::cleanup() after LLAppViewer::disconnectViewer() is called. - * @see cleanup() - */ - static void destroyClass(); - - const static S32 NO_INDEX; -private: - friend class LLSingleton<LLFavoritesOrderStorage>; - LLFavoritesOrderStorage() : mIsDirty(false) { load(); } - ~LLFavoritesOrderStorage() { save(); } - - /** - * Removes sort indexes for items which are not in Favorites bar for now. - */ - void cleanup(); - - const static std::string SORTING_DATA_FILE_NAME; - - void load(); - void save(); - - void saveFavoritesSLURLs(); - - // Remove record of current user's favorites from file on disk. - void removeFavoritesRecordOfUser(); - - void onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark); - void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl); - - typedef std::map<LLUUID, S32> sort_index_map_t; - sort_index_map_t mSortIndexes; - - typedef std::map<LLUUID, std::string> slurls_map_t; - slurls_map_t mSLURLs; - - bool mIsDirty; - - struct IsNotInFavorites - { - IsNotInFavorites(const LLInventoryModel::item_array_t& items) - : mFavoriteItems(items) - { - - } - - /** - * Returns true if specified item is not found among inventory items - */ - bool operator()(const sort_index_map_t::value_type& id_index_pair) const - { - LLPointer<LLViewerInventoryItem> item = gInventory.getItem(id_index_pair.first); - if (item.isNull()) return true; - - LLInventoryModel::item_array_t::const_iterator found_it = - std::find(mFavoriteItems.begin(), mFavoriteItems.end(), item); - - return found_it == mFavoriteItems.end(); - } - private: - LLInventoryModel::item_array_t mFavoriteItems; - }; - -}; - -const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml"; -const S32 LLFavoritesOrderStorage::NO_INDEX = -1; - -void LLFavoritesOrderStorage::setSortIndex(const LLUUID& inv_item_id, S32 sort_index) -{ - mSortIndexes[inv_item_id] = sort_index; - mIsDirty = true; -} - -S32 LLFavoritesOrderStorage::getSortIndex(const LLUUID& inv_item_id) -{ - sort_index_map_t::const_iterator it = mSortIndexes.find(inv_item_id); - if (it != mSortIndexes.end()) - { - return it->second; - } - return NO_INDEX; -} - -void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id) -{ - mSortIndexes.erase(inv_item_id); - mIsDirty = true; -} - -void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id) -{ - slurls_map_t::iterator slurl_iter = mSLURLs.find(asset_id); - if (slurl_iter != mSLURLs.end()) return; // SLURL for current landmark is already cached - - LLLandmark* lm = gLandmarkList.getAsset(asset_id, - boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1)); - if (lm) - { - onLandmarkLoaded(asset_id, lm); - } -} - -// static -void LLFavoritesOrderStorage::destroyClass() -{ - LLFavoritesOrderStorage::instance().cleanup(); - if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) - { - LLFavoritesOrderStorage::instance().saveFavoritesSLURLs(); - } - else - { - LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser(); - } -} - -void LLFavoritesOrderStorage::load() -{ - // load per-resident sorting information - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); - - LLSD settings_llsd; - llifstream file; - file.open(filename); - if (file.is_open()) - { - LLSDSerialize::fromXML(settings_llsd, file); - } - - for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); - iter != settings_llsd.endMap(); ++iter) - { - mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); - } -} - -void LLFavoritesOrderStorage::saveFavoritesSLURLs() -{ - // Do not change the file if we are not logged in yet. - if (!LLLoginInstance::getInstance()->authSuccess()) - { - llwarns << "Cannot save favorites: not logged in" << llendl; - return; - } - - std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); - if (user_dir.empty()) - { - llwarns << "Cannot save favorites: empty user dir name" << llendl; - return; - } - - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); - llifstream in_file; - in_file.open(filename); - LLSD fav_llsd; - if (in_file.is_open()) - { - LLSDSerialize::fromXML(fav_llsd, in_file); - } - - const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); - - LLSD user_llsd; - for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) - { - LLSD value; - value["name"] = (*it)->getName(); - value["asset_id"] = (*it)->getAssetUUID(); - - slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); - if (slurl_iter != mSLURLs.end()) - { - lldebugs << "Saving favorite: idx=" << (*it)->getSortField() << ", SLURL=" << slurl_iter->second << ", value=" << value << llendl; - value["slurl"] = slurl_iter->second; - user_llsd[(*it)->getSortField()] = value; - } - else - { - llwarns << "Not saving favorite " << value["name"] << ": no matching SLURL" << llendl; - } - } - - LLAvatarName av_name; - LLAvatarNameCache::get( gAgentID, &av_name ); - lldebugs << "Saved favorites for " << av_name.getLegacyName() << llendl; - fav_llsd[av_name.getLegacyName()] = user_llsd; - - llofstream file; - file.open(filename); - LLSDSerialize::toPrettyXML(fav_llsd, file); -} - -void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() -{ - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); - LLSD fav_llsd; - llifstream file; - file.open(filename); - if (!file.is_open()) return; - LLSDSerialize::fromXML(fav_llsd, file); - - LLAvatarName av_name; - LLAvatarNameCache::get( gAgentID, &av_name ); - lldebugs << "Removed favorites for " << av_name.getLegacyName() << llendl; - if (fav_llsd.has(av_name.getLegacyName())) - { - fav_llsd.erase(av_name.getLegacyName()); - } - - llofstream out_file; - out_file.open(filename); - LLSDSerialize::toPrettyXML(fav_llsd, out_file); - -} - -void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark) -{ - if (!landmark) return; - - LLVector3d pos_global; - if (!landmark->getGlobalPos(pos_global)) - { - // If global position was unknown on first getGlobalPos() call - // it should be set for the subsequent calls. - landmark->getGlobalPos(pos_global); - } - - if (!pos_global.isExactlyZero()) - { - LLLandmarkActions::getSLURLfromPosGlobal(pos_global, - boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1)); - } -} - -void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl) -{ - lldebugs << "Saving landmark SLURL: " << slurl << llendl; - mSLURLs[asset_id] = slurl; -} - -void LLFavoritesOrderStorage::save() -{ - // nothing to save if clean - if (!mIsDirty) return; - - // If we quit from the login screen we will not have an SL account - // name. Don't try to save, otherwise we'll dump a file in - // C:\Program Files\SecondLife\ or similar. JC - std::string user_dir = gDirUtilp->getLindenUserDir(); - if (!user_dir.empty()) - { - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); - LLSD settings_llsd; - - for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter) - { - settings_llsd[iter->first.asString()] = iter->second; - } - - llofstream file; - file.open(filename); - LLSDSerialize::toPrettyXML(settings_llsd, file); - } -} - -void LLFavoritesOrderStorage::cleanup() -{ - // nothing to clean - if (!mIsDirty) return; - - const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); - - IsNotInFavorites is_not_in_fav(items); - - sort_index_map_t aTempMap; - //copy unremoved values from mSortIndexes to aTempMap - std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(), - inserter(aTempMap, aTempMap.begin()), - is_not_in_fav); - - //Swap the contents of mSortIndexes and aTempMap - mSortIndexes.swap(aTempMap); -} - - -S32 LLViewerInventoryItem::getSortField() const -{ - return LLFavoritesOrderStorage::instance().getSortIndex(mUUID); -} - -void LLViewerInventoryItem::setSortField(S32 sortField) -{ - LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField); - getSLURL(); -} - -void LLViewerInventoryItem::getSLURL() -{ - LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID); -} - const LLUUID& LLViewerInventoryItem::getCreatorUUID() const { if (const LLViewerInventoryItem *linked_item = getLinkedItem()) diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index d66362d544..3cf03c3bc5 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -60,9 +60,6 @@ public: virtual const LLUUID& getAssetUUID() const; virtual const LLUUID& getProtectedAssetUUID() const; // returns LLUUID::null if current agent does not have permission to expose this asset's UUID to the user virtual const std::string& getName() const; - virtual S32 getSortField() const; - virtual void setSortField(S32 sortField); - virtual void getSLURL(); //Caches SLURL for landmark. //*TODO: Find a better way to do it and remove this method from here. virtual const bool getIsFullPerm() const; // 'fullperm' in the popular sense: modify-ok & copy-ok & transfer-ok, no special god rules applied virtual const LLUUID& getCreatorUUID() const; virtual const std::string& getDescription() const; @@ -72,7 +69,7 @@ public: virtual LLWearableType::EType getWearableType() const; virtual U32 getFlags() const; - using LLInventoryItem::getPermissions; + using LLInventoryItem::getPermissions; using LLInventoryItem::getCreationDate; using LLInventoryItem::setCreationDate; using LLInventoryItem::getCRC32; @@ -287,18 +284,6 @@ public: void fire(const LLUUID& inv_item); }; -class AddFavoriteLandmarkCallback : public LLInventoryCallback -{ -public: - AddFavoriteLandmarkCallback() : mTargetLandmarkId(LLUUID::null) {} - void setTargetLandmarkId(const LLUUID& target_uuid) { mTargetLandmarkId = target_uuid; } - -private: - void fire(const LLUUID& inv_item); - - LLUUID mTargetLandmarkId; -}; - // misc functions //void inventory_reliable_callback(void**, S32 status); -- cgit v1.2.3 From d866328f6a9e6537eb8a9775acf4f403b7ad6af6 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 22 Jun 2012 16:11:25 +0300 Subject: CHUI-100 Fix floater's key --- indra/newview/llimview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 4b82596f37..79018ec366 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2611,7 +2611,7 @@ LLUUID LLIMMgr::addSession( if (floater_id.notNull()) { - LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); + LLIMFloater* im_floater = LLIMFloater::findInstance(floater_id); if (im_floater && im_floater->getStartConferenceInSameFloater()) { -- cgit v1.2.3 From 6bb554fc3661d3b8b1284db96bb7c7b0934df621 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 22 Jun 2012 16:54:42 +0300 Subject: CHUI-160 FIXED (Text entered in local chat text field scrolls up and becomes only partially visible after hitting return) - Replaced LLLineEditor with LLChatEntry in nearby chat - Moved reshape method from LLIMFloater to the base LLIMConversation so that vertical reshaping work properly for both LLNearbyChat and LLIMFloater --- indra/newview/llimconversation.cpp | 22 ++++++++++++++++++++++ indra/newview/llimconversation.h | 14 ++++++++++++++ indra/newview/llimfloater.cpp | 15 --------------- indra/newview/llimfloater.h | 9 --------- indra/newview/llnearbychat.cpp | 25 ++++++++++--------------- indra/newview/llnearbychat.h | 6 +++--- indra/newview/llviewerwindow.cpp | 5 +++-- 7 files changed, 52 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index f12821352b..bbbc9fcffd 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -29,6 +29,8 @@ #include "llimconversation.h" +#include "llchatentry.h" +#include "llchathistory.h" #include "lldraghandle.h" #include "llfloaterreg.h" #include "llimfloater.h" @@ -47,6 +49,9 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id) , mCloseBtn(NULL) , mSessionID(session_id) , mParticipantList(NULL) + , mChatHistory(NULL) + , mInputEditor(NULL) + , mInputEditorTopPad(0) { mCommitCallbackRegistrar.add("IMSession.Menu.Action", boost::bind(&LLIMConversation::onIMSessionMenuItemClicked, this, _2)); @@ -86,6 +91,12 @@ BOOL LLIMConversation::postBuild() mTearOffBtn = getChild<LLButton>("tear_off_btn"); mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); + mChatHistory = getChild<LLChatHistory>("chat_history"); + mInputEditor = getChild<LLChatEntry>("chat_editor"); + + mInputEditor->setTextExpandedCallback(boost::bind(&LLIMConversation::reshapeChatHistory, this)); + mInputEditorTopPad = mChatHistory->getRect().mBottom - mInputEditor->getRect().mTop; + if (!getTornOff()) { setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); @@ -242,6 +253,17 @@ void LLIMConversation::updateHeaderAndToolbar() showTranslationCheckbox(); } +void LLIMConversation::reshapeChatHistory() +{ + LLRect chat_rect = mChatHistory->getRect(); + LLRect input_rect = mInputEditor->getRect(); + + int delta_height = chat_rect.mBottom - (input_rect.mTop + mInputEditorTopPad); + + chat_rect.setLeftTopAndSize(chat_rect.mLeft, chat_rect.mTop, chat_rect.getWidth(), chat_rect.getHeight() + delta_height); + mChatHistory->setShape(chat_rect); +} + void LLIMConversation::showTranslationCheckbox(BOOL show) { getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(mIsNearbyChat? show : FALSE); diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 66401b9a3c..f4b8a38242 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -35,6 +35,8 @@ #include "lleventtimer.h" class LLPanelChatControlPanel; +class LLChatEntry; +class LLChatHistory; class LLIMConversation : public LLTransientDockableFloater @@ -102,6 +104,18 @@ protected: private: /// Update floater header and toolbar buttons when hosted/torn off state is toggled. void updateHeaderAndToolbar(); + + /** + * Adjusts chat history height to fit vertically with input chat field + * and avoid overlapping, since input chat field can be vertically expanded. + * Implementation: chat history bottom "follows" top+top_pad of input chat field + */ + void reshapeChatHistory(); + + + LLChatHistory* mChatHistory; + LLChatEntry* mInputEditor; + int mInputEditorTopPad; // padding between input field and chat history }; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 4b954de738..98ebc82f99 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -64,7 +64,6 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mLastMessageIndex(-1), mDialog(IM_NOTHING_SPECIAL), mInputEditor(NULL), - mInputEditorTopPad(0), mSavedTitle(), mTypingStart(), mShouldSendTypingState(false), @@ -314,12 +313,9 @@ BOOL LLIMFloater::postBuild() mInputEditor->setPassDelete( TRUE ); mInputEditor->setCommitCallback(boost::bind(onSendMsg, _1, this)); - mInputEditor->setTextExpandedCallback(boost::bind(&LLIMFloater::reshapeChatHistory, this)); mChatHistory = getChild<LLChatHistory>("chat_history"); - mInputEditorTopPad = mChatHistory->getRect().mBottom - mInputEditor->getRect().mTop; - setDocked(true); mTypingStart = LLTrans::getString("IM_typing_start_string"); @@ -1171,17 +1167,6 @@ void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info) } } -void LLIMFloater::reshapeChatHistory() -{ - LLRect chat_rect = mChatHistory->getRect(); - LLRect input_rect = mInputEditor->getRect(); - - int delta_height = chat_rect.mBottom - (input_rect.mTop + mInputEditorTopPad); - - chat_rect.setLeftTopAndSize(chat_rect.mLeft, chat_rect.mTop, chat_rect.getWidth(), chat_rect.getHeight() + delta_height); - mChatHistory->setShape(chat_rect); -} - // static void LLIMFloater::closeHiddenIMToasts() { diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 1992bd930c..6847efedf1 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -163,13 +163,6 @@ private: // Remove the "User is typing..." indicator. void removeTypingIndicator(const LLIMInfo* im_info = NULL); - /** - * Adjusts chat history height to fit vertically with input chat field - * and avoid overlapping, since input chat field can be vertically expanded. - * Implementation: chat history bottom "follows" top+top_pad of input chat field - */ - void reshapeChatHistory(); - static void closeHiddenIMToasts(); static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); @@ -180,8 +173,6 @@ private: LLChatHistory* mChatHistory; - int mInputEditorTopPad; // padding between input field and chat history - EInstantMessage mDialog; LLUUID mOtherParticipantUUID; LLChatEntry* mInputEditor; diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 1b2d9b6801..29ab4384cb 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -30,6 +30,7 @@ #include "lliconctrl.h" #include "llappviewer.h" +#include "llchatentry.h" #include "llfloaterreg.h" #include "lltrans.h" #include "llimfloatercontainer.h" @@ -138,19 +139,14 @@ LLNearbyChat::LLNearbyChat(const LLSD& key) //virtual BOOL LLNearbyChat::postBuild() { - mChatBox = getChild<LLLineEditor>("chat_editor"); + mChatBox = getChild<LLChatEntry>("chat_editor"); mChatBox->setCommitCallback(boost::bind(&LLNearbyChat::onChatBoxCommit, this)); - mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this); + mChatBox->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this)); mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); mChatBox->setFocusReceivedCallback(boost::bind(&LLNearbyChat::onChatBoxFocusReceived, this)); - mChatBox->setIgnoreArrowKeys( FALSE ); mChatBox->setCommitOnFocusLost( FALSE ); - mChatBox->setRevertOnEsc( FALSE ); - mChatBox->setIgnoreTab(TRUE); mChatBox->setPassDelete(TRUE); - mChatBox->setReplaceNewlinesWithSpaces(FALSE); - mChatBox->setEnableLineHistory(TRUE); mChatBox->setFont(LLViewerChat::getChatFont()); // mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); @@ -459,7 +455,7 @@ BOOL LLNearbyChat::matchChatTypeTrigger(const std::string& in_str, std::string* return string_was_found; } -void LLNearbyChat::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) +void LLNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userdata) { LLFirstUse::otherAvatarChatFirst(false); @@ -513,17 +509,16 @@ void LLNearbyChat::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) { 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); + self->mChatBox->selectNext(rest_of_match, false); } else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) { 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 - self->mChatBox->setCursorToEnd(); + self->mChatBox->endOfDoc(); } //llinfos << "GESTUREDEBUG " << trigger @@ -581,11 +576,11 @@ void LLNearbyChat::sendChat( EChatType type ) { if (mChatBox) { - LLWString text = mChatBox->getConvertedText(); + LLWString text = mChatBox->getWText(); + LLWStringUtil::trim(text); + LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. 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); @@ -794,7 +789,7 @@ void LLNearbyChat::startChat(const char* line) cb->mChatBox->setText(line_string); } - cb->mChatBox->setCursorToEnd(); + cb->mChatBox->endOfDoc(); } } diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 3dc94ce0da..c9aa69a912 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -71,7 +71,7 @@ public: void onNearbyChatContextMenuItemClicked(const LLSD& userdata); bool onNearbyChatCheckContextMenuItem(const LLSD& userdata); - LLLineEditor* getChatBox() { return mChatBox; } + LLChatEntry* getChatBox() { return mChatBox; } //virtual void draw(); @@ -90,7 +90,7 @@ public: protected: static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); - static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata); + static void onChatBoxKeystroke(LLTextEditor* caller, void* userdata); static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); void onChatBoxFocusReceived(); @@ -113,7 +113,7 @@ protected: // Which non-zero channel did we last chat on? static S32 sLastSpecialChatChannel; - LLLineEditor* mChatBox; + LLChatEntry* mChatBox; LLOutputMonitorCtrl* mOutputMonitor; LLLocalSpeakerMgr* mSpeakerMgr; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 016da1d994..258bc5b698 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -56,6 +56,7 @@ // linden library includes #include "llaudioengine.h" // mute on minimize +#include "llchatentry.h" #include "indra_constants.h" #include "llassetstorage.h" #include "llerrorcontrol.h" @@ -2492,7 +2493,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) if (nearby_chat) { - LLLineEditor* chat_editor = nearby_chat->getChatBox(); + LLChatEntry* chat_editor = nearby_chat->getChatBox(); // arrow keys move avatar while chatting hack if (chat_editor && chat_editor->hasFocus()) @@ -2555,7 +2556,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) { - LLLineEditor* chat_editor = LLNearbyChat::getInstance()->getChatBox(); + LLChatEntry* chat_editor = LLNearbyChat::getInstance()->getChatBox(); if (chat_editor) { // passing NULL here, character will be added later when it is handled by character handler. -- cgit v1.2.3 From 91be3bf3019581b74a3515c1081aef883c0658fa Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 22 Jun 2012 16:56:33 +0300 Subject: CHUI-161 FIXED (Text entered in local chat is not visible to other users nearby) - Applied Merov's fix. The problem was that text_editor was registered twice and, depending of the machine you ran, the viewer would pick one or the other. Mac users were unlucky enough to pick the wrong one all the time. --- indra/llui/llchatentry.cpp | 2 +- indra/newview/skins/default/xui/en/floater_im_session.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index 1da7900f59..dea8ff9bb2 100644 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -28,7 +28,7 @@ #include "llchatentry.h" -static LLDefaultChildRegistry::Register<LLChatEntry> r("text_editor"); +static LLDefaultChildRegistry::Register<LLChatEntry> r("chat_editor"); LLChatEntry::Params::Params() : has_history("has_history", true), diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index f6d5b20a65..0720a4b011 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -242,7 +242,7 @@ bottom="-1" follows="left|right|bottom" tab_group="1"> - <text_editor + <chat_editor bottom="0" expand_lines_count="5" follows="left|right|bottom" @@ -256,7 +256,7 @@ tab_group="3" width="240" wrap="true"> - </text_editor> + </chat_editor> </panel> </layout_panel> </layout_stack> -- cgit v1.2.3 From 47c140b81d868229187f85185e4721946430ad87 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 22 Jun 2012 17:04:47 +0300 Subject: CHUI-127 ADDITIONAL FIX (Make chat field auto resizable) - Fixed crash which occurred while navigating through history of sent messages --- indra/llui/llchatentry.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index dea8ff9bb2..a6ba125406 100644 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -170,13 +170,14 @@ BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask) case KEY_DOWN: if (mHasHistory && MASK_CONTROL == mask) { - if (!mLineHistory.empty() && ++mCurrentHistoryLine < mLineHistory.end()) + if (!mLineHistory.empty() && mCurrentHistoryLine < (mLineHistory.end() - 1) ) { - setText(*mCurrentHistoryLine); + setText(*(++mCurrentHistoryLine)); endOfDoc(); } - else if (!mLineHistory.empty() && mCurrentHistoryLine == mLineHistory.end()) + else if (!mLineHistory.empty() && mCurrentHistoryLine == (mLineHistory.end() - 1) ) { + mCurrentHistoryLine++; std::string empty(""); setText(empty); needsReflow(); -- cgit v1.2.3 From 3807f97facc79960c579793376412a0baf6b9de3 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 22 Jun 2012 18:13:34 +0300 Subject: CHUI-136 FIXED (Implement new design for blocked list on the people floater) - Created new LLBlockList class and replaced LLScrollContainer with it - Also created new LLBlockedListItem class which represents blocked objects and blocked avatars --- indra/newview/CMakeLists.txt | 4 + indra/newview/app_settings/settings.xml | 11 + indra/newview/llblockedlistitem.cpp | 105 ++++++++ indra/newview/llblockedlistitem.h | 73 ++++++ indra/newview/llblocklist.cpp | 273 +++++++++++++++++++++ indra/newview/llblocklist.h | 138 +++++++++++ indra/newview/llgrouplist.h | 4 + indra/newview/llpanelblockedlist.cpp | 134 ++++++---- indra/newview/llpanelblockedlist.h | 35 +-- .../default/xui/en/menu_people_blocked_gear.xml | 26 ++ .../default/xui/en/menu_people_blocked_plus.xml | 20 ++ .../default/xui/en/menu_people_blocked_view.xml | 26 ++ .../default/xui/en/panel_block_list_sidetray.xml | 160 ++++++------ .../default/xui/en/panel_blocked_list_item.xml | 62 +++++ .../newview/skins/default/xui/en/panel_people.xml | 1 + 15 files changed, 928 insertions(+), 144 deletions(-) create mode 100644 indra/newview/llblockedlistitem.cpp create mode 100644 indra/newview/llblockedlistitem.h create mode 100644 indra/newview/llblocklist.cpp create mode 100644 indra/newview/llblocklist.h create mode 100644 indra/newview/skins/default/xui/en/menu_people_blocked_gear.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_blocked_plus.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_blocked_view.xml create mode 100644 indra/newview/skins/default/xui/en/panel_blocked_list_item.xml (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 785bf4b868..e67089c4de 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -103,6 +103,8 @@ set(viewer_SOURCE_FILES llavatarlist.cpp llavatarlistitem.cpp llavatarpropertiesprocessor.cpp + llblockedlistitem.cpp + llblocklist.cpp llbox.cpp llbreadcrumbview.cpp llbrowsernotification.cpp @@ -659,6 +661,8 @@ set(viewer_HEADER_FILES llavatarlist.h llavatarlistitem.h llavatarpropertiesprocessor.h + llblockedlistitem.h + llblocklist.h llbox.h llbreadcrumbview.h llbuycurrencyhtml.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index feb80a3611..fe6829a712 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9982,6 +9982,17 @@ <key>Value</key> <integer>2</integer> </map> + <key>BlockPeopleSortOrder</key> + <map> + <key>Comment</key> + <string>Specifies sort order for recent people (0 = by name, 1 = by type)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>2</integer> + </map> <key>ShowPGSearchAll</key> <map> <key>Comment</key> diff --git a/indra/newview/llblockedlistitem.cpp b/indra/newview/llblockedlistitem.cpp new file mode 100644 index 0000000000..14da35c85a --- /dev/null +++ b/indra/newview/llblockedlistitem.cpp @@ -0,0 +1,105 @@ +/** + * @file llviewerobjectlistitem.cpp + * @brief viewer object list item implementation + * + * Class LLPanelInventoryListItemBase displays inventory item as an element + * of LLInventoryItemsList. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llblockedlistitem.h" + +// llui +#include "lliconctrl.h" +#include "lltextbox.h" +#include "lltextutil.h" + +// newview +#include "llavatariconctrl.h" +#include "llinventoryicon.h" +#include "llviewerobject.h" + +LLBlockedListItem::LLBlockedListItem(const LLMute* item) +: LLPanel(), + mItemID(item->mID), + mItemName(item->mName), + mMuteType(item->mType) +{ + buildFromFile("panel_blocked_list_item.xml"); +} + +BOOL LLBlockedListItem::postBuild() +{ + mTitleCtrl = getChild<LLTextBox>("item_name"); + mTitleCtrl->setValue(mItemName); + + switch (mMuteType) + { + case LLMute::AGENT: + { + LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon"); + avatar_icon->setVisible(TRUE); + avatar_icon->setValue(mItemID); + } + break; + + case LLMute::OBJECT: + getChild<LLUICtrl>("object_icon")->setVisible(TRUE); + break; + + default: + break; + } + + return TRUE; +} + +void LLBlockedListItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ + getChildView("hovered_icon")->setVisible(true); + LLPanel::onMouseEnter(x, y, mask); +} + +void LLBlockedListItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ + getChildView("hovered_icon")->setVisible(false); + LLPanel::onMouseLeave(x, y, mask); +} + +void LLBlockedListItem::setValue(const LLSD& value) +{ + if (!value.isMap() || !value.has("selected")) + { + return; + } + + getChildView("selected_icon")->setVisible(value["selected"]); +} + +void LLBlockedListItem::highlightName(const std::string& highlited_text) +{ + LLStyle::Params params; + LLTextUtil::textboxSetHighlightedVal(mTitleCtrl, params, mItemName, highlited_text); +} diff --git a/indra/newview/llblockedlistitem.h b/indra/newview/llblockedlistitem.h new file mode 100644 index 0000000000..05409e8a3b --- /dev/null +++ b/indra/newview/llblockedlistitem.h @@ -0,0 +1,73 @@ +/** + * @file llviewerobjectlistitem.h + * @brief viewer object list item header file + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LLVIEWEROBJECTLISTITEM_H_ +#define LLVIEWEROBJECTLISTITEM_H_ + +#include "llmutelist.h" +#include "llpanel.h" +#include "llstyle.h" +#include "lltextbox.h" +#include "lliconctrl.h" + +/** + * This class represents items of LLBlockList, which represents + * contents of LLMuteList. LLMuteList "consists" of LLMute items. + * Each LLMute represents either blocked avatar or object and + * stores info about mute type (avatar or object) + * + * Each item consists if object/avatar icon and object/avatar name + * + * To create a blocked list item just need to pass LLMute pointer + * and appropriate block list item will be created depending on + * LLMute type (LLMute::EType) and other LLMute's info + */ +class LLBlockedListItem : public LLPanel +{ +public: + + LLBlockedListItem(const LLMute* item); + virtual BOOL postBuild(); + + void onMouseEnter(S32 x, S32 y, MASK mask); + void onMouseLeave(S32 x, S32 y, MASK mask); + + virtual void setValue(const LLSD& value); + + void highlightName(const std::string& highlited_text); + const std::string& getName() const { return mItemName; } + const LLMute::EType& getType() const { return mMuteType; } + const LLUUID& getUUID() const { return mItemID; } + +private: + + LLTextBox* mTitleCtrl; + const LLUUID mItemID; + std::string mItemName; + LLMute::EType mMuteType; + +}; + +#endif /* LLVIEWEROBJECTLISTITEM_H_ */ diff --git a/indra/newview/llblocklist.cpp b/indra/newview/llblocklist.cpp new file mode 100644 index 0000000000..521add4bdc --- /dev/null +++ b/indra/newview/llblocklist.cpp @@ -0,0 +1,273 @@ +/** + * @file llblocklist.cpp + * @brief List of the blocked avatars and objects. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llavataractions.h" +#include "llblocklist.h" +#include "llblockedlistitem.h" +#include "llfloatersidepanelcontainer.h" +#include "llviewermenu.h" + +static LLDefaultChildRegistry::Register<LLBlockList> r("block_list"); + +static const LLBlockListNameComparator NAME_COMPARATOR; +static const LLBlockListNameTypeComparator NAME_TYPE_COMPARATOR; + +LLBlockList::LLBlockList(const Params& p) +: LLFlatListViewEx(p), + mSelectedItem(NULL), + mDirty(true) +{ + + LLMuteList::getInstance()->addObserver(this); + + // Set up context menu. + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + + registrar.add ("Block.Action", boost::bind(&LLBlockList::onCustomAction, this, _2)); + enable_registrar.add("Block.Enable", boost::bind(&LLBlockList::isActionEnabled, this, _2)); + + LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>( + "menu_people_blocked_gear.xml", + gMenuHolder, + LLViewerMenuHolderGL::child_registry_t::instance()); + if(context_menu) + { + mContextMenu = context_menu->getHandle(); + } +} + +LLBlockList::~LLBlockList() +{ + if (mContextMenu.get()) + { + mContextMenu.get()->die(); + } + + LLMuteList::getInstance()->removeObserver(this); +} + +BOOL LLBlockList::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); + + LLToggleableMenu* context_menu = mContextMenu.get(); + if (context_menu && size()) + { + context_menu->buildDrawLabels(); + context_menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, context_menu, x, y); + } + + return handled; +} + +void LLBlockList::setNameFilter(const std::string& filter) +{ + std::string filter_upper = filter; + LLStringUtil::toUpper(filter_upper); + if (mNameFilter != filter_upper) + { + mNameFilter = filter_upper; + setDirty(); + } +} + +void LLBlockList::sortByName() +{ + setComparator(&NAME_COMPARATOR); + sort(); +} + +void LLBlockList::sortByType() +{ + setComparator(&NAME_TYPE_COMPARATOR); + sort(); +} + +void LLBlockList::draw() +{ + if (mDirty) + { + refresh(); + } + + LLFlatListView::draw(); +} + +void LLBlockList::addNewItem(const LLMute* mute) +{ + LLBlockedListItem* item = new LLBlockedListItem(mute); + if (!mNameFilter.empty()) + { + item->highlightName(mNameFilter); + } + addItem(item, item->getUUID(), ADD_BOTTOM); +} + +void LLBlockList::refresh() +{ + bool have_filter = !mNameFilter.empty(); + + // save selection to restore it after list rebuilt + LLUUID selected = getSelectedUUID(); + + // calling refresh may be initiated by removing currently selected item + // so select next item and save the selection to restore it after list rebuilt + if (!selectNextItemPair(false, true)) + { + selectNextItemPair(true, true); + } + LLUUID next_selected = getSelectedUUID(); + + clear(); + + std::vector<LLMute> mutes = LLMuteList::instance().getMutes(); + std::vector<LLMute>::const_iterator mute_it = mutes.begin(); + + for (; mute_it != mutes.end(); ++mute_it) + { + if (have_filter && !findInsensitive(mute_it->mName, mNameFilter)) + continue; + + addNewItem(&*mute_it); + } + + if (getItemPair(selected)) + { + // restore previously selected item + selectItemPair(getItemPair(selected), true); + } + else if (getItemPair(next_selected)) + { + // previously selected item was removed, so select next item + selectItemPair(getItemPair(next_selected), true); + } + + // Sort the list. + sort(); + + setDirty(false); +} + +bool LLBlockList::findInsensitive(std::string haystack, const std::string& needle_upper) +{ + LLStringUtil::toUpper(haystack); + return haystack.find(needle_upper) != std::string::npos; +} + +LLBlockedListItem* LLBlockList::getBlockedItem() const +{ + LLPanel* panel = LLFlatListView::getSelectedItem(); + LLBlockedListItem* item = dynamic_cast<LLBlockedListItem*>(panel); + return item; +} + +bool LLBlockList::isActionEnabled(const LLSD& userdata) +{ + bool action_enabled = true; + + const std::string command_name = userdata.asString(); + + if ("unblock_item" == command_name || "profile_item" == command_name) + { + action_enabled = getSelectedItem() != NULL; + } + + return action_enabled; +} + +void LLBlockList::onCustomAction(const LLSD& userdata) +{ + if (!isActionEnabled(userdata)) + { + return; + } + + LLBlockedListItem* item = getBlockedItem(); + const std::string command_name = userdata.asString(); + + if ("unblock_item" == command_name) + { + LLMute mute(item->getUUID(), item->getName()); + LLMuteList::getInstance()->remove(mute); + } + else if ("profile_item" == command_name) + { + switch(item->getType()) + { + + case LLMute::AGENT: + LLAvatarActions::showProfile(item->getUUID()); + break; + + case LLMute::OBJECT: + LLFloaterSidePanelContainer::showPanel("inventory", LLSD().with("id", item->getUUID())); + break; + + default: + break; + } + } +} + +bool LLBlockListItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const +{ + const LLBlockedListItem* blocked_item1 = dynamic_cast<const LLBlockedListItem*>(item1); + const LLBlockedListItem* blocked_item2 = dynamic_cast<const LLBlockedListItem*>(item2); + + if (!blocked_item1 || !blocked_item2) + { + llerror("blocked_item1 and blocked_item2 cannot be null", 0); + return true; + } + + return doCompare(blocked_item1, blocked_item2); +} + +bool LLBlockListNameComparator::doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const +{ + std::string name1 = blocked_item1->getName(); + std::string name2 = blocked_item2->getName(); + + LLStringUtil::toUpper(name1); + LLStringUtil::toUpper(name2); + + return name1 < name2; +} + +bool LLBlockListNameTypeComparator::doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const +{ + LLMute::EType type1 = blocked_item1->getType(); + LLMute::EType type2 = blocked_item2->getType(); + + if (type1 != type2) + { + return type1 > type2; + } + + return NAME_COMPARATOR.compare(blocked_item1, blocked_item2); +} diff --git a/indra/newview/llblocklist.h b/indra/newview/llblocklist.h new file mode 100644 index 0000000000..1a215710f4 --- /dev/null +++ b/indra/newview/llblocklist.h @@ -0,0 +1,138 @@ +/** + * @file llblocklist.h + * @brief List of the blocked avatars and objects. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LLBLOCKLIST_H_ +#define LLBLOCKLIST_H_ + +#include "llflatlistview.h" +#include "lllistcontextmenu.h" +#include "llmutelist.h" +#include "lltoggleablemenu.h" + +class LLBlockedListItem; +class LLMute; + +/** + * List of blocked avatars and objects. + * This list represents contents of the LLMuteList. + * Each change in LLMuteList leads to rebuilding this list, so + * it's always in actual state. + */ +class LLBlockList: public LLFlatListViewEx, public LLMuteListObserver +{ + LOG_CLASS(LLBlockList); +public: + struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params> + { + Params(){}; + }; + + LLBlockList(const Params& p); + virtual ~LLBlockList(); + + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + LLToggleableMenu* getContextMenu() const { return mContextMenu.get(); } + LLBlockedListItem* getBlockedItem() const; + + virtual void onChange() { refresh(); } + virtual void draw(); + + void setNameFilter(const std::string& filter); + void sortByName(); + void sortByType(); + void refresh(); + +private: + + void addNewItem(const LLMute* mute); + void setDirty(bool dirty = true) { mDirty = dirty; } + bool findInsensitive(std::string haystack, const std::string& needle_upper); + + bool isActionEnabled(const LLSD& userdata); + void onCustomAction (const LLSD& userdata); + + + LLHandle<LLToggleableMenu> mContextMenu; + + LLBlockedListItem* mSelectedItem; + std::string mNameFilter; + bool mDirty; + +}; + + +/* + * Abstract comparator for blocked items + */ +class LLBlockListItemComparator : public LLFlatListView::ItemComparator +{ + LOG_CLASS(LLBlockListItemComparator); + +public: + LLBlockListItemComparator() {}; + virtual ~LLBlockListItemComparator() {}; + + virtual bool compare(const LLPanel* item1, const LLPanel* item2) const; + +protected: + + virtual bool doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const = 0; +}; + + +/* + * Compares items by name + */ +class LLBlockListNameComparator : public LLBlockListItemComparator +{ + LOG_CLASS(LLBlockListNameComparator); + +public: + LLBlockListNameComparator() {}; + virtual ~LLBlockListNameComparator() {}; + +protected: + + virtual bool doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const; +}; + +/* + * Compares items by type and then by name within type + * Objects come first then avatars + */ +class LLBlockListNameTypeComparator : public LLBlockListItemComparator +{ + LOG_CLASS(LLBlockListNameTypeComparator); + +public: + LLBlockListNameTypeComparator() {}; + virtual ~LLBlockListNameTypeComparator() {}; + +protected: + + virtual bool doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const; +}; + +#endif /* LLBLOCKLIST_H_ */ diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 6c8f4406ab..e96a720886 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -48,6 +48,10 @@ class LLGroupList: public LLFlatListViewEx, public LLOldEvents::LLSimpleListener { LOG_CLASS(LLGroupList); public: + struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params> + { + Params(){}; + }; LLGroupList(const Params& p); virtual ~LLGroupList(); diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index d2dff63948..35cda14f8d 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -30,15 +30,23 @@ // library include #include "llavatarname.h" +#include "llfiltereditor.h" #include "llfloater.h" #include "llfloaterreg.h" #include "llnotificationsutil.h" #include "llscrolllistctrl.h" +#include "llmenubutton.h" // project include +#include "llavatarlistitem.h" +#include "llblocklist.h" +#include "llblockedlistitem.h" #include "llfloateravatarpicker.h" #include "llfloatersidepanelcontainer.h" +#include "llinventorylistitem.h" +#include "llinventorymodel.h" #include "llsidetraypanelcontainer.h" +#include "llviewercontrol.h" static LLRegisterPanelClassWrapper<LLPanelBlockedList> t_panel_blocked_list("panel_block_list_sidetray"); @@ -54,24 +62,35 @@ const std::string BLOCKED_PARAM_NAME = "blocked_to_select"; LLPanelBlockedList::LLPanelBlockedList() : LLPanel() { - mCommitCallbackRegistrar.add("Block.ClickPick", boost::bind(&LLPanelBlockedList::onPickBtnClick, this)); - mCommitCallbackRegistrar.add("Block.ClickBlockByName", boost::bind(&LLPanelBlockedList::onBlockByNameClick, this)); - mCommitCallbackRegistrar.add("Block.ClickRemove", boost::bind(&LLPanelBlockedList::onRemoveBtnClick, this)); -} - -LLPanelBlockedList::~LLPanelBlockedList() -{ - LLMuteList::getInstance()->removeObserver(this); + mCommitCallbackRegistrar.add("Block.Action", boost::bind(&LLPanelBlockedList::onCustomAction, this, _2)); + mEnableCallbackRegistrar.add("Block.Check", boost::bind(&LLPanelBlockedList::isActionChecked, this, _2)); } BOOL LLPanelBlockedList::postBuild() { - mBlockedList = getChild<LLScrollListCtrl>("blocked"); + mBlockedList = getChild<LLBlockList>("blocked"); mBlockedList->setCommitOnSelectionChange(TRUE); - LLMuteList::getInstance()->addObserver(this); - - refreshBlockedList(); + switch (gSavedSettings.getU32("BlockPeopleSortOrder")) + { + case E_SORT_BY_NAME: + mBlockedList->sortByName(); + break; + + case E_SORT_BY_TYPE: + mBlockedList->sortByType(); + break; + } + + // Use the context menu of the Block list for the Block tab gear menu. + LLToggleableMenu* blocked_gear_menu = mBlockedList->getContextMenu(); + if (blocked_gear_menu) + { + getChild<LLMenuButton>("blocked_gear_btn")->setMenu(blocked_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); + } + + getChild<LLButton>("unblock_btn")->setCommitCallback(boost::bind(&LLPanelBlockedList::unblockItem, this)); + getChild<LLFilterEditor>("blocked_filter_input")->setCommitCallback(boost::bind(&LLPanelBlockedList::onFilterEdit, this, _2)); return LLPanel::postBuild(); } @@ -92,7 +111,7 @@ void LLPanelBlockedList::onOpen(const LLSD& key) void LLPanelBlockedList::selectBlocked(const LLUUID& mute_id) { - mBlockedList->selectByID(mute_id); + mBlockedList->selectItemByUUID(mute_id); } void LLPanelBlockedList::showPanelAndSelect(const LLUUID& idToSelect) @@ -105,55 +124,64 @@ void LLPanelBlockedList::showPanelAndSelect(const LLUUID& idToSelect) ////////////////////////////////////////////////////////////////////////// // Private Section ////////////////////////////////////////////////////////////////////////// -void LLPanelBlockedList::refreshBlockedList() +void LLPanelBlockedList::updateButtons() { - mBlockedList->deleteAllItems(); + bool hasSelected = NULL != mBlockedList->getSelectedItem(); + getChildView("unblock_btn")->setEnabled(hasSelected); +} - std::vector<LLMute> mutes = LLMuteList::getInstance()->getMutes(); - std::vector<LLMute>::iterator it; - for (it = mutes.begin(); it != mutes.end(); ++it) +void LLPanelBlockedList::unblockItem() +{ + LLBlockedListItem* item = mBlockedList->getBlockedItem(); + if (item) { - LLScrollListItem::Params item_p; - item_p.enabled(TRUE); - item_p.value(it->mID); // link UUID of blocked item with ScrollListItem - item_p.columns.add().column("item_name").value(it->mName);//.type("text"); - item_p.columns.add().column("item_type").value(it->getDisplayType());//.type("text").width(111); - - mBlockedList->addRow(item_p, ADD_BOTTOM); + LLMute mute(item->getUUID(), item->getName()); + LLMuteList::instance().remove(mute); } } -void LLPanelBlockedList::updateButtons() +void LLPanelBlockedList::onCustomAction(const LLSD& userdata) { - bool hasSelected = NULL != mBlockedList->getFirstSelected(); - getChildView("Unblock")->setEnabled(hasSelected); + const std::string command_name = userdata.asString(); + + if ("block_obj_by_name" == command_name) + { + blockObjectByName(); + } + else if ("block_res_by_name" == command_name) + { + blockResidentByName(); + } + else if ("sort_by_name" == command_name) + { + mBlockedList->sortByName(); + gSavedSettings.setU32("BlockPeopleSortOrder", E_SORT_BY_NAME); + } + else if ("sort_by_type" == command_name) + { + mBlockedList->sortByType(); + gSavedSettings.setU32("BlockPeopleSortOrder", E_SORT_BY_TYPE); + } } -void LLPanelBlockedList::onRemoveBtnClick() +BOOL LLPanelBlockedList::isActionChecked(const LLSD& userdata) { - std::string name = mBlockedList->getSelectedItemLabel(); - LLUUID id = mBlockedList->getStringUUIDSelectedItem(); - LLMute mute(id, name); - - S32 last_selected = mBlockedList->getFirstSelectedIndex(); - if (LLMuteList::getInstance()->remove(mute)) + std::string item = userdata.asString(); + U32 sort_order = gSavedSettings.getU32("BlockPeopleSortOrder"); + + if ("sort_by_name" == item) + { + return E_SORT_BY_NAME == sort_order; + } + else if ("sort_by_type" == item) { - // Above removals may rebuild this dialog. - - if (last_selected == mBlockedList->getItemCount()) - { - // we were on the last item, so select the last item again - mBlockedList->selectNthItem(last_selected - 1); - } - else - { - // else select the item after the last item previously selected - mBlockedList->selectNthItem(last_selected); - } + return E_SORT_BY_TYPE == sort_order; } + + return false; } -void LLPanelBlockedList::onPickBtnClick() +void LLPanelBlockedList::blockResidentByName() { const BOOL allow_multiple = FALSE; const BOOL close_on_select = TRUE; @@ -164,11 +192,19 @@ void LLPanelBlockedList::onPickBtnClick() // addDependentFloater(picker); } -void LLPanelBlockedList::onBlockByNameClick() +void LLPanelBlockedList::blockObjectByName() { LLFloaterGetBlockedObjectName::show(&LLPanelBlockedList::callbackBlockByName); } +void LLPanelBlockedList::onFilterEdit(const std::string& search_string) +{ + std::string filter = search_string; + LLStringUtil::trimHead(filter); + + mBlockedList->setNameFilter(filter); +} + void LLPanelBlockedList::callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names) { if (names.empty() || ids.empty()) return; diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h index 97236ecdbf..332349dfc0 100644 --- a/indra/newview/llpanelblockedlist.h +++ b/indra/newview/llpanelblockedlist.h @@ -30,21 +30,15 @@ #include "llpanel.h" #include "llmutelist.h" #include "llfloater.h" -// #include <vector> -// class LLButton; -// class LLLineEditor; -// class LLMessageSystem; -// class LLUUID; class LLAvatarName; -class LLScrollListCtrl; +class LLBlockList; -class LLPanelBlockedList - : public LLPanel, public LLMuteListObserver +class LLPanelBlockedList : public LLPanel { public: LLPanelBlockedList(); - ~LLPanelBlockedList(); + ~LLPanelBlockedList(){}; virtual BOOL postBuild(); virtual void draw(); @@ -59,24 +53,31 @@ public: * If it is LLUUID::null, nothing will be selected. */ static void showPanelAndSelect(const LLUUID& idToSelect); - - // LLMuteListObserver callback interface implementation. - /* virtual */ void onChange() { refreshBlockedList();} private: - void refreshBlockedList(); + + typedef enum e_sort_oder{ + E_SORT_BY_NAME = 0, + E_SORT_BY_TYPE = 1, + } ESortOrder; + void updateButtons(); // UI callbacks - void onRemoveBtnClick(); - void onPickBtnClick(); - void onBlockByNameClick(); + void unblockItem(); + void blockResidentByName(); + void blockObjectByName(); + void onFilterEdit(const std::string& search_string); + + // List commnads + void onCustomAction(const LLSD& userdata); + BOOL isActionChecked(const LLSD& userdata); void callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names); static void callbackBlockByName(const std::string& text); private: - LLScrollListCtrl* mBlockedList; + LLBlockList* mBlockedList; }; //----------------------------------------------------------------------------- diff --git a/indra/newview/skins/default/xui/en/menu_people_blocked_gear.xml b/indra/newview/skins/default/xui/en/menu_people_blocked_gear.xml new file mode 100644 index 0000000000..63295ea27b --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_blocked_gear.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_blocked_gear" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_call + label="Unblock" + name="unblock"> + <on_click + function="Block.Action" + parameter="unblock_item" /> + <on_enable + function="Block.Enable" + parameter="unblock_item" /> + </menu_item_call> + <menu_item_call + label="Profile..." + name="profile"> + <on_click + function="Block.Action" + parameter="profile_item"/> + <on_enable + function="Block.Enable" + parameter="profile_item" /> + </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_blocked_plus.xml b/indra/newview/skins/default/xui/en/menu_people_blocked_plus.xml new file mode 100644 index 0000000000..0c7155667e --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_blocked_plus.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_blocked_plus" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_call + label="Block Resident by name..." + name="block_resident_by_name"> + <on_click + function="Block.Action" + parameter="block_res_by_name"/> + </menu_item_call> + <menu_item_call + label="Block object by name" + name="block_object_by_name"> + <on_click + function="Block.Action" + parameter="block_obj_by_name"/> + </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_blocked_view.xml b/indra/newview/skins/default/xui/en/menu_people_blocked_view.xml new file mode 100644 index 0000000000..2efb70ee37 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_blocked_view.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_blocked_view" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_check + label="Sort by name" + name="sort_by_name"> + <on_click + function="Block.Action" + parameter="sort_by_name"/> + <on_check + function="Block.Check" + parameter="sort_by_name"/> + </menu_item_check> + <menu_item_check + label="Sort by type" + name="sort_by_type"> + <on_click + function="Block.Action" + parameter="sort_by_type" /> + <on_check + function="Block.Check" + parameter="sort_by_type" /> + </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml index 3577d2f457..f466504938 100644 --- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -5,90 +5,94 @@ height="305" layout="topleft" left="0" - right="-1" name="block_list_panel" help_topic="blocked_list" min_height="350" min_width="240" - width="280"> - <button - follows="top|left" - height="24" - image_hover_unselected="BackButton_Over" - image_pressed="BackButton_Press" - image_unselected="BackButton_Off" - layout="topleft" - name="back" - left="4" - tab_stop="false" - top="1" - width="30"/> - <text - follows="top|left|right" - font="SansSerifLargeBold" - height="20" - layout="topleft" - left_pad="10" - name="title_text" - text_color="white" - top="5" - width="250"> - Block List - </text> - <scroll_list + width="323"> + <panel + follows="left|top|right" + height="27" + label="bottom_panel" + layout="topleft" + left="0" + name="blocked_buttons_panel" + right="-1" + top="0"> + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="6" + label="Filter" + max_length_chars="300" + name="blocked_filter_input" + text_color="Black" + text_pad_left="10" + top="4" + width="177" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="8" + menu_filename="menu_people_blocked_gear.xml" + menu_position="bottomleft" + name="blocked_gear_btn" + top="3" + width="31" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Inv_Underpants" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + menu_filename="menu_people_blocked_view.xml" + menu_position="bottomleft" + name="view_btn" + top_delta="0" + width="31" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + menu_filename="menu_people_blocked_plus.xml" + menu_position="bottomleft" + name="plus_btn" + top_delta="0" + width="31"/> + <button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TrashItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + left_pad="2" + layout="topleft" + name="unblock_btn" + top_delta="0" + width="31"/> + </panel> + <block_list follows="all" - height="190" + height="273" layout="topleft" - left="5" + left="3" name="blocked" tool_tip="List of currently blocked Residents" - top="30" - right="-1" - width="270"> - <scroll_list.columns - name="item_name" /> - <scroll_list.columns - name="item_type" - width="96" /> - </scroll_list> - <button - follows="left|bottom" - height="23" - label="Block person" - layout="topleft" - left_delta="0" - name="Block resident..." - tool_tip="Pick a Resident to block" - top_pad="4" - width="210"> - <button.commit_callback - function="Block.ClickPick" /> - </button> - <button - follows="left|bottom" - height="23" - label="Block object by name" - layout="topleft" - left_delta="0" - name="Block object by name..." - tool_tip="Pick an object to block by name" - top_pad="4" - width="210" > - <button.commit_callback - function="Block.ClickBlockByName" /> - </button> - <button - enabled="false" - follows="left|bottom" - height="23" - label="Unblock" - layout="topleft" - left_delta="0" - name="Unblock" - tool_tip="Remove Resident or object from blocked list" - top_pad="4" - width="210" > - <button.commit_callback - function="Block.ClickRemove" /> - </button> + top="31" + right="-1"/> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml new file mode 100644 index 0000000000..a63a14ca69 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="top|right|left" + height="23" + layout="topleft" + left="0" + name="blocked_list_item" + top="0" + width="380"> + <icon + height="24" + follows="top|right|left" + image_name="ListItem_Select" + layout="topleft" + left="0" + name="selected_icon" + top="0" + visible="false" + width="380" /> + <icon + follows="top|right|left" + height="24" + image_name="ListItem_Over" + layout="topleft" + left="0" + name="hovered_icon" + top="0" + visible="false" + width="380" /> + <avatar_icon + default_icon_name="Generic_Person" + follows="top|left" + height="20" + layout="topleft" + left="5" + mouse_opaque="true" + top="2" + visible="false" + width="20" /> + <icon + follows="top|left" + height="16" + image_name="Inv_Object" + layout="topleft" + left="7" + name="object_icon" + top="4" + visible="false" + width="16" /> + <text + follows="left|right" + font="SansSerifSmall" + font.color="DkGray" + height="15" + layout="topleft" + left_pad="5" + name="item_name" + parse_urls="false" + top="6" + use_ellipses="true" + width="180" /> +</panel> \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index ceb03d03a9..38a996547c 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -611,6 +611,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M filename="panel_block_list_sidetray.xml" follows="all" label="Blocked Residents & Objects" + layout="topleft" left="0" font="SansSerifBold" top="0" -- cgit v1.2.3 From afc6a7e6baeb9b568feb31cfd8eb978bb485c0c6 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 22 Jun 2012 20:05:35 +0300 Subject: CHUI-136 ADDITIONAL FIX (Implement new design for blocked list on the people floater) - If mute item type is LLMute::BY_NAME it means that it's an object and we should show corresponding icon - Also added icon for blocked groups --- indra/newview/llblockedlistitem.cpp | 11 ++++++++++- .../newview/skins/default/xui/en/panel_blocked_list_item.xml | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llblockedlistitem.cpp b/indra/newview/llblockedlistitem.cpp index 14da35c85a..d9afd2b629 100644 --- a/indra/newview/llblockedlistitem.cpp +++ b/indra/newview/llblockedlistitem.cpp @@ -38,6 +38,7 @@ // newview #include "llavatariconctrl.h" +#include "llgroupiconctrl.h" #include "llinventoryicon.h" #include "llviewerobject.h" @@ -58,14 +59,22 @@ BOOL LLBlockedListItem::postBuild() switch (mMuteType) { case LLMute::AGENT: + case LLMute::EXTERNAL: { LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon"); avatar_icon->setVisible(TRUE); avatar_icon->setValue(mItemID); } break; - + case LLMute::GROUP: + { + LLGroupIconCtrl* group_icon = getChild<LLGroupIconCtrl>("group_icon"); + group_icon->setVisible(TRUE); + group_icon->setValue(mItemID); + } + break; case LLMute::OBJECT: + case LLMute::BY_NAME: getChild<LLUICtrl>("object_icon")->setVisible(TRUE); break; diff --git a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml index a63a14ca69..84e7e467b1 100644 --- a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml @@ -37,6 +37,16 @@ top="2" visible="false" width="20" /> + <group_icon + default_icon_name="Generic_Group" + follows="top|left" + height="20" + layout="topleft" + left="5" + mouse_opaque="true" + top="2" + visible="false" + width="20" /> <icon follows="top|left" height="16" -- cgit v1.2.3 From 75804ef2b918906108af4a3b9ceb6cbfc1354393 Mon Sep 17 00:00:00 2001 From: merov <none@none> Date: Fri, 22 Jun 2012 19:28:11 +0100 Subject: CHUI-136 : Fix compilation issue showing up when warning treated as errors --- indra/newview/llblocklist.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llblocklist.cpp b/indra/newview/llblocklist.cpp index 521add4bdc..cb68f677eb 100644 --- a/indra/newview/llblocklist.cpp +++ b/indra/newview/llblocklist.cpp @@ -24,8 +24,11 @@ * $/LicenseInfo$ */ -#include "llavataractions.h" +#include "llviewerprecompiledheaders.h" + #include "llblocklist.h" + +#include "llavataractions.h" #include "llblockedlistitem.h" #include "llfloatersidepanelcontainer.h" #include "llviewermenu.h" -- cgit v1.2.3 From 74092930afdc294ef4d204830173d4750a310616 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 22 Jun 2012 14:13:20 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose build fix for gcc added detection of duplicate widget registration --- indra/llui/lluictrlfactory.cpp | 15 ++++++++------- indra/llui/lluictrlfactory.h | 4 ++-- indra/llxuixml/llregistry.h | 4 ++++ indra/newview/llfolderviewmodel.h | 2 +- 4 files changed, 15 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 25e7a31e90..f64f33bc5e 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -278,13 +278,13 @@ const LLInitParam::BaseBlock& get_empty_param_block() // adds a widget and its param block to various registries //static -void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& tag) +void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& name) { // associate parameter block type with template .xml file - std::string* existing_tag = LLWidgetNameRegistry::instance().getValue(param_block_type); - if (existing_tag != NULL) + std::string* existing_name = LLWidgetNameRegistry::instance().getValue(param_block_type); + if (existing_name != NULL) { - if(*existing_tag != tag) + if(*existing_name != name) { std::cerr << "Duplicate entry for T::Params, try creating empty param block in derived classes that inherit T::Params" << std::endl; // forcing crash here @@ -293,18 +293,19 @@ void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const st } else { - // widget already registered + // widget already registered this name return; } } - LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, tag); + + LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, name); //FIXME: comment this in when working on schema generation //LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type); //LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type, &get_empty_param_block<T>); } //static -const std::string* LLUICtrlFactory::getWidgetTag(const std::type_info* widget_type) +const std::string* LLUICtrlFactory::getWidgetName(const std::type_info* widget_type) { return LLWidgetNameRegistry::instance().getValue(widget_type); } diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index d612ad5005..b441cb0c9d 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -105,7 +105,7 @@ private: ParamDefaults() { // look up template file for this param block... - const std::string* param_block_tag = getWidgetTag(&typeid(PARAM_BLOCK)); + const std::string* param_block_tag = getWidgetName(&typeid(PARAM_BLOCK)); if (param_block_tag) { // ...and if it exists, back fill values using the most specific template first PARAM_BLOCK params; @@ -303,7 +303,7 @@ private: } - static const std::string* getWidgetTag(const std::type_info* widget_type); + static const std::string* getWidgetName(const std::type_info* widget_type); // this exists to get around dependency on llview static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group); diff --git a/indra/llxuixml/llregistry.h b/indra/llxuixml/llregistry.h index 36ce6a97b7..3e8d9267cc 100644 --- a/indra/llxuixml/llregistry.h +++ b/indra/llxuixml/llregistry.h @@ -302,6 +302,10 @@ public: virtual ~StaticRegistrar() {} StaticRegistrar(ref_const_key_t key, ref_const_value_t value) { + if (singleton_t::instance().exists(key)) + { + llerrs << "Duplicate registry entry under key \"" << key << "\"" << llendl; + } singleton_t::instance().mStaticScope->add(key, value); } }; diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index c3dcfed97c..74c8bb92ef 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -218,7 +218,7 @@ public: virtual S32 getSortVersion() = 0; virtual void setSortVersion(S32 version) = 0; protected: - friend LLFolderViewItem; + friend class LLFolderViewItem; void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} LLFolderViewItem* mFolderViewItem; -- cgit v1.2.3 From 9fc77dec8788944f93eda14567f9235f97637097 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Mon, 25 Jun 2012 15:49:49 +0300 Subject: CHUI-175 FIXED (Cannot use scroll bar on chat entry field when multi line chat is added) - This change also fixes: CHUI-176 (Only bottom 2 lines of multi line chat allow for selecting in text chat entry) CHUI-177 (Text entry field in chat only accepts 256 characters) --- .../skins/default/xui/en/floater_im_session.xml | 39 +++++++++------------- 1 file changed, 16 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 0720a4b011..56e591e2bb 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -235,29 +235,22 @@ </layout_panel> </layout_stack> </panel> - <panel width="225" - height="31" - left="4" - name="bottom_panel" - bottom="-1" - follows="left|right|bottom" - tab_group="1"> - <chat_editor - bottom="0" - expand_lines_count="5" - follows="left|right|bottom" - font="SansSerifSmall" - visible="true" - height="20" - is_expandable="true" - label="To" - layout="bottomleft" - name="chat_editor" - tab_group="3" - width="240" - wrap="true"> - </chat_editor> - </panel> + <chat_editor + bottom="0" + expand_lines_count="5" + follows="left|right|bottom" + font="SansSerifSmall" + visible="true" + height="20" + is_expandable="true" + label="To" + layout="bottomleft" + name="chat_editor" + max_length="1024" + tab_group="3" + width="240" + wrap="true"> + </chat_editor> </layout_panel> </layout_stack> </view> -- cgit v1.2.3 From 9353a9e6ef071bd980c319d038b1dedb649d2db0 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 25 Jun 2012 23:55:25 +0300 Subject: CHUI-167 FIXED Move onClose() from LLIMFloater to it's basic class (LLIMConversation) for correct using add/remove conversation list items also for LLNearbyChat --- indra/newview/llimconversation.cpp | 14 +++++++ indra/newview/llimconversation.h | 1 + indra/newview/llimfloater.cpp | 84 ++++++++++++++++++-------------------- 3 files changed, 54 insertions(+), 45 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index cbebf3edd3..f304997abf 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -339,6 +339,20 @@ void LLIMConversation::onOpen(const LLSD& key) updateHeaderAndToolbar(); } +// virtual +void LLIMConversation::onClose(bool app_quitting) +{ + // Always suppress the IM from the conversations list on close if present for any reason + if (LLIMConversation::isChatMultiTab()) + { + LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); + if (im_box) + { + im_box->removeConversationListItem(mSessionID); + } + } +} + void LLIMConversation::onTearOffClicked() { onClickTearOff(this); diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index f4b8a38242..47c98d6f8b 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -63,6 +63,7 @@ public: // LLFloater overrides /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClose(bool app_quitting); /*virtual*/ BOOL postBuild(); protected: diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 98ebc82f99..37ee7b8a7c 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -105,51 +105,6 @@ void LLIMFloater::onFocusReceived() } } -// virtual -void LLIMFloater::onClose(bool app_quitting) -{ - // Always suppress the IM from the conversations list on close if present for any reason - if (LLIMConversation::isChatMultiTab()) - { - LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); - if (im_box) - { - im_box->removeConversationListItem(mSessionID); - } - } - - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - mSessionID); - - if (session == NULL) - { - llwarns << "Empty session." << llendl; - return; - } - - bool is_call_with_chat = session->isGroupSessionType() - || session->isAdHocSessionType() || session->isP2PSessionType(); - - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - - if (is_call_with_chat && voice_channel != NULL - && voice_channel->isActive()) - { - LLSD payload; - payload["session_id"] = mSessionID; - LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); - return; - } - - setTyping(false); - - // The source of much argument and design thrashing - // Should the window hide or the session close when the X is clicked? - // - // Last change: - // EXT-3516 X Button should end IM session, _ button should hide - gIMMgr->leaveSession(mSessionID); -} /* static */ void LLIMFloater::newIMCallback(const LLSD& data) @@ -611,6 +566,45 @@ LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) return conversation; } +void LLIMFloater::onClose(bool app_quitting) +{ + LLIMConversation::onClose(app_quitting); + + + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( + mSessionID); + + if (session == NULL) + { + llwarns << "Empty session." << llendl; + return; + } + + bool is_call_with_chat = session->isGroupSessionType() + || session->isAdHocSessionType() || session->isP2PSessionType(); + + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + + if (is_call_with_chat && voice_channel != NULL + && voice_channel->isActive()) + { + LLSD payload; + payload["session_id"] = mSessionID; + LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); + return; + } + + setTyping(false); + + // The source of much argument and design thrashing + // Should the window hide or the session close when the X is clicked? + // + // Last change: + // EXT-3516 X Button should end IM session, _ button should hide + gIMMgr->leaveSession(mSessionID); + +} + void LLIMFloater::setDocked(bool docked, bool pop_on_undock) { // update notification channel state -- cgit v1.2.3 From 7f3b27289da2478381dcb4d7e9f05e082e37eaa2 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 25 Jun 2012 21:59:13 +0300 Subject: CHUI-168 FIXED Added call of updateHeaderAndToolbar from postBuild for correct floater's title and standard buttons showing at start --- indra/newview/llimconversation.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index f304997abf..d3f3e41a29 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -103,6 +103,7 @@ BOOL LLIMConversation::postBuild() } buildParticipantList(); + updateHeaderAndToolbar(); if (isChatMultiTab()) { -- cgit v1.2.3 From 5b6db72c5b7c5c3c4cfde671480ec1fc56bbd859 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Mon, 25 Jun 2012 13:04:09 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose all inventory names are correctly initialized now --- indra/newview/llinventorybridge.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index c0670b71d4..70a174a140 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1844,14 +1844,17 @@ void LLFolderBridge::buildDisplayName() const //"Accessories" inventory category has folder type FT_NONE. So, this folder //can not be detected as protected with LLFolderType::lookupIsProtectedType + mDisplayName.assign(getName()); if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) { LLTrans::findString(mDisplayName, std::string("InvFolder ") + getName(), LLSD()); } - else - { - mDisplayName.assign(getName()); - } + + //if (mDisplayName.empty()) + //{ + // S32 foo; + // foo = 0; + //} } -- cgit v1.2.3 From 41e965c12e29136d2b81a9b67d6b6c9af4fb2092 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 25 Jun 2012 15:20:52 -0700 Subject: CHUI-139 : Hide torn off floaters when hiding conversation list; make nearby chat always present; leave conversation list around when all torn off --- indra/llui/llmultifloater.h | 4 +-- indra/newview/llimconversation.cpp | 6 +++- indra/newview/llimfloatercontainer.cpp | 51 ++++++++++++++++++++++++++++++++-- indra/newview/llimfloatercontainer.h | 6 ++++ 4 files changed, 62 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h index f299ae5dd3..44514a6246 100644 --- a/indra/llui/llmultifloater.h +++ b/indra/llui/llmultifloater.h @@ -45,8 +45,8 @@ public: virtual BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void draw(); - /*virtual*/ void setVisible(BOOL visible); + virtual void draw(); + virtual void setVisible(BOOL visible); /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index bbbc9fcffd..cbebf3edd3 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -106,6 +106,10 @@ BOOL LLIMConversation::postBuild() if (isChatMultiTab()) { + if (mIsNearbyChat) + { + setCanClose(FALSE); + } return LLFloater::postBuild(); } else @@ -246,7 +250,7 @@ void LLIMConversation::updateHeaderAndToolbar() mTearOffBtn->setImageOverlay(getString(is_hosted ? "tear_off_icon" : "return_icon")); - mCloseBtn->setVisible(is_hosted); + mCloseBtn->setVisible(is_hosted && !mIsNearbyChat); enableDisableCallBtn(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index a2a54bf02c..33b96b20f3 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -103,14 +103,14 @@ BOOL LLIMFloaterContainer::postBuild() void LLIMFloaterContainer::onOpen(const LLSD& key) { - LLMultiFloater::onOpen(key); if (getFloaterCount() == 0) { - // If there's *no* conversation open so far, we force the opening of the nearby chat conversation + // We always force the opening of the nearby chat conversation when we open for the first time // *TODO: find a way to move this to XML as a default panel or something like that LLSD name("chat_bar"); LLFloaterReg::toggleInstanceOrBringToFront(name); } + LLMultiFloater::onOpen(key); /* if (key.isDefined()) { @@ -284,6 +284,44 @@ void LLIMFloaterContainer::setMinimized(BOOL b) } } +void LLIMFloaterContainer::draw() +{ + if (mTabContainer->getTabCount() == 0) + { + // Do not close the container when every conversation is torn off because the user + // still needs the conversation list. Simply collapse the message pane in that case. + collapseMessagesPane(true); + } + LLFloater::draw(); +} + +void LLIMFloaterContainer::tabClose() +{ + if (mTabContainer->getTabCount() == 0) + { + // Do not close the container when every conversation is torn off because the user + // still needs the conversation list. Simply collapse the message pane in that case. + collapseMessagesPane(true); + } +} + +void LLIMFloaterContainer::setVisible(BOOL visible) +{ + // We need to show/hide all the associated conversations that have been torn off + // (and therefore, are not longer managed by the multifloater), + // so that they show/hide with the conversations manager. + conversations_items_map::iterator item_it = mConversationsItems.begin(); + for (;item_it != mConversationsItems.end(); ++item_it) + { + LLConversationItem* item = item_it->second; + item->setVisibleIfDetached(visible); + } + + // Now, do the normal multifloater show/hide + LLMultiFloater::setVisible(visible); + +} + void LLIMFloaterContainer::collapseMessagesPane(bool collapse) { if (mMessagesPane->isCollapsed() == collapse) @@ -485,6 +523,15 @@ void LLConversationItem::selectItem(void) mFloater->setFocus(TRUE); } +void LLConversationItem::setVisibleIfDetached(BOOL visible) +{ + // Do this only if the conversation floater has been torn off (i.e. no multi floater host) + if (!mFloater->getHost()) + { + mFloater->setVisible(visible); + } +} + void LLConversationItem::performAction(LLInventoryModel* model, std::string action) { } diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 3d1324c2fb..c6e7c6a3d9 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -97,6 +97,8 @@ public: virtual void previewItem( void ); virtual void selectItem(void); virtual void showProperties(void); + + void setVisibleIfDetached(BOOL visible); // This method should be called when a drag begins. // Returns TRUE if the drag can begin, FALSE otherwise. @@ -128,6 +130,8 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void draw(); + /*virtual*/ void setVisible(BOOL visible); void onCloseFloater(LLUUID& id); /*virtual*/ void addFloater(LLFloater* floaterp, @@ -135,6 +139,8 @@ public: LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); /*virtual*/ void removeFloater(LLFloater* floaterp); + /*virtual*/ void tabClose(); + static LLFloater* getCurrentVoiceFloater(); static LLIMFloaterContainer* findInstance(); -- cgit v1.2.3 From 9c11a6b206f2455e37cf3ba8719bf6b51bc994e8 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Tue, 26 Jun 2012 18:58:57 +0300 Subject: CHUI-177 ADDITIONAL FIX (Text entry field in chat only accepts 256 characters) - Limited text entry field to 1024 instead of 1025 characters should take into account zero (0 ... 1023) --- indra/newview/skins/default/xui/en/floater_im_session.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 56e591e2bb..08bc46a506 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -246,7 +246,7 @@ label="To" layout="bottomleft" name="chat_editor" - max_length="1024" + max_length="1023" tab_group="3" width="240" wrap="true"> -- cgit v1.2.3 From 677c205131e695eb5a3b2a190799330b49d636d8 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Tue, 26 Jun 2012 19:08:27 +0300 Subject: CHUI-182 FIXED (Vertical scrollbar flashes on and off when chat entry text area expands) - To avoid unnecessary appearing of scrollbar, first chat entry must be expanded and only then decision should be taken in the base class whether scrollbar should be shown or not. --- indra/llui/llchatentry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index a6ba125406..2a6ccc3dc9 100644 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -57,12 +57,12 @@ LLChatEntry::~LLChatEntry() void LLChatEntry::draw() { - LLTextEditor::draw(); - if(mIsExpandable) { expandText(); } + + LLTextEditor::draw(); } void LLChatEntry::onCommit() -- cgit v1.2.3 From abe106bd9c33fef12dcf4eacca228d5d669d9e34 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Tue, 26 Jun 2012 19:27:19 +0300 Subject: - CHUI-178 (Right click context menu not present in chat entry field) - Set parameter to true to show context menu --- indra/newview/skins/default/xui/en/widgets/chat_editor.xml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 indra/newview/skins/default/xui/en/widgets/chat_editor.xml (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/widgets/chat_editor.xml b/indra/newview/skins/default/xui/en/widgets/chat_editor.xml new file mode 100644 index 0000000000..f9facb593a --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chat_editor.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chat_editor + name="chat_editor" + show_context_menu="true"/> -- cgit v1.2.3 From c233f0c9494d7dddbd8baab0f87b0ad54f42b0f9 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 26 Jun 2012 17:05:16 -0700 Subject: CHUI-164 : Fix crash when closing ad-hoc conversations; insure consistency of the conversation list when adding and removing items from it --- indra/newview/llimfloater.cpp | 9 ++++-- indra/newview/llimfloatercontainer.cpp | 56 +++++++++++++++++++++++++++------- indra/newview/llimfloatercontainer.h | 8 +++-- 3 files changed, 58 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 98ebc82f99..f89bafc7ea 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -540,8 +540,10 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) } } + // Test the existence of the floater before we try to create it bool exist = findInstance(session_id); + // Get the floater: this will create the instance if it didn't exist LLIMFloater* floater = getInstance(session_id); if (!floater) return NULL; @@ -550,18 +552,21 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) { LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); - // do not add existed floaters to avoid adding torn off instances + // Do not add again existing floaters if (!exist) { // LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; // TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END; - if (floater_container) { floater_container->addFloater(floater, TRUE, i_pt); } } + + // Add a conversation list item in the left pane: nothing will be done if already in there + // but relevant clean up will be done to ensure consistency of the conversation list + floater_container->addConversationListItem(floater->getTitle(), session_id, floater); floater->openFloater(floater->getKey()); } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 33b96b20f3..f6bcf8bbe9 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -146,7 +146,7 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, LLUUID session_id = floaterp->getKey(); // Add a conversation list item in the left pane - addConversationListItem(floaterp->getTitle(), session_id, floaterp, this); + addConversationListItem(floaterp->getTitle(), session_id, floaterp); LLView* floater_contents = floaterp->getChild<LLView>("contents_view"); @@ -408,18 +408,33 @@ void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) } // CHUI-137 : Temporary implementation of conversations list -void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp) +void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp) { - // Check if the item is not already in the list, exit if it is (nothing to do) + // Check if the item is not already in the list, exit if it is and has the same name and points to the same floater (nothing to do) // Note: this happens often, when reattaching a torn off conversation for instance conversations_items_map::iterator item_it = mConversationsItems.find(uuid); if (item_it != mConversationsItems.end()) { - return; + LLConversationItem* item = item_it->second; + // Check if the item has changed + if (item->hasSameValues(name,floaterp)) + { + // If it hasn't, nothing to do -> exit + return; + } + // If it has, remove it: it'll be recreated anew further down + removeConversationListItem(uuid,false); + } + + // Reverse find and clean up: we need to make sure that no other uuid is pointing to that same floater + LLUUID found_id = LLUUID::null; + if (findConversationItem(floaterp,found_id)) + { + removeConversationListItem(found_id,false); } // Create a conversation item - LLConversationItem* item = new LLConversationItem(name, uuid, floaterp, containerp); + LLConversationItem* item = new LLConversationItem(name, uuid, floaterp, this); mConversationsItems[uuid] = item; // Create a widget from it @@ -439,7 +454,7 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI return; } -void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id) +void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id, bool change_focus) { // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting @@ -469,16 +484,35 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id) } // Don't let the focus fall IW, select and refocus on the first conversation in the list - setFocus(TRUE); - conversations_items_map::iterator item_it = mConversationsItems.begin(); - if (item_it != mConversationsItems.end()) + if (change_focus) { - LLConversationItem* item = item_it->second; - item->selectItem(); + setFocus(TRUE); + conversations_items_map::iterator item_it = mConversationsItems.begin(); + if (item_it != mConversationsItems.end()) + { + LLConversationItem* item = item_it->second; + item->selectItem(); + } } return; } +bool LLIMFloaterContainer::findConversationItem(LLFloater* floaterp, LLUUID& uuid) +{ + bool found = false; + for (conversations_items_map::iterator item_it = mConversationsItems.begin(); item_it != mConversationsItems.end(); ++item_it) + { + LLConversationItem* item = item_it->second; + uuid = item_it->first; + if (item->hasSameValue(floaterp)) + { + found = true; + break; + } + } + return found; +} + LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) { LLFolderViewItem::Params params; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index c6e7c6a3d9..2a8cbf3e1c 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -112,6 +112,9 @@ public: EDragAndDropType cargo_type, void* cargo_data, std::string& tooltip_msg) { return FALSE; } + + bool hasSameValues(std::string name, LLFloater* floaterp) { return ((name == mName) && (floaterp == mFloater)); } + bool hasSameValue(LLFloater* floaterp) { return (floaterp == mFloater); } private: std::string mName; const LLUUID mUUID; @@ -183,9 +186,10 @@ private: // CHUI-137 : Temporary implementation of conversations list public: - void removeConversationListItem(const LLUUID& session_id); + void removeConversationListItem(const LLUUID& session_id, bool change_focus = true); + void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp); + bool findConversationItem(LLFloater* floaterp, LLUUID& uuid); private: - void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp); LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); // Conversation list data LLPanel* mConversationsListPanel; // This is the widget we add items to (i.e. clickable title for each conversation) -- cgit v1.2.3 From a7831406abfe87e9bd1da8091e008edcd65b402c Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Wed, 27 Jun 2012 18:52:08 +0300 Subject: CHUI-180 FIXED (Started an ad hoc IM spams log with drawtext warning) - Don't draw TextBase context if it's empty and in focus --- indra/llui/lltextbase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index c112a7e477..3b3bc64c5b 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -508,7 +508,7 @@ void LLTextBase::drawText() { return; } - else if (text_len <= 0 && !mLabel.empty()) + else if (text_len <= 0 && !mLabel.empty() && !hasFocus()) { text_len = mLabel.length(); } -- cgit v1.2.3 From 0cfea7b406c87bf593d2f7cf6040d92ef99b64cf Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Tue, 26 Jun 2012 01:38:59 +0300 Subject: CHUI-147 FIX Added updating conference participants in IM floater title - The title is updated with the data from participants list widget in IM floater. - Creating the participants list is fixed for the case of starting the ad hoc session when the session id changes upon initialization (see LLIMConversation::buildParticipantList()). - LLEventTimer replaced with simple LLTimer to avoid crashes in LLEventTimer::tick(). - Moved the build_residents_string() code to LLAvatarActions::buildResidentsString() to use it in LLIMFloater::onParticipantsListChanged(). --- indra/newview/llavataractions.cpp | 35 +++++++------- indra/newview/llavataractions.h | 9 ++++ indra/newview/llimconversation.cpp | 34 +++++++++----- indra/newview/llimconversation.h | 10 ++-- indra/newview/llimfloater.cpp | 93 ++++++++++++++++++++++++++++--------- indra/newview/llimfloater.h | 9 +++- indra/newview/llnearbychat.cpp | 36 ++++++-------- indra/newview/llnearbychat.h | 6 +-- indra/newview/llparticipantlist.cpp | 1 + 9 files changed, 151 insertions(+), 82 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index c9031dd26a..21367c224d 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -529,23 +529,6 @@ namespace action_give_inventory return acceptable; } - static void build_residents_string(const std::vector<LLAvatarName> avatar_names, std::string& residents_string) - { - llassert(avatar_names.size() > 0); - - const std::string& separator = LLTrans::getString("words_separator"); - for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; ) - { - LLAvatarName av_name = *it; - residents_string.append(av_name.mDisplayName); - if (++it == avatar_names.end()) - { - break; - } - residents_string.append(separator); - } - } - static void build_items_string(const std::set<LLUUID>& inventory_selected_uuids , std::string& items_string) { llassert(inventory_selected_uuids.size() > 0); @@ -675,7 +658,7 @@ namespace action_give_inventory } std::string residents; - build_residents_string(avatar_names, residents); + LLAvatarActions::buildResidentsString(avatar_names, residents); std::string items; build_items_string(inventory_selected_uuids, items); @@ -706,7 +689,23 @@ namespace action_give_inventory } } +// static +void LLAvatarActions::buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string) +{ + llassert(avatar_names.size() > 0); + const std::string& separator = LLTrans::getString("words_separator"); + for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; ) + { + LLAvatarName av_name = *it; + residents_string.append(av_name.mDisplayName); + if (++it == avatar_names.end()) + { + break; + } + residents_string.append(separator); + } +} //static std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs() diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 0a69ad86a3..46830eb22c 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -34,6 +34,7 @@ #include <string> #include <vector> +class LLAvatarName; class LLInventoryPanel; class LLFloater; @@ -208,6 +209,14 @@ public: */ static bool canShareSelectedItems(LLInventoryPanel* inv_panel = NULL); + /** + * Builds a string of residents' display names separated by "words_separator" string. + * + * @param avatar_names - a vector of given avatar names from which resulting string is built + * @param residents_string - the resulting string + */ + static void buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string); + static std::set<LLUUID> getInventorySelectedUUIDs(); private: diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index d3f3e41a29..c734c3edd2 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -42,7 +42,6 @@ const F32 REFRESH_INTERVAL = 0.2f; LLIMConversation::LLIMConversation(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id) - , LLEventTimer(REFRESH_INTERVAL) , mIsP2PChat(false) , mExpandCollapseBtn(NULL) , mTearOffBtn(NULL) @@ -52,6 +51,7 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id) , mChatHistory(NULL) , mInputEditor(NULL) , mInputEditorTopPad(0) + , mRefreshTimer(new LLTimer()) { mCommitCallbackRegistrar.add("IMSession.Menu.Action", boost::bind(&LLIMConversation::onIMSessionMenuItemClicked, this, _2)); @@ -67,6 +67,10 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id) boost::bind(&LLIMConversation::onIMShowModesMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", boost::bind(&LLIMConversation::onIMShowModesMenuItemEnable, this, _2)); + + // Zero expiry time is set only once to allow initial update. + mRefreshTimer->setTimerExpirySec(0); + mRefreshTimer->start(); } LLIMConversation::~LLIMConversation() @@ -76,6 +80,8 @@ LLIMConversation::~LLIMConversation() delete mParticipantList; mParticipantList = NULL; } + + delete mRefreshTimer; } BOOL LLIMConversation::postBuild() @@ -120,19 +126,22 @@ BOOL LLIMConversation::postBuild() } -BOOL LLIMConversation::tick() +void LLIMConversation::draw() { - // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater - // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy(). - if (isDead()) return false; + LLTransientDockableFloater::draw(); - // Need to resort the participant list if it's in sort by recent speaker order. - if (mParticipantList) + if (mRefreshTimer->hasExpired()) { - mParticipantList->update(); - } + if (mParticipantList) + { + mParticipantList->update(); + } - return false; + refresh(); + + // Restart the refresh timer + mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); + } } void LLIMConversation::buildParticipantList() @@ -144,10 +153,11 @@ void LLIMConversation::buildParticipantList() } else { + LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID); // for group and ad-hoc chat we need to include agent into list - if(!mIsP2PChat && !mParticipantList && mSessionID.notNull()) + if(!mIsP2PChat && mSessionID.notNull() && speaker_manager) { - LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + delete mParticipantList; // remove the old list and create a new one if the session id has changed mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false); } } diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 47c98d6f8b..50663137ac 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -40,7 +40,6 @@ class LLChatHistory; class LLIMConversation : public LLTransientDockableFloater - , public LLEventTimer { public: @@ -65,6 +64,7 @@ public: /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); protected: @@ -89,8 +89,6 @@ protected: void buildParticipantList(); void onSortMenuItemClicked(const LLSD& userdata); - /*virtual*/ BOOL tick(); - bool mIsNearbyChat; bool mIsP2PChat; @@ -103,6 +101,9 @@ protected: LLButton* mCloseBtn; private: + /// Refreshes the floater at a constant rate. + virtual void refresh() = 0; + /// Update floater header and toolbar buttons when hosted/torn off state is toggled. void updateHeaderAndToolbar(); @@ -113,10 +114,11 @@ private: */ void reshapeChatHistory(); - LLChatHistory* mChatHistory; LLChatEntry* mInputEditor; int mInputEditorTopPad; // padding between input field and chat history + + LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. }; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 9ea4bec069..6a5bf153d4 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -105,6 +105,18 @@ void LLIMFloater::onFocusReceived() } } +// virtual +void LLIMFloater::refresh() +{ + if (mMeTyping) + { + // Time out if user hasn't typed for a while. + if (mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS) + { + setTyping(false); + } + } +} /* static */ void LLIMFloater::newIMCallback(const LLSD& data) @@ -188,6 +200,7 @@ void LLIMFloater::sendMsg() LLIMFloater::~LLIMFloater() { + mParticipantsListRefreshConnection.disconnect(); mVoiceChannelStateChangeConnection.disconnect(); if(LLVoiceClient::instanceExists()) { @@ -225,6 +238,8 @@ void LLIMFloater::initIMFloater() boundVoiceChannel(); + mTypingStart = LLTrans::getString("IM_typing_start_string"); + // Show control panel in torn off floaters only. mParticipantListPanel->setVisible(!getHost() && gSavedSettings.getBOOL("IMShowControlPanel")); @@ -246,6 +261,20 @@ void LLIMFloater::initIMFloater() { std::string session_name(LLIMModel::instance().getName(mSessionID)); updateSessionName(session_name, session_name); + + // For ad hoc conferences we should update the title with participants names. + if ((IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) + || mDialog == IM_SESSION_CONFERENCE_START) + { + if (mParticipantsListRefreshConnection.connected()) + { + mParticipantsListRefreshConnection.disconnect(); + } + + LLAvatarList* avatar_list = getChild<LLAvatarList>("speakers_list"); + mParticipantsListRefreshConnection = avatar_list->setRefreshCompleteCallback( + boost::bind(&LLIMFloater::onParticipantsListChanged, this, _1)); + } } } @@ -273,8 +302,6 @@ BOOL LLIMFloater::postBuild() setDocked(true); - mTypingStart = LLTrans::getString("IM_typing_start_string"); - LLButton* add_btn = getChild<LLButton>("add_btn"); // Allow to add chat participants depending on the session type @@ -341,7 +368,9 @@ bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) for (uuid_vec_t::const_iterator id = uuids.begin(); id != uuids.end(); ++id) { - if (*id == mOtherParticipantUUID) + // Skip this check for ad hoc conferences, + // conference participants should be listed in mSession->mInitialTargetIDs. + if (mIsP2PChat && *id == mOtherParticipantUUID) { return false; } @@ -411,11 +440,6 @@ void LLIMFloater::onCallButtonClicked() } } -/*void LLIMFloater::onOpenVoiceControlsClicked() -{ - LLFloaterReg::showInstance("voice_controls"); -}*/ - void LLIMFloater::onChange(EStatusType status, const std::string &channelURI, bool proximal) { if(status != STATUS_JOINING && status != STATUS_LEFT_CHANNEL) @@ -448,28 +472,55 @@ void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id, mTypingStart.setArg("[NAME]", ui_title); } -// virtual -BOOL LLIMFloater::tick() +void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) { - // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater - // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy(). - if (isDead()) + LLAvatarList* avatar_list = dynamic_cast<LLAvatarList*>(ctrl); + if (!avatar_list) { - return false; + return; } - BOOL parents_retcode = LLIMConversation::tick(); + bool all_names_resolved = true; + std::vector<LLSD> participants_uuids; - if ( mMeTyping ) + avatar_list->getValues(participants_uuids); + + // Check whether we have all participants names in LLAvatarNameCache + for (std::vector<LLSD>::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it) { - // Time out if user hasn't typed for a while. - if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS ) + const LLUUID& id = it->asUUID(); + LLAvatarName av_name; + if (!LLAvatarNameCache::get(id, &av_name)) { - setTyping(false); + all_names_resolved = false; + + // If a name is not found in cache, request it and continue the process recursively + // until all ids are resolved into names. + LLAvatarNameCache::get(id, + boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list)); + break; } } - return parents_retcode; + if (all_names_resolved) + { + std::vector<LLAvatarName> avatar_names; + std::vector<LLSD>::const_iterator it = participants_uuids.begin(); + for (; it != participants_uuids.end(); ++it) + { + const LLUUID& id = it->asUUID(); + LLAvatarName av_name; + if (LLAvatarNameCache::get(id, &av_name)) + { + avatar_names.push_back(av_name); + } + } + + std::string ui_title; + LLAvatarActions::buildResidentsString(avatar_names, ui_title); + + updateSessionName(ui_title, ui_title); + } } //static @@ -737,8 +788,6 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) { initIMSession(im_session_id); - boundVoiceChannel(); - buildParticipantList(); } diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 6847efedf1..23f9e75e21 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -66,7 +66,6 @@ public: /*virtual*/ void setVisible(BOOL visible); /*virtual*/ BOOL getVisible(); // Check typing timeout timer. - /*virtual*/ BOOL tick(); static LLIMFloater* findInstance(const LLUUID& session_id); static LLIMFloater* getInstance(const LLUUID& session_id); @@ -131,12 +130,18 @@ private: /* virtual */ void onFocusLost(); /* virtual */ void onFocusReceived(); + /*virtual*/ void refresh(); + // Update the window title, input field help text, etc. void updateSessionName(const std::string& ui_title, const std::string& ui_label); // For display name lookups for IM window titles void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + /// Updates the list of ad hoc conference participants + /// in an IM floater title. + void onParticipantsListChanged(LLUICtrl* ctrl); + bool dropPerson(LLUUID* person_id, bool drop); BOOL isInviteAllowed() const; @@ -193,6 +198,8 @@ private: // connection to voice channel state change signal boost::signals2::connection mVoiceChannelStateChangeConnection; + + boost::signals2::connection mParticipantsListRefreshConnection; }; #endif // LL_IMFLOATER_H diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 29ab4384cb..369ca699c5 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -186,6 +186,21 @@ BOOL LLNearbyChat::postBuild() return LLIMConversation::postBuild(); } +// virtual +void LLNearbyChat::refresh() +{ + displaySpeakingIndicator(); + updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); + + // *HACK: Update transparency type depending on whether our children have focus. + // This is needed because this floater is chrome and thus cannot accept focus, so + // the transparency type setting code from LLFloater::setFocus() isn't reached. + if (getTransparencyType() != TT_DEFAULT) + { + setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE); + } +} + void LLNearbyChat::onNearbySpeakers() { LLSD param; @@ -389,27 +404,6 @@ void LLNearbyChat::showHistory() storeRectControl(); } - -BOOL LLNearbyChat::tick() -{ - // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater - // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy(). - if (isDead()) return false; - - displaySpeakingIndicator(); - updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); - - // *HACK: Update transparency type depending on whether our children have focus. - // This is needed because this floater is chrome and thus cannot accept focus, so - // the transparency type setting code from LLFloater::setFocus() isn't reached. - if (getTransparencyType() != TT_DEFAULT) - { - setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE); - } - - return LLIMConversation::tick(); -} - std::string LLNearbyChat::getCurrentChat() { return mChatBox ? mChatBox->getText() : LLStringUtil::null; diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index c9aa69a912..db367f0b59 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -73,8 +73,6 @@ public: LLChatEntry* getChatBox() { return mChatBox; } - //virtual void draw(); - std::string getCurrentChat(); virtual BOOL handleKeyHere( KEY key, MASK mask ); @@ -119,8 +117,6 @@ protected: S32 mExpandedHeight; - /*virtual*/ BOOL tick(); - private: void getAllowedRect (LLRect& rect); @@ -128,6 +124,8 @@ private: void appendMessage(const LLChat& chat, const LLSD &args = 0); void onNearbySpeakers (); + /*virtual*/ void refresh(); + LLHandle<LLView> mPopupMenuHandle; std::vector<LLChat> mMessageArchive; LLChatHistory* mChatHistory; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 59d26edff2..47518a365f 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -475,6 +475,7 @@ void LLParticipantList::update() { mSpeakerMgr->update(true); + // Need to resort the participant list if it's in sort by recent speaker order. if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder() && !isHovered()) { // Resort avatar list -- cgit v1.2.3 From 3385a6398951bc94b3dc5da6224e285d85e606ab Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 27 Jun 2012 16:11:04 +0300 Subject: CHUI-162 FIXED Opening a nearby chat when text entered --- indra/newview/llnearbychat.cpp | 22 ++++++++++++++++++++++ indra/newview/llnearbychat.h | 1 + 2 files changed, 23 insertions(+) (limited to 'indra') diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 369ca699c5..ee7169b1c3 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -131,6 +131,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& key) mSpeakerMgr(NULL), mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) { + setIsChrome(TRUE); mKey = LLSD(); mIsNearbyChat = true; mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); @@ -394,6 +395,26 @@ LLNearbyChat* LLNearbyChat::getInstance() return LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar"); } +void LLNearbyChat::show() +{ + // Get the floater + LLNearbyChat* floater = LLNearbyChat::getInstance(); + if (floater) + { + if(isChatMultiTab()) + { + LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); + + // Add a conversation list item in the left pane: nothing will be done if already in there + // but relevant clean up will be done to ensure consistency of the conversation list + floater_container->addConversationListItem(floater->getTitle(), LLUUID(), floater); + + floater->openFloater(floater->getKey()); + } + + floater->setVisible(TRUE); + } +} void LLNearbyChat::showHistory() { @@ -773,6 +794,7 @@ void LLNearbyChat::startChat(const char* line) if (cb ) { + cb->show(); cb->setVisible(TRUE); cb->setFocus(TRUE); cb->mChatBox->setFocus(TRUE); diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index db367f0b59..61404df942 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -65,6 +65,7 @@ public: static LLNearbyChat* getInstance(); void addToHost(); + void show(); /** @param archive true - to save a message to the chat history log */ void addMessage (const LLChat& message,bool archive = true, const LLSD &args = LLSD()); -- cgit v1.2.3 From 9091986c698af6d008a12f1944724609d649b63e Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Wed, 27 Jun 2012 19:33:22 +0300 Subject: CHUI-147 FIX Added check against empty participants names array to pass the assertion in LLAvatarActions::buildResidentsString. --- indra/newview/llimfloater.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 6a5bf153d4..1bbf6cc320 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -516,10 +516,14 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) } } - std::string ui_title; - LLAvatarActions::buildResidentsString(avatar_names, ui_title); - - updateSessionName(ui_title, ui_title); + // We should check whether the vector is not empty to pass the assertion + // that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. + if (!avatar_names.empty()) + { + std::string ui_title; + LLAvatarActions::buildResidentsString(avatar_names, ui_title); + updateSessionName(ui_title, ui_title); + } } } -- cgit v1.2.3 From 0eda1f9a4d909870b15c6d7243e47838540598e8 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Wed, 27 Jun 2012 19:33:27 +0300 Subject: CHUI-169 FIX Restored inventory sharing functionality via IM floater drag and drop. --- indra/newview/llimfloater.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 1bbf6cc320..b94a4048d4 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -1077,6 +1077,12 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, *accept = ACCEPT_NO; } } + else if (mDialog == IM_NOTHING_SPECIAL) + { + LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, + cargo_type, cargo_data, accept); + } + return TRUE; } -- cgit v1.2.3 From 0e316a1510d5051088a62b86e4b0e05702786d9a Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 27 Jun 2012 21:30:05 +0300 Subject: CHUI-125 FIXED Supressed of a commented out code --- indra/newview/llchicletbar.cpp | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index 0e58008cd2..39f5d0b8f6 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -57,24 +57,11 @@ LLChicletBar::LLChicletBar(const LLSD&) : mChicletPanel(NULL), mToolbarStack(NULL) { - // IM floaters are from now managed by LLIMFloaterContainer. - // See LLIMFloaterContainer::sessionVoiceOrIMStarted() and CHUI-125 - -// // Firstly add our self to IMSession observers, so we catch session events -// // before chiclets do that. -// LLIMMgr::getInstance()->addSessionObserver(this); - buildFromFile("panel_chiclet_bar.xml"); } LLChicletBar::~LLChicletBar() { - // IM floaters are from now managed by LLIMFloaterContainer. - // See LLIMFloaterContainer::sessionVoiceOrIMStarted() and CHUI-125 -// if (!LLSingleton<LLIMMgr>::destroyed()) -// { -// LLIMMgr::getInstance()->removeSessionObserver(this); -// } } LLIMChiclet* LLChicletBar::createIMChiclet(const LLUUID& session_id) -- cgit v1.2.3 From 1eb6b4509d9ae79f8313e1e68351028794093a53 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 27 Jun 2012 14:03:16 -0700 Subject: CHUI-139 : Make sure the Nearby Chat shows up in the conversations floater in every situation --- indra/newview/llimfloatercontainer.cpp | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index f6bcf8bbe9..52bacf15e4 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -103,24 +103,7 @@ BOOL LLIMFloaterContainer::postBuild() void LLIMFloaterContainer::onOpen(const LLSD& key) { - if (getFloaterCount() == 0) - { - // We always force the opening of the nearby chat conversation when we open for the first time - // *TODO: find a way to move this to XML as a default panel or something like that - LLSD name("chat_bar"); - LLFloaterReg::toggleInstanceOrBringToFront(name); - } LLMultiFloater::onOpen(key); - /* - if (key.isDefined()) - { - LLIMFloater* im_floater = LLIMFloater::findInstance(key.asUUID()); - if (im_floater) - { - im_floater->openFloater(); - } - } - */ } // virtual @@ -307,6 +290,20 @@ void LLIMFloaterContainer::tabClose() void LLIMFloaterContainer::setVisible(BOOL visible) { + if (visible) + { + // Make sure we have the Nearby Chat present when showing the conversation container + LLUUID nearbychat_uuid = LLUUID::null; // Hacky but true: the session id for nearby chat is null + conversations_items_map::iterator item_it = mConversationsItems.find(nearbychat_uuid); + if (item_it == mConversationsItems.end()) + { + // If not found, force the creation of the nearby chat conversation panel + // *TODO: find a way to move this to XML as a default panel or something like that + LLSD name("chat_bar"); + LLFloaterReg::toggleInstanceOrBringToFront(name); + } + } + // We need to show/hide all the associated conversations that have been torn off // (and therefore, are not longer managed by the multifloater), // so that they show/hide with the conversations manager. -- cgit v1.2.3 From d470632799dfdea723d15d91aa5783bdd1700257 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 27 Jun 2012 15:32:08 -0700 Subject: CHUI-130 : Leave minimized torn off IM untouched when showing hiding the whole set of conversations --- indra/newview/llimfloatercontainer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 52bacf15e4..34a9758c52 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -556,8 +556,9 @@ void LLConversationItem::selectItem(void) void LLConversationItem::setVisibleIfDetached(BOOL visible) { - // Do this only if the conversation floater has been torn off (i.e. no multi floater host) - if (!mFloater->getHost()) + // Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized + // Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here + if (!mFloater->getHost() && !mFloater->isMinimized()) { mFloater->setVisible(visible); } -- cgit v1.2.3 From c9da4d0a6dccbdcff228a5841d224463bc45297c Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 27 Jun 2012 15:55:09 -0700 Subject: CHUI-162 : Simplified the nearby chat show method following CHUI-139 fixes --- indra/newview/llnearbychat.cpp | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index ee7169b1c3..a81d6b4025 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -397,23 +397,11 @@ LLNearbyChat* LLNearbyChat::getInstance() void LLNearbyChat::show() { - // Get the floater - LLNearbyChat* floater = LLNearbyChat::getInstance(); - if (floater) + if (isChatMultiTab()) { - if(isChatMultiTab()) - { - LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); - - // Add a conversation list item in the left pane: nothing will be done if already in there - // but relevant clean up will be done to ensure consistency of the conversation list - floater_container->addConversationListItem(floater->getTitle(), LLUUID(), floater); - - floater->openFloater(floater->getKey()); - } - - floater->setVisible(TRUE); + openFloater(getKey()); } + setVisible(TRUE); } void LLNearbyChat::showHistory() -- cgit v1.2.3 From 7a147c1de99a7d03008d2921f091aa3de03a559f Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 27 Jun 2012 17:08:19 -0700 Subject: CHUI-146 : Fixed. Focus goes to first conversation in list when a conversation is dismissed. --- indra/newview/llimfloater.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index b94a4048d4..9d3c0f98ce 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -628,9 +628,6 @@ LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) void LLIMFloater::onClose(bool app_quitting) { - LLIMConversation::onClose(app_quitting); - - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( mSessionID); @@ -663,6 +660,8 @@ void LLIMFloater::onClose(bool app_quitting) // EXT-3516 X Button should end IM session, _ button should hide gIMMgr->leaveSession(mSessionID); + // Clean up the conversation *after* the session has been ended + LLIMConversation::onClose(app_quitting); } void LLIMFloater::setDocked(bool docked, bool pop_on_undock) -- cgit v1.2.3 From cbe3c3ae95c0850cd0ecba893ddabe0200bbc0ac Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 27 Jun 2012 17:16:15 -0700 Subject: CHUI-184 : Change default pref LetterKeysFocusChatBar from 1 (chat) to 0 (WASD movements) --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index fe6829a712..4a586b02af 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1538,7 +1538,7 @@ <key>Type</key> <string>S32</string> <key>Value</key> - <integer>1</integer> + <integer>0</integer> </map> <key>ChatBubbleOpacity</key> <map> -- cgit v1.2.3 From cb865a7e1300d4ce0bedae7c856fb210b68a43f8 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 27 Jun 2012 18:56:10 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose moved filtering logic to viewmodel --- indra/llui/llnotifications.cpp | 24 +- indra/newview/llfolderview.cpp | 106 ++--- indra/newview/llfolderview.h | 12 +- indra/newview/llfolderviewitem.cpp | 787 +++++++------------------------ indra/newview/llfolderviewitem.h | 82 +--- indra/newview/llfolderviewmodel.h | 194 ++++---- indra/newview/llinventorybridge.cpp | 20 +- indra/newview/llinventorybridge.h | 3 + indra/newview/llinventoryfilter.cpp | 97 ++-- indra/newview/llinventoryfilter.h | 20 +- indra/newview/llinventoryfunctions.cpp | 10 +- indra/newview/llinventorypanel.cpp | 128 ++++- indra/newview/llinventorypanel.h | 6 + indra/newview/llpanellandmarks.cpp | 2 +- indra/newview/llpanelmaininventory.cpp | 2 +- indra/newview/llpanelobjectinventory.cpp | 11 + indra/newview/llsidepanelappearance.cpp | 2 +- indra/newview/lltexturectrl.cpp | 10 +- 18 files changed, 557 insertions(+), 959 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 487a2e5fe7..48128e0b40 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1542,34 +1542,32 @@ void LLNotifications::addFromCallback(const LLSD& name) add(name.asString(), LLSD(), LLSD()); } -LLNotificationPtr LLNotifications::add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload) +LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload) { LLNotification::Params::Functor functor_p; functor_p.name = name; return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); } -LLNotificationPtr LLNotifications::add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload, - const std::string& functor_name) +LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, const std::string& functor_name) { LLNotification::Params::Functor functor_p; functor_p.name = functor_name; - return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); + return add(LLNotification::Params().name(name) + .substitutions(substitutions) + .payload(payload) + .functor(functor_p)); } //virtual -LLNotificationPtr LLNotifications::add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload, - LLNotificationFunctorRegistry::ResponseFunctor functor) +LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, LLNotificationFunctorRegistry::ResponseFunctor functor) { LLNotification::Params::Functor functor_p; functor_p.function = functor; - return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); + return add(LLNotification::Params().name(name) + .substitutions(substitutions) + .payload(payload) + .functor(functor_p)); } // generalized add function that takes a parameter block object for more complex instantiations diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index ee8c94a2dd..a37fc7714b 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -181,7 +181,6 @@ LLFolderView::LLFolderView(const Params& p) mNeedsAutoSelect( FALSE ), mAutoSelectOverride(FALSE), mNeedsAutoRename(FALSE), - mDebugFilters(FALSE), mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME), // This gets overridden by a pref immediately mFilter(new LLInventoryFilter(LLInventoryFilter::Params().name(p.title))), mShowSelectionContext(FALSE), @@ -316,7 +315,7 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) folder->reshape(getRect().getWidth(), 0); folder->setVisible(FALSE); addChild( folder ); - folder->dirtyFilter(); + folder->getViewModelItem()->dirtyFilter(); folder->requestArrange(); return TRUE; } @@ -339,15 +338,14 @@ void LLFolderView::openTopLevelFolders() } // This view grows and shrinks to enclose all of its children items and folders. -// mItemHeight = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; // *width should be 0 // conform show folder state works -S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation ) +S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) { mMinWidth = 0; S32 target_height; - LLFolderViewFolder::arrange(&mMinWidth, &target_height, mFilter->getFirstSuccessGeneration()); + LLFolderViewFolder::arrange(&mMinWidth, &target_height); LLRect scroll_rect = mScrollContainer->getContentWindowRect(); reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); @@ -371,15 +369,10 @@ void LLFolderView::filter( LLFolderViewFilter& filter ) LLFastTimer t2(FTM_FILTER); filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); - if (getCompletedFilterGeneration() < filter.getCurrentGeneration()) + if (getLastFilterGeneration() < filter.getCurrentGeneration()) { - mPassedFilter = FALSE; mMinWidth = 0; - LLFolderViewFolder::filter(filter); - } - else - { - mPassedFilter = TRUE; + getViewModelItem()->filter(filter); } } @@ -548,15 +541,15 @@ void LLFolderView::sanitizeSelection() LLFolderViewItem* item = *item_iter; // ensure that each ancestor is open and potentially passes filtering - BOOL visible = item->potentiallyVisible(); // initialize from filter state for this item + BOOL visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item // modify with parent open and filters states LLFolderViewFolder* parent_folder = item->getParentFolder(); // Move up through parent folders and see what's visible - while(parent_folder) - { - visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); - parent_folder = parent_folder->getParentFolder(); - } + while(parent_folder) + { + visible = visible && parent_folder->isOpen() && parent_folder->getViewModelItem()->potentiallyVisible(); + parent_folder = parent_folder->getParentFolder(); + } // deselect item if any ancestor is closed or didn't pass filter requirements. if (!visible) @@ -606,7 +599,7 @@ void LLFolderView::sanitizeSelection() parent_folder; parent_folder = parent_folder->getParentFolder()) { - if (parent_folder->potentiallyVisible()) + if (parent_folder->getViewModelItem()->potentiallyVisible()) { // give initial selection to first ancestor folder that potentially passes the filter if (!new_selection) @@ -684,16 +677,6 @@ void LLFolderView::commitRename( const LLSD& data ) void LLFolderView::draw() { - static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", LLColor4::white); - if (mDebugFilters) - { - std::string current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d", - mFilter->getCurrentGeneration(), mFilter->getFirstSuccessGeneration(), mFilter->getFirstRequiredGeneration()); - LLFontGL::getFontMonospace()->renderUTF8(current_filter_string, 0, 2, - getRect().getHeight() - LLFontGL::getFontMonospace()->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f), - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); - } - //LLFontGL* font = getLabelFontForStyle(mLabelStyle); // if cursor has moved off of me during drag and drop @@ -734,17 +717,14 @@ void LLFolderView::draw() } else if (mShowEmptyMessage) { - if (!mViewModel->contentsReady() || mCompletedFilterGeneration < mFilter->getFirstSuccessGeneration()) + if (!mViewModel->contentsReady() || getLastFilterGeneration() < mFilter->getFirstSuccessGeneration()) { // TODO RN: Get this from filter mStatusText = LLTrans::getString("Searching"); } else { - if (getFilter()) - { - mStatusText = getFilter()->getEmptyLookupMessage(); - } + mStatusText = getFolderViewModel()->getFilter()->getEmptyLookupMessage(); } mStatusTextBox->setValue(mStatusText); mStatusTextBox->setVisible( TRUE ); @@ -763,7 +743,11 @@ void LLFolderView::draw() // This will indirectly call ::arrange and reshape of the status textbox. // We should call this method to also notify parent about required rect. // See EXT-7564, EXT-7047. - arrangeFromRoot(); + S32 height = 0; + S32 width = 0; + S32 total_height = arrange( &width, &height ); + notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); + LLUI::popMatrix(); LLUI::pushMatrix(); LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); @@ -902,16 +886,16 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL } if(parent) { - if (parent->removeItem(item_to_delete)) + if (item_to_delete->remove()) { // change selection on successful delete if (new_selection) { - setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); + getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); } else { - setSelectionFromRoot(NULL, mParentPanel->hasFocus()); + getRoot()->setSelection(NULL, mParentPanel->hasFocus()); } } } @@ -937,11 +921,11 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL } if (new_selection) { - setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); + getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); } else { - setSelectionFromRoot(NULL, mParentPanel->hasFocus()); + getRoot()->setSelection(NULL, mParentPanel->hasFocus()); } for(S32 i = 0; i < count; ++i) @@ -1386,12 +1370,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if (next->isSelected()) { // shrink selection - changeSelectionFromRoot(last_selected, FALSE); + getRoot()->changeSelection(last_selected, FALSE); } else if (last_selected->getParentFolder() == next->getParentFolder()) { // grow selection - changeSelectionFromRoot(next, TRUE); + getRoot()->changeSelection(next, TRUE); } } } @@ -1450,12 +1434,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if (prev->isSelected()) { // shrink selection - changeSelectionFromRoot(last_selected, FALSE); + getRoot()->changeSelection(last_selected, FALSE); } else if (last_selected->getParentFolder() == prev->getParentFolder()) { // grow selection - changeSelectionFromRoot(prev, TRUE); + getRoot()->changeSelection(prev, TRUE); } } } @@ -1649,7 +1633,7 @@ BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &searc } } - const std::string current_item_label(search_item->getSearchableLabel()); + const std::string current_item_label(search_item->getViewModelItem()->getSearchableName()); S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); if (!current_item_label.compare(0, search_string_length, upper_case_string)) { @@ -1959,13 +1943,6 @@ void LLFolderView::doIdle() LLFastTimer t2(FTM_INVENTORY); - BOOL debug_filters = gSavedSettings.getBOOL("DebugInventoryFilters"); - if (debug_filters != getDebugFilters()) - { - mDebugFilters = debug_filters; - arrangeAll(); - } - if (mFilter->isModified() && mFilter->isNotDefault()) { mNeedsAutoSelect = TRUE; @@ -1973,7 +1950,7 @@ void LLFolderView::doIdle() mFilter->clearModified(); // filter to determine visibility before arranging - filterFromRoot(); + filter(*(getFolderViewModel()->getFilter())); // automatically show matching items, and select first one if we had a selection if (mNeedsAutoSelect) @@ -1981,7 +1958,7 @@ void LLFolderView::doIdle() LLFastTimer t3(FTM_AUTO_SELECT); // select new item only if a filtered item not currently selected LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); - if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->potentiallyHidden())) + if (!mAutoSelectOverride && (!selected_itemp || selected_itemp->passedFilter())) { // these are named variables to get around gcc not binding non-const references to rvalues // and functor application is inherently non-const to allow for stateful functors @@ -1991,7 +1968,7 @@ void LLFolderView::doIdle() // Open filtered folders for folder views with mAutoSelectOverride=TRUE. // Used by LLPlacesFolderView. - if (mAutoSelectOverride && mFilter->showAllResults()) + if (mFilter->showAllResults()) { // these are named variables to get around gcc not binding non-const references to rvalues // and functor application is inherently non-const to allow for stateful functors @@ -2002,7 +1979,7 @@ void LLFolderView::doIdle() scrollToShowSelection(); } - BOOL filter_finished = mCompletedFilterGeneration >= mFilter->getCurrentGeneration() + BOOL filter_finished = getLastFilterGeneration() >= mFilter->getCurrentGeneration() && mViewModel->contentsReady(); if (filter_finished || gFocusMgr.childHasKeyboardFocus(inventory_panel) @@ -2073,7 +2050,10 @@ void LLFolderView::doIdle() sanitizeSelection(); if( needsArrange() ) { - arrangeFromRoot(); + S32 height = 0; + S32 width = 0; + S32 total_height = arrange( &width, &height ); + notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); } } @@ -2278,25 +2258,19 @@ void LLFolderView::onRenamerLost() if( mRenameItem ) { - setSelectionFromRoot( mRenameItem, TRUE ); + setSelection( mRenameItem, TRUE ); mRenameItem = NULL; } } -LLFolderViewFilter* LLFolderView::getFilter() -{ - return mFilter; -} - S32 LLFolderView::getItemHeight() { - S32 debug_height = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; if(!hasVisibleChildren()) { //We need to display status textbox, let's reserve some place for it - return llmax(debug_height, mStatusTextBox->getTextPixelHeight()); + return llmax(0, mStatusTextBox->getTextPixelHeight()); } - return debug_height; + return 0; } //TODO RN: move to llfolderviewmodel.cpp file diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 8b58da9f45..d261a5967d 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -110,9 +110,11 @@ public: virtual BOOL canFocusChildren() const; + virtual const LLFolderView* getRoot() const { return this; } virtual LLFolderView* getRoot() { return this; } LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } + const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; } void setFilterPermMask(PermissionMask filter_perm_mask); @@ -120,9 +122,6 @@ public: void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } - // filter is never null - LLFolderViewFilter* getFilter(); - bool getAllowMultiSelect() { return mAllowMultiSelect; } // Close all folders in the view @@ -133,7 +132,7 @@ public: // Find width and height of this object and its children. Also // makes sure that this view and its children are the right size. - virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); + virtual S32 arrange( S32* width, S32* height ); virtual S32 getItemHeight(); void arrangeAll() { mArrangeGeneration++; } @@ -147,7 +146,7 @@ public: // Record the selected item and pass it down the hierarchy. virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus); + BOOL take_keyboard_focus = TRUE); // This method is used to toggle the selection of an item. Walks // children, and keeps track of selected objects. @@ -244,8 +243,6 @@ public: void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } - BOOL getDebugFilters() { return mDebugFilters; } - LLPanel* getParentPanel() { return mParentPanel; } // DEBUG only void dumpSelectionInformation(); @@ -299,7 +296,6 @@ protected: bool mUseLabelSuffix; bool mShowItemLinkOverlays; - BOOL mDebugFilters; U32 mSortOrder; LLDepthStack<LLFolderViewFolder> mAutoOpenItems; LLFolderViewFolder* mAutoOpenCandidate; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 3f0b493986..f65a13be1e 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -114,8 +114,6 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mHasVisibleChildren(FALSE), mIndentation(0), mItemHeight(p.item_height), - mPassedFilter(FALSE), - mLastFilterGeneration(-1), //TODO RN: create interface for string highlighting //mStringMatchOffset(std::string::npos), mControlLabelRotation(0.f), @@ -146,6 +144,10 @@ LLFolderView* LLFolderViewItem::getRoot() return mRoot; } +const LLFolderView* LLFolderViewItem::getRoot() const +{ + return mRoot; +} // Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) { @@ -207,99 +209,47 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) return itemp; } -// is this item something we think we should be showing? -// for example, if we haven't gotten around to filtering it yet, then the answer is yes -// until we find out otherwise -BOOL LLFolderViewItem::potentiallyVisible() -{ - return getFiltered() // we've passed the filter - || getLastFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration(); // or we don't know yet -} - -BOOL LLFolderViewItem::potentiallyHidden() +BOOL LLFolderViewItem::passedFilter(S32 filter_generation) { - return !mPassedFilter // didn't pass the filter - || getLastFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration(); // or we don't know yet -} - -BOOL LLFolderViewItem::getFiltered() -{ - return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getFirstSuccessGeneration(); -} - -BOOL LLFolderViewItem::getFiltered(S32 filter_generation) -{ - return mPassedFilter && mLastFilterGeneration >= filter_generation; -} - -void LLFolderViewItem::setFiltered(BOOL filtered, S32 filter_generation) -{ - mPassedFilter = filtered; - mLastFilterGeneration = filter_generation; + return getViewModelItem()->passedFilter(filter_generation); } void LLFolderViewItem::refresh() { - if(!getViewModelItem()) return; + LLFolderViewModelItem& vmi = *getViewModelItem(); - mLabel = getViewModelItem()->getDisplayName(); + mLabel = vmi.getDisplayName(); setToolTip(mLabel); - mIcon = getViewModelItem()->getIcon(); - mIconOpen = getViewModelItem()->getIconOpen(); - mIconOverlay = getViewModelItem()->getIconOverlay(); + mIcon = vmi.getIcon(); + mIconOpen = vmi.getIconOpen(); + mIconOverlay = vmi.getIconOverlay(); if (mRoot->useLabelSuffix()) { - mLabelStyle = getViewModelItem()->getLabelStyle(); - mLabelSuffix = getViewModelItem()->getLabelSuffix(); + mLabelStyle = vmi.getLabelStyle(); + mLabelSuffix = vmi.getLabelSuffix(); } - std::string searchable_label(mLabel); - searchable_label.append(mLabelSuffix); - LLStringUtil::toUpper(searchable_label); + //TODO RN: make sure this logic still fires + //std::string searchable_label(mLabel); + //searchable_label.append(mLabelSuffix); + //LLStringUtil::toUpper(searchable_label); - if (mSearchableLabel.compare(searchable_label)) - { - mSearchableLabel.assign(searchable_label); - dirtyFilter(); - // some part of label has changed, so overall width has potentially changed, and sort order too - if (mParentFolder) - { - mParentFolder->requestSort(); - mParentFolder->requestArrange(); - } - } + //if (mSearchableLabel.compare(searchable_label)) + //{ + // mSearchableLabel.assign(searchable_label); + // vmi.dirtyFilter(); + // // some part of label has changed, so overall width has potentially changed, and sort order too + // if (mParentFolder) + // { + // mParentFolder->requestSort(); + // mParentFolder->requestArrange(); + // } + //} mLabelWidthDirty = true; - dirtyFilter(); -} - -// This function is called when items are added or view filters change. It's -// implemented here but called by derived classes when folding the -// views. -void LLFolderViewItem::filterFromRoot( void ) -{ - LLFolderViewItem* root = getRoot(); - - root->filter(*((LLFolderView*)root)->getFilter()); -} - -// This function is called when the folder view is dirty. It's -// implemented here but called by derived classes when folding the -// views. -void LLFolderViewItem::arrangeFromRoot() -{ - LLFolderViewItem* root = getRoot(); - - S32 height = 0; - S32 width = 0; - S32 total_height = root->arrange( &width, &height, 0 ); - - LLSD params; - params["action"] = "size_changes"; - params["height"] = total_height; - getParent()->notifyParent(params); + vmi.dirtyFilter(); } // Utility function for LLFolderView @@ -313,7 +263,7 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection, } if(set_selection) { - setSelectionFromRoot(this, TRUE, take_keyboard_focus); + getRoot()->setSelection(this, TRUE, take_keyboard_focus); if(root) { root->scrollToShowSelection(); @@ -321,22 +271,6 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection, } } -// This function clears the currently selected item, and records the -// specified selected item appropriately for display and use in the -// UI. If open is TRUE, then folders are opened up along the way to -// the selection. -void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, - BOOL openitem, - BOOL take_keyboard_focus) -{ - getRoot()->setSelection(selection, openitem, take_keyboard_focus); -} - -// helper function to change the selection from the root. -void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected) -{ - getRoot()->changeSelection(selection, selected); -} std::set<LLFolderViewItem*> LLFolderViewItem::getSelectionList() const { @@ -347,18 +281,13 @@ std::set<LLFolderViewItem*> LLFolderViewItem::getSelectionList() const // addToFolder() returns TRUE if it succeeds. FALSE otherwise BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) { - if (!folder) - { - return FALSE; - } - mParentFolder = folder; return folder->addItem(this); } // Finds width and height of this object and its children. Also // makes sure that this view and its children are the right size. -S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) +S32 LLFolderViewItem::arrange( S32* width, S32* height ) { const Params& p = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); S32 indentation = p.folder_indentation(); @@ -390,41 +319,6 @@ S32 LLFolderViewItem::getItemHeight() return mItemHeight; } -void LLFolderViewItem::filter( LLFolderViewFilter& filter) -{ - const BOOL previous_passed_filter = mPassedFilter; - const BOOL passed_filter = filter.check(this); - - // If our visibility will change as a result of this filter, then - // we need to be rearranged in our parent folder - if (mParentFolder) - { - if (getVisible() != passed_filter - || previous_passed_filter != passed_filter ) - mParentFolder->requestArrange(); - } - - setFiltered(passed_filter, filter.getCurrentGeneration()); - //TODO RN: create interface for string highlighting - //mStringMatchOffset = filter.getStringMatchOffset(this); - filter.decrementFilterCount(); - - if (getRoot()->getDebugFilters()) - { - mStatusText = llformat("%d", mLastFilterGeneration); - } -} - -void LLFolderViewItem::dirtyFilter() -{ - mLastFilterGeneration = -1; - // bubble up dirty flag all the way to root - if (getParentFolder()) - { - getParentFolder()->setCompletedFilterGeneration(-1, TRUE); - } -} - // *TODO: This can be optimized a lot by simply recording that it is // selected in the appropriate places, and assuming that set selection // means 'deselect' for a leaf item. Do this optimization after @@ -469,45 +363,31 @@ void LLFolderViewItem::selectItem(void) { if (mIsSelected == FALSE) { - if (getViewModelItem()) - { - getViewModelItem()->selectItem(); - } + getViewModelItem()->selectItem(); mIsSelected = TRUE; } } BOOL LLFolderViewItem::isMovable() { - if( getViewModelItem() ) - { - return getViewModelItem()->isItemMovable(); - } - else - { - return TRUE; - } + return getViewModelItem()->isItemMovable(); } BOOL LLFolderViewItem::isRemovable() { - if( getViewModelItem() ) - { - return getViewModelItem()->isItemRemovable(); - } - else - { - return TRUE; - } + return getViewModelItem()->isItemRemovable(); } void LLFolderViewItem::destroyView() { + getRoot()->removeFromSelectionList(this); + if (mParentFolder) { // removeView deletes me - mParentFolder->removeView(this); + mParentFolder->extractItem(this); } + delete this; } // Call through to the viewed object and return true if it can be @@ -519,58 +399,36 @@ BOOL LLFolderViewItem::remove() { return FALSE; } - if(getViewModelItem()) - { - return getViewModelItem()->removeItem(); - } - return TRUE; + return getViewModelItem()->removeItem(); } // Build an appropriate context menu for the item. void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) { - if(getViewModelItem()) - { - getViewModelItem()->buildContextMenu(menu, flags); - } + getViewModelItem()->buildContextMenu(menu, flags); } void LLFolderViewItem::openItem( void ) { - if( getViewModelItem() ) - { - getViewModelItem()->openItem(); - } + getViewModelItem()->openItem(); } void LLFolderViewItem::rename(const std::string& new_name) { if( !new_name.empty() ) { - if( getViewModelItem() ) - { - getViewModelItem()->renameItem(new_name); + getViewModelItem()->renameItem(new_name); - if(mParentFolder) - { - mParentFolder->requestSort(); - } + if(mParentFolder) + { + mParentFolder->requestSort(); } } } -const std::string& LLFolderViewItem::getSearchableLabel() const -{ - return mSearchableLabel; -} - const std::string& LLFolderViewItem::getName( void ) const { - if(getViewModelItem()) - { - return getViewModelItem()->getName(); - } - return LLStringUtil::null; + return getViewModelItem()->getName(); } // LLView functionality @@ -578,7 +436,7 @@ BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) { if(!mIsSelected) { - setSelectionFromRoot(this, FALSE); + getRoot()->setSelection(this, FALSE); } make_ui_sound("UISndClick"); return TRUE; @@ -599,7 +457,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) { if(mask & MASK_CONTROL) { - changeSelectionFromRoot(this, !mIsSelected); + getRoot()->changeSelection(this, !mIsSelected); } else if (mask & MASK_SHIFT) { @@ -607,7 +465,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) } else { - setSelectionFromRoot(this, FALSE); + getRoot()->setSelection(this, FALSE); } make_ui_sound("UISndClick"); } @@ -646,14 +504,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) // *TODO: push this into listener and remove // dependency on llagent - if (getViewModelItem()) - { - src = getViewModelItem()->getDragSource(); - } - else - { - src = LLToolDragAndDrop::SOURCE_VIEWER; - } + src = getViewModelItem()->getDragSource(); can_drag = root->startDrag(src); if (can_drag) @@ -695,10 +546,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) { - if (getViewModelItem()) - { - getViewModelItem()->openItem(); - } + getViewModelItem()->openItem(); return TRUE; } @@ -715,7 +563,7 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) //...then select if(mask & MASK_CONTROL) { - changeSelectionFromRoot(this, !mIsSelected); + getRoot()->changeSelection(this, !mIsSelected); } else if (mask & MASK_SHIFT) { @@ -723,7 +571,7 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) } else { - setSelectionFromRoot(this, FALSE); + getRoot()->setSelection(this, FALSE); } } @@ -748,21 +596,17 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = FALSE; BOOL handled = FALSE; - if(getViewModelItem()) + BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + handled = accepted; + if (accepted) { - accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); - handled = accepted; - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; } if(mParentFolder && !handled) { @@ -781,17 +625,17 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLFolderViewItem::draw() { - static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); - static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); - static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); + static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); - static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); - static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); - static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); - static LLUIColor sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); - static LLUIColor sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); + static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); + static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); + static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); + static LLUIColor sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); + static LLUIColor sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); - static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); const Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); const S32 TOP_PAD = default_params.item_top_pad; @@ -929,29 +773,12 @@ void LLFolderViewItem::draw() LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; //TODO RN: implement this in terms of getColor() //if (highlight_link) color = sLinkColor; - //if (getViewModelItem() && gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; + //if (gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; F32 right_x = 0; F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); - //--------------------------------------------------------------------------------// - // Highlight filtered text - // - if (getRoot()->getDebugFilters()) - { - if (!getFiltered() && !getViewModelItem()->hasChildren()) - { - color.mV[VALPHA] *= 0.5f; - } - LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? - LLColor4(0.5f, 0.8f, 0.5f, 1.f) : - LLColor4(0.8f, 0.5f, 0.5f, 1.f); - LLFontGL::getFontMonospace()->renderUTF8(mStatusText, 0, text_left, y, filter_color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x, FALSE ); - text_left = right_x; - } //--------------------------------------------------------------------------------// // Draw the actual label text // @@ -997,6 +824,22 @@ void LLFolderViewItem::draw() //} } +const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const +{ + return getRoot()->getFolderViewModel(); +} + +LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) +{ + return getRoot()->getFolderViewModel(); +} + +S32 LLFolderViewItem::getLastFilterGeneration() const +{ + return getViewModelItem()->getLastFilterGeneration(); +} + + ///---------------------------------------------------------------------------- /// Class LLFolderViewFolder @@ -1010,10 +853,7 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): mTargetHeight(0.f), mAutoOpenCountdown(0.f), mLastArrangeGeneration( -1 ), - mLastCalculatedWidth(0), - mCompletedFilterGeneration(-1), - mMostFilteredDescendantGeneration(-1), - mPassedFolderFilter(FALSE) + mLastCalculatedWidth(0) { } @@ -1025,25 +865,9 @@ LLFolderViewFolder::~LLFolderViewFolder( void ) gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() } -void LLFolderViewFolder::setFilteredFolder(bool filtered, S32 filter_generation) -{ - mPassedFolderFilter = filtered; - mLastFilterGeneration = filter_generation; -} - -bool LLFolderViewFolder::getFilteredFolder(S32 filter_generation) -{ - return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter()->getFirstSuccessGeneration(); -} - // addToFolder() returns TRUE if it succeeds. FALSE otherwise BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) { - if (!folder) - { - return FALSE; - } - mParentFolder = folder; return folder->addFolder(this); } @@ -1051,7 +875,7 @@ static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); // Finds width and height of this object and its children. Also // makes sure that this view and its children are the right size. -S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) +S32 LLFolderViewFolder::arrange( S32* width, S32* height ) { // sort before laying out contents getRoot()->getFolderViewModel()->sort(this); @@ -1060,7 +884,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) // evaluate mHasVisibleChildren mHasVisibleChildren = false; - if (hasFilteredDescendants(filter_generation)) + if (getViewModelItem()->descendantsPassedFilter()) { // We have to verify that there's at least one child that's not filtered out bool found = false; @@ -1068,7 +892,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit) { LLFolderViewItem* itemp = (*iit); - found = (itemp->getFiltered(filter_generation)); + found = itemp->passedFilter(); if (found) break; } @@ -1078,9 +902,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) { LLFolderViewFolder* folderp = (*fit); - found = ( (folderp->getFiltered(filter_generation) - || (folderp->getFilteredFolder(filter_generation) - && folderp->hasFilteredDescendants(filter_generation)))); + found = folderp->passedFilter(); if (found) break; } @@ -1090,7 +912,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) } // calculate height as a single item (without any children), and reshapes rectangle to match - LLFolderViewItem::arrange( width, height, filter_generation ); + LLFolderViewItem::arrange( width, height ); // clamp existing animated height so as to never get smaller than a single item mCurHeight = llmax((F32)*height, mCurHeight); @@ -1113,16 +935,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) { LLFolderViewFolder* folderp = (*fit); - if (getRoot()->getDebugFilters()) - { - folderp->setVisible(TRUE); - } - else - { - folderp->setVisible( folderp->getFiltered(filter_generation) - || (folderp->getFilteredFolder(filter_generation) - && folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter - } + folderp->setVisible(folderp->passedFilter()); // passed filter or has descendants that passed filter if (folderp->getVisible()) { @@ -1130,7 +943,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) S32 child_height = 0; S32 child_top = parent_item_height - llround(running_height); - target_height += folderp->arrange( &child_width, &child_height, filter_generation ); + target_height += folderp->arrange( &child_width, &child_height ); running_height += (F32)child_height; *width = llmax(*width, child_width); @@ -1141,14 +954,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) iit != mItems.end(); ++iit) { LLFolderViewItem* itemp = (*iit); - if (getRoot()->getDebugFilters()) - { - itemp->setVisible(TRUE); - } - else - { - itemp->setVisible(itemp->getFiltered(filter_generation)); - } + itemp->setVisible(itemp->passedFilter()); if (itemp->getVisible()) { @@ -1156,7 +962,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) S32 child_height = 0; S32 child_top = parent_item_height - llround(running_height); - target_height += itemp->arrange( &child_width, &child_height, filter_generation ); + target_height += itemp->arrange( &child_width, &child_height ); // don't change width, as this item is as wide as its parent folder by construction itemp->reshape( itemp->getRect().getWidth(), child_height); @@ -1234,234 +1040,21 @@ void LLFolderViewFolder::requestSort() getViewModelItem()->requestSort(); } -void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up) -{ - //mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation); - mCompletedFilterGeneration = generation; - // only aggregate up if we are a lower (older) value - if (recurse_up - && mParentFolder - && generation < mParentFolder->getCompletedFilterGeneration()) - { - mParentFolder->setCompletedFilterGeneration(generation, TRUE); - } -} +//TODO RN: get height resetting working +//void LLFolderViewFolder::setPassedFilter(BOOL passed, BOOL passed_folder, S32 filter_generation) +//{ +// // if this folder is now filtered, but wasn't before +// // (it just passed) +// if (passed && !passedFilter(filter_generation)) +// { +// // reset current height, because last time we drew it +// // it might have had more visible items than now +// mCurHeight = 0.f; +// } +// +// LLFolderViewItem::setPassedFilter(passed, passed_folder, filter_generation); +//} -void LLFolderViewFolder::filter( LLFolderViewFilter& filter) -{ - S32 filter_generation = filter.getCurrentGeneration(); - // if failed to pass filter newer than must_pass_generation - // you will automatically fail this time, so we only - // check against items that have passed the filter - S32 must_pass_generation = filter.getFirstRequiredGeneration(); - - bool autoopen_folders = filter.showAllResults(); - - // if we have already been filtered against this generation, skip out - if (getCompletedFilterGeneration() >= filter_generation) - { - return; - } - - // filter folder itself - if (getLastFilterGeneration() < filter_generation) - { - if (getLastFilterGeneration() >= must_pass_generation // folder has been compared to a valid precursor filter - && !mPassedFilter) // and did not pass the filter - { - // go ahead and flag this folder as done - mLastFilterGeneration = filter_generation; - //TODO RN: create interface for string highlighting - //mStringMatchOffset = std::string::npos; - } - else // filter self only on first pass through - { - // filter against folder rules - filterFolder(filter); - // and then item rules - LLFolderViewItem::filter( filter ); - } - } - - if (getRoot()->getDebugFilters()) - { - mStatusText = llformat("%d", mLastFilterGeneration); - mStatusText += llformat("(%d)", mCompletedFilterGeneration); - mStatusText += llformat("+%d", mMostFilteredDescendantGeneration); - } - - // all descendants have been filtered later than must pass generation - // but none passed - if(getCompletedFilterGeneration() >= must_pass_generation && !hasFilteredDescendants(must_pass_generation)) - { - // don't traverse children if we've already filtered them since must_pass_generation - // and came back with nothing - return; - } - - // we entered here with at least one filter iteration left - // check to see if we have any more before continuing on to children - if (filter.getFilterCount() < 0) - { - return; - } - - // now query children - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end(); - ++iter) - { - LLFolderViewFolder* folder = (*iter); - // have we run out of iterations this frame? - if (filter.getFilterCount() < 0) - { - break; - } - - // mMostFilteredDescendantGeneration might have been reset - // in which case we need to update it even for folders that - // don't need to be filtered anymore - if (folder->getCompletedFilterGeneration() >= filter_generation) - { - // track latest generation to pass any child items - if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getFirstSuccessGeneration())) - { - mMostFilteredDescendantGeneration = filter_generation; - requestArrange(); - } - // just skip it, it has already been filtered - continue; - } - - // update this folders filter status (and children) - folder->filter( filter ); - - // track latest generation to pass any child items - if (folder->getFiltered() || folder->hasFilteredDescendants(filter_generation)) - { - mMostFilteredDescendantGeneration = filter_generation; - requestArrange(); - if (getRoot()->needsAutoSelect() && autoopen_folders) - { - folder->setOpenArrangeRecursively(TRUE); - } - } - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end(); - ++iter) - { - LLFolderViewItem* item = (*iter); - if (filter.getFilterCount() < 0) - { - break; - } - if (item->getLastFilterGeneration() >= filter_generation) - { - if (item->getFiltered()) - { - mMostFilteredDescendantGeneration = filter_generation; - requestArrange(); - } - continue; - } - - if (item->getLastFilterGeneration() >= must_pass_generation && - !item->getFiltered(must_pass_generation)) - { - // failed to pass an earlier filter that was a subset of the current one - // go ahead and flag this item as done - item->setFiltered(FALSE, filter_generation); - continue; - } - - item->filter( filter ); - - if (item->getFiltered(filter.getFirstSuccessGeneration())) - { - mMostFilteredDescendantGeneration = filter_generation; - requestArrange(); - } - } - - // if we didn't use all filter iterations - // that means we filtered all of our descendants - // instead of exhausting the filter count for this frame - if (filter.getFilterCount() > 0) - { - // flag this folder as having completed filter pass for all descendants - setCompletedFilterGeneration(filter_generation, FALSE/*dont recurse up to root*/); - } -} - -void LLFolderViewFolder::filterFolder(LLFolderViewFilter& filter) -{ - const BOOL previous_passed_filter = mPassedFolderFilter; - const BOOL passed_filter = filter.checkFolder(this); - - // If our visibility will change as a result of this filter, then - // we need to be rearranged in our parent folder - if (mParentFolder) - { - if (getVisible() != passed_filter - || previous_passed_filter != passed_filter ) - { - mParentFolder->requestArrange(); - } - } - - setFilteredFolder(passed_filter, filter.getCurrentGeneration()); - filter.decrementFilterCount(); - - if (getRoot()->getDebugFilters()) - { - mStatusText = llformat("%d", mLastFilterGeneration); - } -} - -void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation) -{ - // if this folder is now filtered, but wasn't before - // (it just passed) - if (filtered && !mPassedFilter) - { - // reset current height, because last time we drew it - // it might have had more visible items than now - mCurHeight = 0.f; - } - - LLFolderViewItem::setFiltered(filtered, filter_generation); -} - -void LLFolderViewFolder::dirtyFilter() -{ - // we're a folder, so invalidate our completed generation - setCompletedFilterGeneration(-1, FALSE); - LLFolderViewItem::dirtyFilter(); -} - -BOOL LLFolderViewFolder::getFiltered() -{ - return getFilteredFolder(getRoot()->getFilter()->getFirstSuccessGeneration()) - && LLFolderViewItem::getFiltered(); -} - -BOOL LLFolderViewFolder::getFiltered(S32 filter_generation) -{ - return getFilteredFolder(filter_generation) && LLFolderViewItem::getFiltered(filter_generation); -} - -BOOL LLFolderViewFolder::hasFilteredDescendants(S32 filter_generation) -{ - return mMostFilteredDescendantGeneration >= filter_generation; -} - - -BOOL LLFolderViewFolder::hasFilteredDescendants() -{ - return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getFirstSuccessGeneration(); -} // Passes selection information on to children and record selection // information if necessary. @@ -1824,39 +1417,7 @@ void LLFolderViewFolder::destroyView() folderp->destroyView(); // removes entry from mFolders } - if (mParentFolder) - { - mParentFolder->removeView(this); - } -} - -// remove the specified item (and any children) if possible. Return -// TRUE if the item was deleted. -BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item) -{ - if(item->remove()) - { - return TRUE; - } - return FALSE; -} - -// simply remove the view (and any children) Don't bother telling the -// listeners. -void LLFolderViewFolder::removeView(LLFolderViewItem* item) -{ - if (!item || item->getParentFolder() != this) - { - return; - } - // deselect without traversing hierarchy - if (item->isSelected()) - { - item->deselectItem(); - } - getRoot()->removeFromSelectionList(item); - extractItem(item); - delete item; + LLFolderViewItem::destroyView(); } // extractItem() removes the specified item from the folder, but @@ -1882,7 +1443,7 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) mItems.erase(it); } //item has been removed, need to update filter - dirtyFilter(); + getViewModelItem()->dirtyFilter(); //because an item is going away regardless of filter status, force rearrange requestArrange(); removeChild(item); @@ -1890,31 +1451,28 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) BOOL LLFolderViewFolder::isMovable() { - if( getViewModelItem() ) + if( !(getViewModelItem()->isItemMovable()) ) { - if( !(getViewModelItem()->isItemMovable()) ) - { - return FALSE; - } + return FALSE; + } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isMovable()) { - items_t::iterator iit = iter++; - if(!(*iit)->isMovable()) - { - return FALSE; - } + return FALSE; } + } - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isMovable()) { - folders_t::iterator fit = iter++; - if(!(*fit)->isMovable()) - { - return FALSE; - } + return FALSE; } } return TRUE; @@ -1923,31 +1481,28 @@ BOOL LLFolderViewFolder::isMovable() BOOL LLFolderViewFolder::isRemovable() { - if( getViewModelItem() ) + if( !(getViewModelItem()->isItemRemovable()) ) { - if( !(getViewModelItem()->isItemRemovable()) ) - { - return FALSE; - } + return FALSE; + } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isRemovable()) { - items_t::iterator iit = iter++; - if(!(*iit)->isRemovable()) - { - return FALSE; - } + return FALSE; } + } - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isRemovable()) { - folders_t::iterator fit = iter++; - if(!(*fit)->isRemovable()) - { - return FALSE; - } + return FALSE; } } return TRUE; @@ -1956,6 +1511,12 @@ BOOL LLFolderViewFolder::isRemovable() // this is an internal method used for adding items to folders. BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) { + if (item->getParentFolder()) + { + item->getParentFolder()->extractItem(item); + } + item->setParentFolder(this); + mItems.push_back(item); item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); @@ -1963,12 +1524,14 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) addChild(item); - item->dirtyFilter(); + item->getViewModelItem()->dirtyFilter(); // Handle sorting requestArrange(); requestSort(); + getViewModelItem()->addChild(item->getViewModelItem()); + //TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria //// Traverse parent folders and update creation date and resort, if necessary //LLFolderViewFolder* parentp = this; @@ -1989,16 +1552,23 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) // this is an internal method used for adding items to folders. BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) { + if (folder->mParentFolder) + { + folder->mParentFolder->extractItem(folder); + } + folder->mParentFolder = this; mFolders.push_back(folder); folder->setOrigin(0, 0); folder->reshape(getRect().getWidth(), 0); folder->setVisible(FALSE); addChild( folder ); - folder->dirtyFilter(); + folder->getViewModelItem()->dirtyFilter(); // rearrange all descendants too, as our indentation level might have changed folder->requestArrange(); requestSort(); + getViewModelItem()->addChild(folder->getViewModelItem()); + return TRUE; } @@ -2027,16 +1597,13 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r { BOOL was_open = isOpen(); mIsOpen = openitem; - if (getViewModelItem()) + if(!was_open && openitem) { - if(!was_open && openitem) - { - getViewModelItem()->openItem(); - } - else if(was_open && !openitem) - { - getViewModelItem()->closeItem(); - } + getViewModelItem()->openItem(); + } + else if(was_open && !openitem) + { + getViewModelItem()->closeItem(); } if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) @@ -2068,7 +1635,7 @@ BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); + BOOL accepted = mListener->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); if (accepted) { mDragAndDropTarget = TRUE; @@ -2156,7 +1723,7 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = getViewModelItem() && getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); if (accepted) { @@ -2259,7 +1826,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) } else { - setSelectionFromRoot(this, FALSE); + getRoot()->setSelection(this, FALSE); toggleOpen(); } handled = TRUE; @@ -2293,16 +1860,6 @@ void LLFolderViewFolder::draw() mExpanderHighlighted = FALSE; } -BOOL LLFolderViewFolder::potentiallyVisible() -{ - // folder should be visible by it's own filter status - return LLFolderViewItem::potentiallyVisible() - // or one or more of its descendants have passed the minimum filter requirement - || hasFilteredDescendants() - // or not all of its descendants have been checked against minimum filter requirement - || getCompletedFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration(); -} - // this does prefix traversal, as folders are listed above their contents LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children ) { diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index fd2948f34e..7e48969826 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -35,6 +35,7 @@ class LLFolderViewModelItem; class LLFolderViewFolder; class LLFolderViewFunctor; class LLFolderViewFilter; +class LLFolderViewModelInterface; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderViewItem @@ -78,8 +79,6 @@ public: static const F32 FOLDER_CLOSE_TIME_CONSTANT; static const F32 FOLDER_OPEN_TIME_CONSTANT; - const std::string& getSearchableLabel() { return mSearchableLabel; } - private: BOOL mIsSelected; @@ -90,7 +89,6 @@ protected: LLFolderViewItem(const Params& p); std::string mLabel; - std::string mSearchableLabel; S32 mLabelWidth; bool mLabelWidthDirty; LLFolderViewFolder* mParentFolder; @@ -106,8 +104,7 @@ protected: BOOL mHasVisibleChildren; S32 mIndentation; S32 mItemHeight; - BOOL mPassedFilter; - S32 mLastFilterGeneration; + //TODO RN: create interface for string highlighting //std::string::size_type mStringMatchOffset; F32 mControlLabelRotation; @@ -115,9 +112,6 @@ protected: BOOL mDragAndDropTarget; bool mIsMouseOverTitle; - // helper function to change the selection from the root. - void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected); - // this is an internal method used for adding items to folders. A // no-op at this level, but reimplemented in derived classes. virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } @@ -130,39 +124,20 @@ public: virtual void openItem( void ); - // This function clears the currently selected item, and records - // the specified selected item appropriately for display and use - // in the UI. If open is TRUE, then folders are opened up along - // the way to the selection. - void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus = TRUE); - - // This function is called when the folder view is dirty. It's - // implemented here but called by derived classes when folding the - // views. - void arrangeFromRoot(); - void filterFromRoot( void ); - void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus); virtual ~LLFolderViewItem( void ); // addToFolder() returns TRUE if it succeeds. FALSE otherwise - enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE }; virtual BOOL addToFolder(LLFolderViewFolder* folder); // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. - virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); + virtual S32 arrange( S32* width, S32* height ); virtual S32 getItemHeight(); - // applies filters to control visibility of items - virtual void filter( LLFolderViewFilter& filter); - // updates filter serial number and optionally propagated value up to root - S32 getLastFilterGeneration() { return mLastFilterGeneration; } - - virtual void dirtyFilter(); + S32 getLastFilterGeneration() const; // If 'selection' is 'this' then note that otherwise ignore. // Returns TRUE if this item ends up being selected. @@ -213,8 +188,6 @@ public: // viewed. This method will ask the viewed object itself. const std::string& getName( void ) const; - const std::string& getSearchableLabel( void ) const; - // This method returns the label displayed on the view. This // method was primarily added to allow sorting on the folder // contents possible before the entire view has been constructed. @@ -224,12 +197,17 @@ public: LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } + void setParentFolder(LLFolderViewFolder* parent) { mParentFolder = parent; } + LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); const LLFolderViewModelItem* getViewModelItem( void ) const { return mListener; } LLFolderViewModelItem* getViewModelItem( void ) { return mListener; } + const LLFolderViewModelInterface* getFolderViewModel( void ) const; + LLFolderViewModelInterface* getFolderViewModel( void ); + // just rename the object. void rename(const std::string& new_name); @@ -239,15 +217,11 @@ public: virtual BOOL isOpen() const { return FALSE; } virtual LLFolderView* getRoot(); + virtual const LLFolderView* getRoot() const; BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); S32 getIndentation() { return mIndentation; } - virtual BOOL potentiallyVisible(); // is the item definitely visible or we haven't made up our minds yet? - virtual BOOL potentiallyHidden(); // did this item not pass the filter or do we not know yet? - - virtual BOOL getFiltered(); - virtual BOOL getFiltered(S32 filter_generation); - virtual void setFiltered(BOOL filtered, S32 filter_generation); + virtual BOOL passedFilter(S32 filter_generation = -1); // refresh information from the object being viewed. virtual void refresh(); @@ -305,7 +279,6 @@ protected: F32 mAutoOpenCountdown; S32 mLastArrangeGeneration; S32 mLastCalculatedWidth; - S32 mCompletedFilterGeneration; S32 mMostFilteredDescendantGeneration; bool mNeedsSort; bool mPassedFolderFilter; @@ -322,8 +295,6 @@ public: virtual ~LLFolderViewFolder( void ); - virtual BOOL potentiallyVisible(); - LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); @@ -332,34 +303,17 @@ public: // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. - virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); + virtual S32 arrange( S32* width, S32* height ); BOOL needsArrange(); - virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up); - virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; } - - BOOL hasFilteredDescendants(S32 filter_generation); - BOOL hasFilteredDescendants(); - - // applies filters to control visibility of items - virtual void filter( LLFolderViewFilter& filter); - virtual void setFiltered(BOOL filtered, S32 filter_generation); - virtual BOOL getFiltered(); - virtual BOOL getFiltered(S32 filter_generation); - - virtual void dirtyFilter(); - - // folder-specific filtering (filter status propagates top down instead of bottom up) - void filterFolder(LLFolderViewFilter& filter); - void setFilteredFolder(bool filtered, S32 filter_generation); - bool getFilteredFolder(S32 filter_generation); + bool descendantsPassedFilter(S32 filter_generation = -1); // Passes selection information on to children and record // selection information if necessary. // Returns TRUE if this object (or a child) ends up being selected. // If 'openitem' is TRUE then folders are opened up along the way to the selection. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus = TRUE); // This method is used to change the selection of an item. // Recursively traverse all children; if 'selection' is 'this' then change @@ -385,14 +339,6 @@ public: //virtual BOOL removeRecursively(BOOL single_item); //virtual BOOL remove(); - // remove the specified item (and any children) if - // possible. Return TRUE if the item was deleted. - BOOL removeItem(LLFolderViewItem* item); - - // simply remove the view (and any children) Don't bother telling - // the listeners. - void removeView(LLFolderViewItem* item); - // extractItem() removes the specified item from the folder, but // doesn't delete it. virtual void extractItem( LLFolderViewItem* item ); diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 74c8bb92ef..0216ba2a07 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -72,9 +72,9 @@ public: // +-------------------------------------------------------------------+ // + Execution And Results // +-------------------------------------------------------------------+ - virtual bool check(const LLFolderViewItem* item) = 0; + virtual bool check(const LLFolderViewModelItem* item) = 0; virtual bool check(const LLInventoryItem* item) = 0; - virtual bool checkFolder(const LLFolderViewFolder* folder) const = 0; + virtual bool checkFolder(const LLFolderViewModelItem* folder) const = 0; virtual bool checkFolder(const LLUUID& folder_id) const = 0; virtual void setEmptyLookupMessage(const std::string& message) = 0; @@ -126,6 +126,8 @@ public: virtual bool contentsReady() = 0; virtual void setFolderView(LLFolderView* folder_view) = 0; + virtual LLFolderViewFilter* getFilter() = 0; + virtual const LLFolderViewFilter* getFilter() const = 0; }; class LLFolderViewModelCommon : public LLFolderViewModelInterface @@ -152,20 +154,82 @@ protected: }; +template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE> +class LLFolderViewModel : public LLFolderViewModelCommon +{ +public: + LLFolderViewModel(){} + virtual ~LLFolderViewModel() {} + + typedef SORT_TYPE SortType; + typedef ITEM_TYPE ItemType; + typedef FOLDER_TYPE FolderType; + typedef FILTER_TYPE FilterType; + + virtual SortType& getSorter() { return mSorter; } + virtual const SortType& getSorter() const { return mSorter; } + virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } + + virtual FilterType* getFilter() { return &mFilter; } + virtual const FilterType* getFilter() const { return &mFilter; } + virtual void setFilter(const FilterType& filter) { mFilter = filter; } + + // TODO RN: remove this and put all filtering logic in view model + // add getStatusText and isFiltering() + virtual bool contentsReady() { return true; } + + struct ViewModelCompare + { + ViewModelCompare(const SortType& sorter) + : mSorter(sorter) + {} + + bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const + { + return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); + } + + bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const + { + return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); + } + + const SortType& mSorter; + }; + + void sort(LLFolderViewFolder* folder) + { + if (needsSort(folder->getViewModelItem())) + { + folder->sortFolders(ViewModelCompare(getSorter())); + folder->sortItems(ViewModelCompare(getSorter())); + folder->getViewModelItem()->setSortVersion(mTargetSortVersion); + folder->requestArrange(); + } + } + + //TODO RN: fix this + void filter(LLFolderViewFolder* folder) + { + + } + +protected: + SortType mSorter; + FilterType mFilter; +}; + // This is am abstract base class that users of the folderview classes // would use to bridge the folder view with the underlying data class LLFolderViewModelItem { public: - LLFolderViewModelItem() - : mFolderViewItem(NULL) - {} - virtual ~LLFolderViewModelItem( void ) {}; virtual void update() {} //called when drawing virtual const std::string& getName() const = 0; virtual const std::string& getDisplayName() const = 0; + virtual const std::string& getSearchableName() const = 0; virtual LLPointer<LLUIImage> getIcon() const = 0; virtual LLPointer<LLUIImage> getIconOpen() const { return getIcon(); } @@ -198,12 +262,23 @@ public: virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; + virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? + + virtual void filter( LLFolderViewFilter& filter) = 0; + virtual bool passedFilter(S32 filter_generation = -1) = 0; + virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; + virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) = 0; + virtual void dirtyFilter() = 0; + + virtual S32 getLastFilterGeneration() const = 0; + // This method should be called when a drag begins. returns TRUE // if the drag can begin, otherwise FALSE. virtual LLToolDragAndDrop::ESource getDragSource() const = 0; virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; virtual bool hasChildren() const = 0; + virtual void addChild(LLFolderViewModelItem* child) = 0; // This method will be called to determine if a drop can be // performed, and will set drop to TRUE if a drop is @@ -217,10 +292,12 @@ public: virtual void requestSort() = 0; virtual S32 getSortVersion() = 0; virtual void setSortVersion(S32 version) = 0; + virtual void setParent(LLFolderViewModelItem* parent) = 0; + protected: + friend class LLFolderViewItem; - void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} - LLFolderViewItem* mFolderViewItem; + virtual void setFolderViewItem(LLFolderViewItem* folder_view_item) = 0; }; @@ -228,95 +305,48 @@ class LLFolderViewModelItemCommon : public LLFolderViewModelItem { public: LLFolderViewModelItemCommon() - : mSortVersion(-1) + : mSortVersion(-1), + mPassedFilter(false), + mPassedFolderFilter(false), + mFolderViewItem(NULL), + mLastFilterGeneration(-1), + mMostFilteredDescendantGeneration(-1) {} void requestSort() { mSortVersion = -1; } S32 getSortVersion() { return mSortVersion; } void setSortVersion(S32 version) { mSortVersion = version;} -protected: - - S32 mSortVersion; -}; - -template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE> -class LLFolderViewModel : public LLFolderViewModelCommon -{ -public: - LLFolderViewModel(){} - virtual ~LLFolderViewModel() {} - - typedef SORT_TYPE SortType; - typedef ITEM_TYPE ItemType; - typedef FOLDER_TYPE FolderType; - typedef FILTER_TYPE FilterType; - - virtual SortType& getSorter() { return mSorter; } - virtual const SortType& getSorter() const { return mSorter; } - virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } - virtual FilterType& getFilter() { return mFilter; } - virtual const FilterType& getFilter() const { return mFilter; } - virtual void setFilter(const FilterType& filter) { mFilter = filter; } - - // TODO RN: remove this and put all filtering logic in view model - // add getStatusText and isFiltering() - virtual bool contentsReady() { return true; } - - struct ViewModelCompare + S32 getLastFilterGeneration() const { return mLastFilterGeneration; } + void dirtyFilter() { - ViewModelCompare(const SortType& sorter) - : mSorter(sorter) - {} - - bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const + mLastFilterGeneration = -1; + // bubble up dirty flag all the way to root + if (mParent) { - return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); + mParent->dirtyFilter(); } + } + virtual void addChild(LLFolderViewModelItem* child) { mChildren.push_back(child); child->setParent(this); } - bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const - { - return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); - } +protected: + virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } - const SortType& mSorter; - }; + S32 mSortVersion; + bool mPassedFilter; + bool mPassedFolderFilter; - void sort(LLFolderViewFolder* folder) - { - if (needsSort(folder->getViewModelItem())) - { - folder->sortFolders(ViewModelCompare(getSorter())); - folder->sortItems(ViewModelCompare(getSorter())); - folder->getViewModelItem()->setSortVersion(mTargetSortVersion); - folder->requestArrange(); - } - } + S32 mLastFilterGeneration; + S32 mMostFilteredDescendantGeneration; - //TODO RN: fix this - void filter(LLFolderViewFolder* folder) - { - /*FilterType& filter = getFilter(); - for (std::list<LLFolderViewItem*>::const_iterator it = folder->getItemsBegin(), end_it = folder->getItemsEnd(); - it != end_it; - ++it) - { - LLFolderViewItem* child_item = *it; - child_item->setFiltered(filter.checkFolder(static_cast<ItemType*>(child_item->getViewModelItem())), filter.getCurrentGeneration()); - } - for (std::list<LLFolderViewFolder*>::const_iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); - it != end_it; - ++it) - { - LLFolderViewItem* child_folder = *it; - child_folder->setFiltered(filter.check(static_cast<ItemType*>(child_folder->getViewModelItem())), filter.getCurrentGeneration()); - }*/ - } + typedef std::list<LLFolderViewModelItem*> child_list_t; + child_list_t mChildren; + LLFolderViewModelItem* mParent; -protected: - SortType mSorter; - FilterType mFilter; + void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} + LLFolderViewItem* mFolderViewItem; }; + #endif diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 70a174a140..45a2bffa6b 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1545,6 +1545,10 @@ void LLItemBridge::buildDisplayName() const { mDisplayName.assign(LLStringUtil::null); } + + mSearchableName.assign(mDisplayName); + mSearchableName.append(getLabelSuffix()); + LLStringUtil::toUpper(mSearchableName); } LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const @@ -1850,11 +1854,9 @@ void LLFolderBridge::buildDisplayName() const LLTrans::findString(mDisplayName, std::string("InvFolder ") + getName(), LLSD()); } - //if (mDisplayName.empty()) - //{ - // S32 foo; - // foo = 0; - //} + mSearchableName.assign(mDisplayName); + mSearchableName.append(getLabelSuffix()); + LLStringUtil::toUpper(mSearchableName); } @@ -4000,7 +4002,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLFolderViewItem* fv_item = active_panel->getItemByID(inv_item->getUUID()); if (!fv_item) return false; - accept = filter->check(fv_item); + accept = filter->check(fv_item->getViewModelItem()); } if (accept && drop) @@ -4222,7 +4224,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLFolderViewItem* fv_item = active_panel->getItemByID(inv_item->getUUID()); if (!fv_item) return false; - accept = filter->check(fv_item); + accept = filter->check(fv_item->getViewModelItem()); } if (accept && drop) @@ -4319,7 +4321,7 @@ bool check_item(const LLUUID& item_id, LLFolderViewItem* fv_item = active_panel->getItemByID(item_id); if (!fv_item) return false; - return filter->check(fv_item); + return filter->check(fv_item->getViewModelItem()); } // +=================================================+ @@ -6126,7 +6128,7 @@ void LLLinkFolderBridge::gotoItem() model->fetchDescendentsOf(cat_uuid); } base_folder->setOpen(TRUE); - mRoot->setSelectionFromRoot(base_folder,TRUE); + mRoot->setSelection(base_folder,TRUE); mRoot->scrollToShowSelection(); } } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 26789627f7..b0582d003d 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -88,6 +88,8 @@ public: //-------------------------------------------------------------------- virtual const std::string& getName() const; virtual const std::string& getDisplayName() const; + const std::string& getSearchableName() const { return mSearchableName; } + virtual PermissionMask getPermissionMask() const; virtual LLFolderType::EType getPreferredType() const; virtual time_t getCreationDate() const; @@ -174,6 +176,7 @@ protected: bool mIsLink; LLTimer mTimeSinceRequestStart; mutable std::string mDisplayName; + mutable std::string mSearchableName; void purgeItem(LLInventoryModel *model, const LLUUID &uuid); virtual void buildDisplayName() const {} diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index c13bb5123e..c7e0136368 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -71,35 +71,35 @@ LLInventoryFilter::LLInventoryFilter(const Params& p) mFilterOps(p.filter_ops), mOrder(p.sort_order), mFilterSubString(p.substring), - mLastSuccessGeneration(0), - mLastFailGeneration(S32_MAX), + mCurrentGeneration(0), + mFirstRequiredGeneration(0), mFirstSuccessGeneration(0), mFilterCount(0) { - mNextFilterGeneration = mLastSuccessGeneration + 1; + mNextFilterGeneration = mCurrentGeneration + 1; // copy mFilterOps into mDefaultFilterOps markDefault(); } -bool LLInventoryFilter::check(const LLFolderViewItem* item) +bool LLInventoryFilter::check(const LLFolderViewModelItem* item) { + const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item); // Clipboard cut items are *always* filtered so we need this value upfront - const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE); // If it's a folder and we're showing all folders, return automatically. - const BOOL is_folder = (dynamic_cast<const LLFolderViewFolder*>(item) != NULL); + const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY;; if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)) { return passed_clipboard; } - std::string::size_type string_offset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; + std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos; - const BOOL passed_filtertype = checkAgainstFilterType(item); - const BOOL passed_permissions = checkAgainstPermissions(item); - const BOOL passed_filterlink = checkAgainstFilterLinks(item); + const BOOL passed_filtertype = checkAgainstFilterType(listener); + const BOOL passed_permissions = checkAgainstPermissions(listener); + const BOOL passed_filterlink = checkAgainstFilterLinks(listener); const BOOL passed = (passed_filtertype && passed_permissions && passed_filterlink && @@ -117,27 +117,19 @@ bool LLInventoryFilter::check(const LLInventoryItem* item) const bool passed_permissions = checkAgainstPermissions(item); const BOOL passed_clipboard = checkAgainstClipboard(item->getUUID()); const bool passed = (passed_filtertype - && passed_permissions - && passed_clipboard - && (mFilterSubString.size() == 0 || string_offset != std::string::npos)); + && passed_permissions + && passed_clipboard + && (mFilterSubString.size() == 0 || string_offset != std::string::npos)); return passed; } -bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const +bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const { - if (!folder) - { - llwarns << "The filter can not be checked on an invalid folder." << llendl; - llassert(false); // crash in development builds - return false; - } - - const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(folder->getViewModelItem()); + const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item); if (!listener) { - llwarns << "Folder view event listener not found." << llendl; - llassert(false); // crash in development builds + llerrs << "Folder view event listener not found." << llendl; return false; } @@ -179,9 +171,8 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const return passed_clipboard; } -bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInventory* listener) const { - const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); if (!listener) return FALSE; LLInventoryType::EType object_type = listener->getInventoryType(); @@ -347,13 +338,12 @@ bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const return true; } -bool LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstPermissions(const LLFolderViewModelItemInventory* listener) const { - const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); if (!listener) return FALSE; PermissionMask perm = listener->getPermissionMask(); - const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(item->getViewModelItem()); + const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(listener); if (bridge && bridge->isLink()) { const LLUUID& linked_uuid = gInventory.getLinkedItemID(bridge->getUUID()); @@ -375,9 +365,8 @@ bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) con return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions; } -bool LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewModelItemInventory* listener) const { - const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); if (!listener) return TRUE; const LLUUID object_id = listener->getUUID(); @@ -740,7 +729,7 @@ void LLInventoryFilter::resetDefault() void LLInventoryFilter::setModified(EFilterModified behavior) { mFilterText.clear(); - mLastSuccessGeneration = mNextFilterGeneration++; + mCurrentGeneration = mNextFilterGeneration++; if (mFilterModified == FILTER_NONE) { @@ -753,33 +742,21 @@ void LLInventoryFilter::setModified(EFilterModified behavior) mFilterModified = FILTER_RESTART; } - if (isNotDefault()) - { - // if not keeping current filter results, update last valid as well - switch(mFilterModified) - { - case FILTER_RESTART: - mLastFailGeneration = mLastSuccessGeneration; - mFirstSuccessGeneration = mLastSuccessGeneration; - break; - case FILTER_LESS_RESTRICTIVE: - mLastFailGeneration = mLastSuccessGeneration; - break; - case FILTER_MORE_RESTRICTIVE: - mFirstSuccessGeneration = mLastSuccessGeneration; - // must have passed either current filter generation (meaningless, as it hasn't been run yet) - // or some older generation, so keep the value - mLastFailGeneration = llmin(mLastFailGeneration, mLastSuccessGeneration); - break; - default: - llerrs << "Bad filter behavior specified" << llendl; - } - } - else + // if not keeping current filter results, update last valid as well + switch(mFilterModified) { - // shortcut disabled filters to show everything immediately - mLastFailGeneration = 0; - mFirstSuccessGeneration = S32_MAX; + case FILTER_RESTART: + mFirstRequiredGeneration = mCurrentGeneration; + mFirstSuccessGeneration = mCurrentGeneration; + break; + case FILTER_LESS_RESTRICTIVE: + mFirstRequiredGeneration = mCurrentGeneration; + break; + case FILTER_MORE_RESTRICTIVE: + mFirstSuccessGeneration = mCurrentGeneration; + break; + default: + llerrs << "Bad filter behavior specified" << llendl; } } @@ -1101,7 +1078,7 @@ void LLInventoryFilter::decrementFilterCount() S32 LLInventoryFilter::getCurrentGeneration() const { - return mLastSuccessGeneration; + return mCurrentGeneration; } S32 LLInventoryFilter::getFirstSuccessGeneration() const { @@ -1109,7 +1086,7 @@ S32 LLInventoryFilter::getFirstSuccessGeneration() const } S32 LLInventoryFilter::getFirstRequiredGeneration() const { - return mLastFailGeneration; + return mFirstRequiredGeneration; } void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 5b92c21a85..af245a9c3b 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -186,16 +186,10 @@ public: // +-------------------------------------------------------------------+ // + Execution And Results // +-------------------------------------------------------------------+ - bool check(const LLFolderViewItem* item); + bool check(const LLFolderViewModelItem* listener); bool check(const LLInventoryItem* item); - bool checkFolder(const LLFolderViewFolder* folder) const; + bool checkFolder(const LLFolderViewModelItem* listener) const; bool checkFolder(const LLUUID& folder_id) const; - bool checkAgainstFilterType(const LLFolderViewItem* item) const; - bool checkAgainstFilterType(const LLInventoryItem* item) const; - bool checkAgainstPermissions(const LLFolderViewItem* item) const; - bool checkAgainstPermissions(const LLInventoryItem* item) const; - bool checkAgainstFilterLinks(const LLFolderViewItem* item) const; - bool checkAgainstClipboard(const LLUUID& object_id) const; bool showAllResults() const; @@ -260,6 +254,12 @@ public: private: bool areDateLimitsSet(); + bool checkAgainstFilterType(const class LLFolderViewModelItemInventory* listener) const; + bool checkAgainstFilterType(const LLInventoryItem* item) const; + bool checkAgainstPermissions(const class LLFolderViewModelItemInventory* listener) const; + bool checkAgainstPermissions(const LLInventoryItem* item) const; + bool checkAgainstFilterLinks(const class LLFolderViewModelItemInventory* listener) const; + bool checkAgainstClipboard(const LLUUID& object_id) const; U32 mOrder; @@ -270,8 +270,8 @@ private: std::string mFilterSubStringOrig; const std::string mName; - S32 mLastSuccessGeneration; - S32 mLastFailGeneration; + S32 mCurrentGeneration; + S32 mFirstRequiredGeneration; S32 mFirstSuccessGeneration; S32 mNextFilterGeneration; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 1e494c3ef1..ff461236a2 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -983,7 +983,7 @@ void LLSaveFolderState::doFolder(LLFolderViewFolder* folder) void LLOpenFilteredFolders::doItem(LLFolderViewItem *item) { - if (item->getFiltered()) + if (item->passedFilter()) { item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); } @@ -991,12 +991,12 @@ void LLOpenFilteredFolders::doItem(LLFolderViewItem *item) void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder) { - if (folder->getFiltered() && folder->getParentFolder()) + if (folder->LLFolderViewItem::passedFilter() && folder->getParentFolder()) { folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); } // if this folder didn't pass the filter, and none of its descendants did - else if (!folder->getFiltered() && !folder->hasFilteredDescendants()) + else if (!folder->getViewModelItem()->passedFilter() && !folder->getViewModelItem()->descendantsPassedFilter()) { folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO); } @@ -1004,7 +1004,7 @@ void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder) void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item) { - if (item->getFiltered() && !mItemSelected) + if (item->passedFilter() && !mItemSelected) { item->getRoot()->setSelection(item, FALSE, FALSE); if (item->getParentFolder()) @@ -1017,7 +1017,7 @@ void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item) void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder) { - if (folder->getFiltered() && !mItemSelected) + if (folder->LLFolderViewItem::passedFilter() && !mItemSelected) { folder->getRoot()->setSelection(folder, FALSE, FALSE); if (folder->getParentFolder()) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 74492e0005..aba4c088ab 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -254,18 +254,16 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) mFolderRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); // Scroller - { - LLRect scroller_view_rect = getRect(); - scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); - LLScrollContainer::Params scroller_params(params.scroll()); - scroller_params.rect(scroller_view_rect); - mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); - addChild(mScroller); - mScroller->addChild(mFolderRoot); - mFolderRoot->setScrollContainer(mScroller); - mFolderRoot->setFollowsAll(); - mFolderRoot->addChild(mFolderRoot->mStatusTextBox); - } + LLRect scroller_view_rect = getRect(); + scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); + LLScrollContainer::Params scroller_params(params.scroll()); + scroller_params.rect(scroller_view_rect); + mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); + addChild(mScroller); + mScroller->addChild(mFolderRoot); + mFolderRoot->setScrollContainer(mScroller); + mFolderRoot->setFollowsAll(); + mFolderRoot->addChild(mFolderRoot->mStatusTextBox); // Set up the callbacks from the inventory we're viewing, and then build everything. mInventoryObserver = new LLInventoryPanelObserver(this); @@ -344,12 +342,12 @@ void LLInventoryPanel::draw() const LLInventoryFilter* LLInventoryPanel::getFilter() const { - return &getFolderViewModel()->getFilter(); + return getFolderViewModel()->getFilter(); } LLInventoryFilter* LLInventoryPanel::getFilter() { - return &getFolderViewModel()->getFilter(); + return getFolderViewModel()->getFilter(); } void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type) @@ -561,7 +559,6 @@ void LLInventoryPanel::modelChanged(U32 mask) if (new_parent != NULL) { // Item is to be moved and we found its new parent in the panel's directory, so move the item's UI. - view_item->getParentFolder()->extractItem(view_item); view_item->addToFolder(new_parent); addItemID(viewmodel_item->getUUID(), view_item); } @@ -1358,3 +1355,104 @@ void LLFolderViewModelItemInventory::requestSort() mFolderViewItem->getParentFolder()->getViewModelItem()->requestSort(); } } + +bool LLFolderViewModelItemInventory::potentiallyVisible() +{ + return passedFilter() // we've passed the filter + || getLastFilterGeneration() < mFolderViewItem->getRoot()->getFolderViewModel()->getFilter()->getFirstSuccessGeneration() // or we don't know yet + || descendantsPassedFilter(); +} + +bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) +{ + if (filter_generation < 0) filter_generation = mFolderViewItem->getRoot()->getFolderViewModel()->getFilter()->getFirstSuccessGeneration(); + return mPassedFolderFilter + && mLastFilterGeneration >= filter_generation + && (mPassedFilter || descendantsPassedFilter(filter_generation)); +} + +bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) +{ + if (filter_generation < 0) filter_generation = mFolderViewItem->getRoot()->getFolderViewModel()->getFilter()->getFirstSuccessGeneration(); + return mMostFilteredDescendantGeneration >= filter_generation; +} + +void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) +{ + mPassedFilter = passed; + mPassedFolderFilter = passed_folder; + mLastFilterGeneration = filter_generation; +} + +void LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) +{ + S32 filter_generation = filter.getCurrentGeneration(); + S32 must_pass_generation = filter.getFirstRequiredGeneration(); + + // mMostFilteredDescendantGeneration might have been reset + // in which case we need to update it even for folders that + // don't need to be filtered anymore + if (item->getLastFilterGeneration() < filter_generation) + { + if (item->getLastFilterGeneration() >= must_pass_generation && + !item->passedFilter(must_pass_generation)) + { + // failed to pass an earlier filter that was a subset of the current one + // go ahead and flag this item as done + item->setPassedFilter(false, false, filter_generation); + } + else + { + //TODO RN: + item->filter( filter ); + } + } + + // track latest generation to pass any child items + if (item->passedFilter()) + { + mMostFilteredDescendantGeneration = filter_generation; + //TODO RN: ensure this still happens + //requestArrange(); + } +} + +void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) +{ + if(getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass + || descendantsPassedFilter(filter.getFirstRequiredGeneration())) // or at least one descendant has passed the minimum requirement + { + // now query children + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end() && filter.getFilterCount() > 0; + ++iter) + { + filterChildItem((*iter), filter); + } + } + + // if we didn't use all filter iterations + // that means we filtered all of our descendants + // so filter ourselves now + if (filter.getFilterCount() > 0) + { + const BOOL previous_passed_filter = mPassedFilter; + const BOOL passed_filter = filter.check(this); + const BOOL passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) + ? filter.checkFolder(this) + : true; + + // If our visibility will change as a result of this filter, then + // we need to be rearranged in our parent folder + LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder(); + if (parent_folder && passed_filter != previous_passed_filter) + { + parent_folder->requestArrange(); + } + + setPassedFilter(passed_filter, passed_filter_folder, filter.getCurrentGeneration()); + //TODO RN: create interface for string highlighting + //mStringMatchOffset = filter.getStringMatchOffset(this); + filter.decrementFilterCount(); + } +} diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 645e2f6d76..35a3f9b5e1 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -62,6 +62,12 @@ public: virtual EInventorySortGroup getSortGroup() const = 0; virtual LLInventoryObject* getInventoryObject() const = 0; virtual void requestSort(); + virtual bool potentiallyVisible(); + virtual bool passedFilter(S32 filter_generation = -1); + virtual bool descendantsPassedFilter(S32 filter_generation = -1); + virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); + virtual void filter( LLFolderViewFilter& filter); + virtual void filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); }; class LLInventorySort diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 901c6379de..0b899d34f4 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -102,7 +102,7 @@ void LLCheckFolderState::doFolder(LLFolderViewFolder* folder) // Counting only folders that pass the filter. // The listener check allow us to avoid counting the folder view // object itself because it has no listener assigned. - if (folder->hasFilteredDescendants() && folder->getViewModelItem()) + if (folder->getViewModelItem()->descendantsPassedFilter()) { if (folder->isOpen()) { diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index e3446fdb3a..33581160fd 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -227,7 +227,7 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) } } - LLInventoryFilter* filter = getChild<LLInventoryPanel>("Recent Items")->getFilter(); + LLInventoryFilter* filter = findChild<LLInventoryPanel>("Recent Items")->getFilter(); if (filter) { LLSD filterState; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index da82d70f22..6a232a26f7 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -77,6 +77,7 @@ protected: LLUUID mUUID; std::string mName; mutable std::string mDisplayName; + mutable std::string mSearchableName; LLPanelObjectInventory* mPanel; U32 mFlags; LLAssetType::EType mAssetType; @@ -105,6 +106,8 @@ public: // LLFolderViewModelItemInventory functionality virtual const std::string& getName() const; virtual const std::string& getDisplayName() const; + virtual const std::string& getSearchableName() const; + virtual PermissionMask getPermissionMask() const { return PERM_NONE; } /*virtual*/ LLFolderType::EType getPreferredType() const { return LLFolderType::FT_NONE; } virtual const LLUUID& getUUID() const { return mUUID; } @@ -335,9 +338,17 @@ const std::string& LLTaskInvFVBridge::getDisplayName() const } } + mSearchableName.assign(mDisplayName + getLabelSuffix()); + return mDisplayName; } +const std::string& LLTaskInvFVBridge::getSearchableName() const +{ + return mSearchableName; +} + + // BUG: No creation dates for task inventory time_t LLTaskInvFVBridge::getCreationDate() const { diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 194aa7f71b..b143240187 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -271,7 +271,7 @@ void LLSidepanelAppearance::onOpenOutfitButtonClicked() if (outfit_folder) { outfit_folder->setOpen(!outfit_folder->isOpen()); - root->setSelectionFromRoot(outfit_folder,TRUE); + root->setSelection(outfit_folder,TRUE); root->scrollToShowSelection(); } } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 50d63911ad..654b18614a 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -623,10 +623,9 @@ void LLFloaterTexturePicker::draw() LLFolderView* folder_view = mInventoryPanel->getRootFolder(); if (!folder_view) return; - LLInventoryFilter* filter = static_cast<LLInventoryFilter*>(folder_view->getFilter()); - if (!filter) return; + LLInventoryFilter* filter = static_cast<LLFolderViewModelInventory*>(folder_view->getFolderViewModel())->getFilter(); - bool is_filter_active = folder_view->getCompletedFilterGeneration() < filter->getCurrentGeneration() && + bool is_filter_active = folder_view->getLastFilterGeneration() < filter->getCurrentGeneration() && filter->isNotDefault(); // After inventory panel filter is applied we have to update @@ -637,8 +636,9 @@ void LLFloaterTexturePicker::draw() if (!is_filter_active && !mSelectedItemPinned) { folder_view->setPinningSelectedItem(mSelectedItemPinned); - folder_view->dirtyFilter(); - folder_view->arrangeFromRoot(); + folder_view->getViewModelItem()->dirtyFilter(); + //TODO RN: test + //folder_view->arrangeFromRoot(); mSelectedItemPinned = TRUE; } -- cgit v1.2.3 From 569c004057ef5da03e05bedf77d39159e5782458 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 27 Jun 2012 19:17:49 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose fixed crash on startup --- indra/newview/llfolderviewmodel.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 0216ba2a07..c5079712f5 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -310,7 +310,8 @@ public: mPassedFolderFilter(false), mFolderViewItem(NULL), mLastFilterGeneration(-1), - mMostFilteredDescendantGeneration(-1) + mMostFilteredDescendantGeneration(-1), + mParent(NULL) {} void requestSort() { mSortVersion = -1; } -- cgit v1.2.3 From e8fa07d6384c9eb2a0fb42b0e06abb6a0d5fdea9 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 28 Jun 2012 16:47:37 -0700 Subject: CHUI-82 : Fixed all icons to use the new Conv_*.png icons; please use those in the new UIs moving forward --- .../textures/icons/Conv_toolbar_add_person.png | Bin 0 -> 322 bytes .../textures/icons/Conv_toolbar_arrow_ne.png | Bin 0 -> 301 bytes .../textures/icons/Conv_toolbar_arrow_sw.png | Bin 0 -> 293 bytes .../textures/icons/Conv_toolbar_call_log.png | Bin 0 -> 546 bytes .../default/textures/icons/Conv_toolbar_close.png | Bin 0 -> 262 bytes .../textures/icons/Conv_toolbar_collapse.png | Bin 0 -> 663 bytes .../default/textures/icons/Conv_toolbar_expand.png | Bin 0 -> 662 bytes .../textures/icons/Conv_toolbar_hang_up.png | Bin 0 -> 460 bytes .../textures/icons/Conv_toolbar_open_call.png | Bin 0 -> 485 bytes .../default/textures/icons/Conv_toolbar_plus.png | Bin 0 -> 195 bytes .../default/textures/icons/Conv_toolbar_sort.png | Bin 0 -> 196 bytes indra/newview/skins/default/textures/textures.xml | 14 ++++++++ .../skins/default/xui/en/floater_im_container.xml | 10 +++--- .../skins/default/xui/en/floater_im_session.xml | 36 ++++++++++----------- .../default/xui/en/panel_block_list_sidetray.xml | 2 +- .../newview/skins/default/xui/en/panel_people.xml | 8 ++--- 16 files changed, 42 insertions(+), 28 deletions(-) create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_close.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png (limited to 'indra') diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png new file mode 100755 index 0000000000..f024c733f3 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png new file mode 100755 index 0000000000..a19e720d42 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png new file mode 100755 index 0000000000..7f3f42639d Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png new file mode 100755 index 0000000000..2880eb766a Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png new file mode 100755 index 0000000000..25a939d7f5 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png new file mode 100755 index 0000000000..82baabde47 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png new file mode 100755 index 0000000000..7d64abb042 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png new file mode 100755 index 0000000000..f0da962c2d Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png new file mode 100755 index 0000000000..0db001dcdb Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png new file mode 100755 index 0000000000..0cf7edc2d4 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png new file mode 100755 index 0000000000..a0c15a6d3e Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index eabcc68916..ce9474d5e5 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -160,7 +160,21 @@ with the same filename but different name <texture name="ComboButton_On" file_name="widgets/ComboButton_On.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> <texture name="ComboButton_Off" file_name="widgets/ComboButton_Off.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> <texture name="ComboButton_UpOff" file_name="widgets/ComboButton_UpOff.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> + <texture name="Container" file_name="containers/Container.png" preload="false" /> + + <texture name="Conv_toolbar_add_person" file_name="icons/Conv_toolbar_add_person.png" preload="false" /> + <texture name="Conv_toolbar_arrow_ne" file_name="icons/Conv_toolbar_arrow_ne.png" preload="false" /> + <texture name="Conv_toolbar_arrow_sw" file_name="icons/Conv_toolbar_arrow_sw.png" preload="false" /> + <texture name="Conv_toolbar_call_log" file_name="icons/Conv_toolbar_call_log.png" preload="false" /> + <texture name="Conv_toolbar_close" file_name="icons/Conv_toolbar_close.png" preload="false" /> + <texture name="Conv_toolbar_collapse" file_name="icons/Conv_toolbar_collapse.png" preload="false" /> + <texture name="Conv_toolbar_expand" file_name="icons/Conv_toolbar_expand.png" preload="false" /> + <texture name="Conv_toolbar_hang_up" file_name="icons/Conv_toolbar_hang_up.png" preload="false" /> + <texture name="Conv_toolbar_open_call" file_name="icons/Conv_toolbar_open_call.png" preload="false" /> + <texture name="Conv_toolbar_plus" file_name="icons/Conv_toolbar_plus.png" preload="false" /> + <texture name="Conv_toolbar_sort" file_name="icons/Conv_toolbar_sort.png" preload="false" /> + <texture name="Copy" file_name="icons/Copy.png" preload="false" /> <texture name="DisclosureArrow_Opened_Off" file_name="widgets/DisclosureArrow_Opened_Off.png" preload="true" /> diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index ce40f44a64..8e434b5848 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -15,10 +15,10 @@ width="680"> <string name="collapse_icon" - value="TabIcon_Open_Off"/> + value="Conv_toolbar_collapse"/> <string name="expand_icon" - value="TabIcon_Close_Off"/> + value="Conv_toolbar_expand"/> <layout_stack animate="true" follows="all" @@ -53,7 +53,7 @@ follows="top|left" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="OptionsMenu_Off" + image_overlay="Conv_toolbar_sort" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" @@ -65,7 +65,7 @@ follows="top|left" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" + image_overlay="Conv_toolbar_plus" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" @@ -84,7 +84,7 @@ follows="right|top" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="TabIcon_Open_Off" + image_overlay="Conv_toolbar_collapse" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 08bc46a506..32eb4ebdae 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -18,20 +18,20 @@ <floater.string name="NearbyChatTitle" value="Nearby Chat"/> - <floater.string name="call_btn_start">VoicePTT_Off</floater.string> - <floater.string name="call_btn_stop">VoicePTT_On</floater.string> + <floater.string name="call_btn_start">Conv_toolbar_open_call</floater.string> + <floater.string name="call_btn_stop">Conv_toolbar_hang_up</floater.string> <floater.string name="collapse_icon" - value="TabIcon_Open_Off"/> + value="Conv_toolbar_collapse"/> <floater.string name="expand_icon" - value="TabIcon_Close_Off"/> + value="Conv_toolbar_expand"/> <floater.string name="tear_off_icon" - value="tearoffbox.tga"/> + value="Conv_toolbar_arrow_ne"/> <floater.string name="return_icon" - value="Icon_Dock_Foreground"/> + value="Conv_toolbar_arrow_sw"/> <view follows="all" layout="topleft" @@ -52,10 +52,10 @@ menu_filename="menu_im_session_showmodes.xml" follows="top|left" height="25" - image_hover_unselected="Toolbar_Left_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Left_Selected" - image_unselected="Toolbar_Left_Off" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_sort" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" layout="topleft" left="5" name="view_options_btn" @@ -66,7 +66,7 @@ follows="top|left" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" + image_overlay="Conv_toolbar_add_person" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" @@ -77,10 +77,10 @@ <button follows="top|left" height="25" - image_hover_unselected="Toolbar_Right_Over" - image_overlay="VoicePTT_Off" - image_selected="Toolbar_Right_Selected" - image_unselected="Toolbar_Right_Off" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_open_call" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" left_pad="4" @@ -90,7 +90,7 @@ follows="right|top" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Icon_Close_Foreground" + image_overlay="Conv_toolbar_close" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" @@ -102,7 +102,7 @@ follows="right|top" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="TabIcon_Open_Off" + image_overlay="Conv_toolbar_collapse" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" @@ -114,7 +114,7 @@ follows="right|top" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="tearoffbox.tga" + image_overlay="Conv_toolbar_arrow_ne" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml index f466504938..24f7d44cce 100644 --- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -49,7 +49,7 @@ follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Inv_Underpants" + image_overlay="Conv_toolbar_sort" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 38a996547c..09156b41b5 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -122,7 +122,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Inv_Underpants" + image_overlay="Conv_toolbar_sort" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" @@ -270,7 +270,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Inv_Underpants" + image_overlay="Conv_toolbar_sort" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" @@ -425,7 +425,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Inv_Underpants" + image_overlay="Conv_toolbar_sort" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" @@ -533,7 +533,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M follows="right" height="25" image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Inv_Underpants" + image_overlay="Conv_toolbar_sort" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" layout="topleft" -- cgit v1.2.3 From 71deb6d500238900bf7bf62cf957a68c063ade56 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 29 Jun 2012 11:59:14 -0700 Subject: CHUI-164 : Fix crash when removing ad-hoc conversation. Turns out that sessions uuids are not constant so I shouldn't use them as index in the conversation list. More complete fix to follow. --- indra/newview/llimconversation.cpp | 2 +- indra/newview/llimfloatercontainer.cpp | 34 ++++++++++++++++++++-------------- indra/newview/llimfloatercontainer.h | 2 +- 3 files changed, 22 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index c734c3edd2..d7ef65edb6 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -359,7 +359,7 @@ void LLIMConversation::onClose(bool app_quitting) LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); if (im_box) { - im_box->removeConversationListItem(mSessionID); + im_box->removeConversationListItem(mSessionID,this); } } } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 34a9758c52..85cc8cf38b 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -416,19 +416,14 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI // Check if the item has changed if (item->hasSameValues(name,floaterp)) { - // If it hasn't, nothing to do -> exit + // If it hasn't changed, nothing to do -> exit return; } - // If it has, remove it: it'll be recreated anew further down - removeConversationListItem(uuid,false); } - // Reverse find and clean up: we need to make sure that no other uuid is pointing to that same floater - LLUUID found_id = LLUUID::null; - if (findConversationItem(floaterp,found_id)) - { - removeConversationListItem(found_id,false); - } + // Remove the conversation item that might exist already: it'll be recreated anew further down anyway + // and nothing wrong will happen removing it if it doesn't exist + removeConversationListItem(uuid,floaterp,false); // Create a conversation item LLConversationItem* item = new LLConversationItem(name, uuid, floaterp, this); @@ -451,21 +446,32 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI return; } -void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id, bool change_focus) +void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id, LLFloater* floaterp, bool change_focus) { + // Reverse find : we need to find the item that point to that floater + // Note : the session UUID actually might change so we cannot really use it here + // *TODO : Change the structure so that we use the floaterp and not the uuid as a map index + LLUUID found_id = LLUUID::null; + if (!findConversationItem(floaterp,found_id)) + { + // If the floater wasn't found, we trust the passed id + // Note: in most cases, the id doesn't correspond to any conversation either + found_id = session_id; + } + // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener - conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(session_id); + conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(found_id); if (widget_it != mConversationsWidgets.end()) { LLFolderViewItem* widget = widget_it->second; delete widget; } - + // Suppress the conversation items and widgets from their respective maps - mConversationsItems.erase(session_id); - mConversationsWidgets.erase(session_id); + mConversationsItems.erase(found_id); + mConversationsWidgets.erase(found_id); // Reposition the leftover conversation items LLRect panel_rect = mConversationsListPanel->getRect(); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 2a8cbf3e1c..181aaa38a8 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -186,7 +186,7 @@ private: // CHUI-137 : Temporary implementation of conversations list public: - void removeConversationListItem(const LLUUID& session_id, bool change_focus = true); + void removeConversationListItem(const LLUUID& session_id, LLFloater* floaterp, bool change_focus = true); void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp); bool findConversationItem(LLFloater* floaterp, LLUUID& uuid); private: -- cgit v1.2.3 From 5eab95955fec4d3dcb8b2f98c6c084d227e70b8c Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 29 Jun 2012 14:29:56 -0700 Subject: CHUI-164 : Fix conversation list index using handle to floater rather than uuid. Simplify the code accordingly (suppress hacks). --- indra/newview/llimconversation.cpp | 2 +- indra/newview/llimfloatercontainer.cpp | 48 +++++++++++++--------------------- indra/newview/llimfloatercontainer.h | 12 ++++----- 3 files changed, 25 insertions(+), 37 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index d7ef65edb6..dc68c5cea1 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -359,7 +359,7 @@ void LLIMConversation::onClose(bool app_quitting) LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); if (im_box) { - im_box->removeConversationListItem(mSessionID,this); + im_box->removeConversationListItem(this); } } } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 85cc8cf38b..261b5f33a2 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -293,9 +293,9 @@ void LLIMFloaterContainer::setVisible(BOOL visible) if (visible) { // Make sure we have the Nearby Chat present when showing the conversation container - LLUUID nearbychat_uuid = LLUUID::null; // Hacky but true: the session id for nearby chat is null - conversations_items_map::iterator item_it = mConversationsItems.find(nearbychat_uuid); - if (item_it == mConversationsItems.end()) + LLUUID nearbychat_uuid = LLUUID::null; // Hacky but true: the session id for nearby chat is always null + LLFloater* floaterp = findConversationItem(nearbychat_uuid); + if (floaterp == NULL) { // If not found, force the creation of the nearby chat conversation panel // *TODO: find a way to move this to XML as a default panel or something like that @@ -407,14 +407,14 @@ void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) // CHUI-137 : Temporary implementation of conversations list void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp) { - // Check if the item is not already in the list, exit if it is and has the same name and points to the same floater (nothing to do) + // Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do) // Note: this happens often, when reattaching a torn off conversation for instance - conversations_items_map::iterator item_it = mConversationsItems.find(uuid); + conversations_items_map::iterator item_it = mConversationsItems.find(floaterp); if (item_it != mConversationsItems.end()) { LLConversationItem* item = item_it->second; // Check if the item has changed - if (item->hasSameValues(name,floaterp)) + if (item->hasSameValues(name,uuid)) { // If it hasn't changed, nothing to do -> exit return; @@ -423,15 +423,15 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI // Remove the conversation item that might exist already: it'll be recreated anew further down anyway // and nothing wrong will happen removing it if it doesn't exist - removeConversationListItem(uuid,floaterp,false); + removeConversationListItem(floaterp,false); // Create a conversation item LLConversationItem* item = new LLConversationItem(name, uuid, floaterp, this); - mConversationsItems[uuid] = item; + mConversationsItems[floaterp] = item; // Create a widget from it LLFolderViewItem* widget = createConversationItemWidget(item); - mConversationsWidgets[uuid] = widget; + mConversationsWidgets[floaterp] = widget; // Add it to the UI widget->setVisible(TRUE); @@ -446,23 +446,12 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI return; } -void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id, LLFloater* floaterp, bool change_focus) +void LLIMFloaterContainer::removeConversationListItem(LLFloater* floaterp, bool change_focus) { - // Reverse find : we need to find the item that point to that floater - // Note : the session UUID actually might change so we cannot really use it here - // *TODO : Change the structure so that we use the floaterp and not the uuid as a map index - LLUUID found_id = LLUUID::null; - if (!findConversationItem(floaterp,found_id)) - { - // If the floater wasn't found, we trust the passed id - // Note: in most cases, the id doesn't correspond to any conversation either - found_id = session_id; - } - // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener - conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(found_id); + conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(floaterp); if (widget_it != mConversationsWidgets.end()) { LLFolderViewItem* widget = widget_it->second; @@ -470,8 +459,8 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id, } // Suppress the conversation items and widgets from their respective maps - mConversationsItems.erase(found_id); - mConversationsWidgets.erase(found_id); + mConversationsItems.erase(floaterp); + mConversationsWidgets.erase(floaterp); // Reposition the leftover conversation items LLRect panel_rect = mConversationsListPanel->getRect(); @@ -500,20 +489,19 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id, return; } -bool LLIMFloaterContainer::findConversationItem(LLFloater* floaterp, LLUUID& uuid) +LLFloater* LLIMFloaterContainer::findConversationItem(LLUUID& uuid) { - bool found = false; + LLFloater* floaterp = NULL; for (conversations_items_map::iterator item_it = mConversationsItems.begin(); item_it != mConversationsItems.end(); ++item_it) { LLConversationItem* item = item_it->second; - uuid = item_it->first; - if (item->hasSameValue(floaterp)) + if (item->hasSameValue(uuid)) { - found = true; + floaterp = item_it->first; break; } } - return found; + return floaterp; } LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 181aaa38a8..2bbd371e8f 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -48,8 +48,8 @@ class LLIMFloaterContainer; // CHUI-137 : Temporary implementation of conversations list class LLConversationItem; -typedef std::map<LLUUID, LLConversationItem*> conversations_items_map; -typedef std::map<LLUUID, LLFolderViewItem*> conversations_widgets_map; +typedef std::map<LLFloater*, LLConversationItem*> conversations_items_map; +typedef std::map<LLFloater*, LLFolderViewItem*> conversations_widgets_map; // Conversation items: we hold a list of those and create an LLFolderViewItem widget for each // that we tuck into the mConversationsListPanel. @@ -113,8 +113,8 @@ public: void* cargo_data, std::string& tooltip_msg) { return FALSE; } - bool hasSameValues(std::string name, LLFloater* floaterp) { return ((name == mName) && (floaterp == mFloater)); } - bool hasSameValue(LLFloater* floaterp) { return (floaterp == mFloater); } + bool hasSameValues(std::string name, const LLUUID& uuid) { return ((name == mName) && (uuid == mUUID)); } + bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } private: std::string mName; const LLUUID mUUID; @@ -186,9 +186,9 @@ private: // CHUI-137 : Temporary implementation of conversations list public: - void removeConversationListItem(const LLUUID& session_id, LLFloater* floaterp, bool change_focus = true); + void removeConversationListItem(LLFloater* floaterp, bool change_focus = true); void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp); - bool findConversationItem(LLFloater* floaterp, LLUUID& uuid); + LLFloater* findConversationItem(LLUUID& uuid); private: LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); // Conversation list data -- cgit v1.2.3 From cd7d499ea779178d49be65d37e852712f82c3c90 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 28 Jun 2012 17:22:00 +0300 Subject: CHUI-168 FIXED, CHUI-183 FIXED Supress of a resizable and dragging and hide a title for the docked floater --- indra/newview/llimconversation.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index dc68c5cea1..acdd7ba46a 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -250,14 +250,16 @@ void LLIMConversation::updateHeaderAndToolbar() bool is_expanded = is_hosted || is_participant_list_visible; mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); - // The button (>>) should be disabled for torn off P2P conversations. - mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat); - + // toggle floater's drag handle and title visibility if (mDragHandle) { - // toggle floater's drag handle and title visibility - mDragHandle->setVisible(!is_hosted); + mDragHandle->setTitleVisible(!is_hosted); + setCanDrag(!is_hosted); } + setCanResize(!is_hosted); + + // The button (>>) should be disabled for torn off P2P conversations. + mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat); mTearOffBtn->setImageOverlay(getString(is_hosted ? "tear_off_icon" : "return_icon")); @@ -347,6 +349,8 @@ void LLIMConversation::onOpen(const LLSD& key) host_floater->collapseMessagesPane(false); } + setCanResize(TRUE); + updateHeaderAndToolbar(); } -- cgit v1.2.3 From ed7173c987cf4a5de2f3c9b9d792e5ac4006e833 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 28 Jun 2012 23:29:58 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose filtering mostly working --- indra/newview/llfolderview.cpp | 124 ++++++++++----------- indra/newview/llfolderviewitem.cpp | 5 +- indra/newview/llinventorybridge.cpp | 47 ++++---- indra/newview/llinventorybridge.h | 3 + indra/newview/llinventorypanel.cpp | 37 ++++-- indra/newview/llinventorypanel.h | 18 ++- indra/newview/llpanelmarketplaceinboxinventory.cpp | 1 + .../newview/llpanelmarketplaceoutboxinventory.cpp | 1 + indra/newview/llplacesinventorybridge.cpp | 5 + indra/newview/llplacesinventorybridge.h | 1 + indra/newview/llplacesinventorypanel.cpp | 1 + 11 files changed, 135 insertions(+), 108 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index a37fc7714b..0f7809d4b4 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -182,7 +182,6 @@ LLFolderView::LLFolderView(const Params& p) mAutoSelectOverride(FALSE), mNeedsAutoRename(FALSE), mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME), // This gets overridden by a pref immediately - mFilter(new LLInventoryFilter(LLInventoryFilter::Params().name(p.title))), mShowSelectionContext(FALSE), mShowSingleSelection(FALSE), mArrangeGeneration(0), @@ -288,9 +287,6 @@ LLFolderView::~LLFolderView( void ) mItems.clear(); mFolders.clear(); - delete mFilter; - mFilter = NULL; - delete mViewModel; mViewModel = NULL; } @@ -302,6 +298,9 @@ BOOL LLFolderView::canFocusChildren() const BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { + LLFolderViewFolder::addFolder(folder); + + mFolders.remove(folder); // enforce sort order of My Inventory followed by Library if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) { @@ -311,12 +310,7 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { mFolders.insert(mFolders.begin(), folder); } - folder->setOrigin(0, 0); - folder->reshape(getRect().getWidth(), 0); - folder->setVisible(FALSE); - addChild( folder ); - folder->getViewModelItem()->dirtyFilter(); - folder->requestArrange(); + return TRUE; } @@ -717,7 +711,7 @@ void LLFolderView::draw() } else if (mShowEmptyMessage) { - if (!mViewModel->contentsReady() || getLastFilterGeneration() < mFilter->getFirstSuccessGeneration()) + if (!mViewModel->contentsReady() || getLastFilterGeneration() < getFolderViewModel()->getFilter()->getFirstSuccessGeneration()) { // TODO RN: Get this from filter mStatusText = LLTrans::getString("Searching"); @@ -952,37 +946,36 @@ void LLFolderView::openSelectedItems( void ) { if(getVisible() && getEnabled()) { - // TODO RN: move to LLFolderViewModelInventory - //if (mSelectedItems.size() == 1) - //{ - // mSelectedItems.front()->openItem(); - //} - //else - //{ - // LLMultiPreview* multi_previewp = new LLMultiPreview(); - // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - // selected_items_t::iterator item_it; - // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - // { - // // IT_{OBJECT,ATTACHMENT} creates LLProperties - // // floaters; others create LLPreviews. Put - // // each one in the right type of container. - // LLFolderViewModelItemInventory* listener = (*item_it)->getViewModelItem(); - // bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); - // if (is_prop) - // LLFloater::setFloaterHost(multi_propertiesp); - // else - // LLFloater::setFloaterHost(multi_previewp); - // (*item_it)->openItem(); - // } - - // LLFloater::setFloaterHost(NULL); - // // *NOTE: LLMulti* will safely auto-delete when open'd - // // without any children. - // multi_previewp->openFloater(LLSD()); - // multi_propertiesp->openFloater(LLSD()); - //} + if (mSelectedItems.size() == 1) + { + mSelectedItems.front()->openItem(); + } + else + { + LLMultiPreview* multi_previewp = new LLMultiPreview(); + LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + // IT_{OBJECT,ATTACHMENT} creates LLProperties + // floaters; others create LLPreviews. Put + // each one in the right type of container. + LLFolderViewModelItemInventory* listener = static_cast<LLFolderViewModelItemInventory*>((*item_it)->getViewModelItem()); + bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); + if (is_prop) + LLFloater::setFloaterHost(multi_propertiesp); + else + LLFloater::setFloaterHost(multi_previewp); + listener->openItem(); + } + + LLFloater::setFloaterHost(NULL); + // *NOTE: LLMulti* will safely auto-delete when open'd + // without any children. + multi_previewp->openFloater(LLSD()); + multi_propertiesp->openFloater(LLSD()); + } } } @@ -990,28 +983,27 @@ void LLFolderView::propertiesSelectedItems( void ) { if(getVisible() && getEnabled()) { - // TODO RN: move to LLFolderViewModelInventory - //if (mSelectedItems.size() == 1) - //{ - // LLFolderViewItem* folder_item = mSelectedItems.front(); - // if(!folder_item) return; - // folder_item->getViewModelItem()->showProperties(); - //} - //else - //{ - // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + if (mSelectedItems.size() == 1) + { + LLFolderViewItem* folder_item = mSelectedItems.front(); + if(!folder_item) return; + folder_item->getViewModelItem()->showProperties(); + } + else + { + LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - // LLFloater::setFloaterHost(multi_propertiesp); + LLFloater::setFloaterHost(multi_propertiesp); - // selected_items_t::iterator item_it; - // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - // { - // (*item_it)->getViewModelItem()->showProperties(); - // } + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + (*item_it)->getViewModelItem()->showProperties(); + } - // LLFloater::setFloaterHost(NULL); - // multi_propertiesp->openFloater(LLSD()); - //} + LLFloater::setFloaterHost(NULL); + multi_propertiesp->openFloater(LLSD()); + } } } @@ -1943,11 +1935,11 @@ void LLFolderView::doIdle() LLFastTimer t2(FTM_INVENTORY); - if (mFilter->isModified() && mFilter->isNotDefault()) + if (getFolderViewModel()->getFilter()->isModified() && getFolderViewModel()->getFilter()->isNotDefault()) { mNeedsAutoSelect = TRUE; } - mFilter->clearModified(); + getFolderViewModel()->getFilter()->clearModified(); // filter to determine visibility before arranging filter(*(getFolderViewModel()->getFilter())); @@ -1958,7 +1950,7 @@ void LLFolderView::doIdle() LLFastTimer t3(FTM_AUTO_SELECT); // select new item only if a filtered item not currently selected LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); - if (!mAutoSelectOverride && (!selected_itemp || selected_itemp->passedFilter())) + if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->getViewModelItem()->potentiallyVisible())) { // these are named variables to get around gcc not binding non-const references to rvalues // and functor application is inherently non-const to allow for stateful functors @@ -1968,7 +1960,7 @@ void LLFolderView::doIdle() // Open filtered folders for folder views with mAutoSelectOverride=TRUE. // Used by LLPlacesFolderView. - if (mFilter->showAllResults()) + if (getFolderViewModel()->getFilter()->showAllResults()) { // these are named variables to get around gcc not binding non-const references to rvalues // and functor application is inherently non-const to allow for stateful functors @@ -1979,7 +1971,7 @@ void LLFolderView::doIdle() scrollToShowSelection(); } - BOOL filter_finished = getLastFilterGeneration() >= mFilter->getCurrentGeneration() + BOOL filter_finished = getLastFilterGeneration() >= getFolderViewModel()->getFilter()->getCurrentGeneration() && mViewModel->contentsReady(); if (filter_finished || gFocusMgr.childHasKeyboardFocus(inventory_panel) diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index f65a13be1e..685a4cbf49 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -123,7 +123,10 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mListener(p.listener), mIsMouseOverTitle(false) { - mListener->setFolderViewItem(this); + if (mListener) + { + mListener->setFolderViewItem(this); + } } BOOL LLFolderViewItem::postBuild() diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 45a2bffa6b..002278601a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1026,6 +1026,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags) @@ -1151,12 +1152,13 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, default: llinfos << "Unhandled asset type (llassetstorage.h): " << (S32)asset_type << " (" << LLAssetType::lookup(asset_type) << ")" << llendl; - break; + break; } if (new_listener) { new_listener->mInvType = inv_type; + new_listener->setRootViewModel(view_model); } return new_listener; @@ -1332,6 +1334,7 @@ LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags /* = 0x00 */) const @@ -1340,6 +1343,7 @@ LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset actual_asset_type, inv_type, inventory, + view_model, root, uuid, flags); @@ -6472,41 +6476,30 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags /*= 0x00*/ ) const { LLInvFVBridge* new_listener = NULL; - switch(asset_type) + if (asset_type == LLAssetType::AT_CATEGORY + && actual_asset_type != LLAssetType::AT_LINK_FOLDER) { - case LLAssetType::AT_CATEGORY: - if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) - { - // *TODO: Create a link folder handler instead if it is necessary - new_listener = LLInventoryFVBridgeBuilder::createBridge( - asset_type, - actual_asset_type, - inv_type, - inventory, - root, - uuid, - flags); - break; - } new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid); - break; - default: - new_listener = LLInventoryFVBridgeBuilder::createBridge( - asset_type, - actual_asset_type, - inv_type, - inventory, - root, - uuid, - flags); + new_listener->setRootViewModel(view_model); + } + else + { + new_listener = LLInventoryFVBridgeBuilder::createBridge(asset_type, + actual_asset_type, + inv_type, + inventory, + view_model, + root, + uuid, + flags); } return new_listener; - } // EOF diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index b0582d003d..e235d9cf5f 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -66,6 +66,7 @@ public: LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags = 0x00); @@ -196,6 +197,7 @@ public: LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags = 0x00) const; @@ -645,6 +647,7 @@ public: LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags = 0x00) const; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index aba4c088ab..73e20fc684 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -234,6 +234,7 @@ void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) LLAssetType::AT_CATEGORY, LLInventoryType::IT_CATEGORY, this, + &mInventoryViewModel, NULL, root_id); @@ -672,7 +673,7 @@ LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool u p.parent_panel = this; p.tool_tip = p.name; p.listener = bridge; - p.view_model = new LLFolderViewModelInventory(); + p.view_model = &mInventoryViewModel; p.use_label_suffix = useLabelSuffix; p.allow_multiselect = mAllowMultiSelect; p.show_empty_message = mShowEmptyMessage; @@ -736,6 +737,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) objectp->getType(), LLInventoryType::IT_CATEGORY, this, + &mInventoryViewModel, mFolderRoot, objectp->getUUID()); if (new_listener) @@ -751,6 +753,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) item->getActualType(), item->getInventoryType(), this, + &mInventoryViewModel, mFolderRoot, item->getUUID(), item->getFlags()); @@ -1130,7 +1133,6 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open) if (!floater_inventory) { llwarns << "Could not find My Inventory floater" << llendl; - return FALSE; } @@ -1347,25 +1349,27 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params) void LLFolderViewModelItemInventory::requestSort() { LLFolderViewModelItemCommon::requestSort(); - //TODO RN: need better way to get to root viewmodel, also consider reflecting hierarchy in viewmodel space as well - if (static_cast<LLFolderViewModelInventory*>(mFolderViewItem->getRoot()->getFolderViewModel())->getSorter().isByDate()) + if (mRootViewModel->getSorter().isByDate()) { // sort by date potentially affects parent folders which use a date // derived from newest item in them - mFolderViewItem->getParentFolder()->getViewModelItem()->requestSort(); + if (mParent) + { + mParent->requestSort(); + } } } bool LLFolderViewModelItemInventory::potentiallyVisible() { return passedFilter() // we've passed the filter - || getLastFilterGeneration() < mFolderViewItem->getRoot()->getFolderViewModel()->getFilter()->getFirstSuccessGeneration() // or we don't know yet + || getLastFilterGeneration() < mRootViewModel->getFilter()->getFirstSuccessGeneration() // or we don't know yet || descendantsPassedFilter(); } bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) { - if (filter_generation < 0) filter_generation = mFolderViewItem->getRoot()->getFolderViewModel()->getFilter()->getFirstSuccessGeneration(); + if (filter_generation < 0) filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); return mPassedFolderFilter && mLastFilterGeneration >= filter_generation && (mPassedFilter || descendantsPassedFilter(filter_generation)); @@ -1373,7 +1377,7 @@ bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) { - if (filter_generation < 0) filter_generation = mFolderViewItem->getRoot()->getFolderViewModel()->getFilter()->getFirstSuccessGeneration(); + if (filter_generation < 0) filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); return mMostFilteredDescendantGeneration >= filter_generation; } @@ -1419,8 +1423,9 @@ void LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) { - if(getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass - || descendantsPassedFilter(filter.getFirstRequiredGeneration())) // or at least one descendant has passed the minimum requirement + if(!mChildren.empty() + && (getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass + || descendantsPassedFilter(filter.getFirstRequiredGeneration()))) // or at least one descendant has passed the minimum requirement { // now query children for (child_list_t::iterator iter = mChildren.begin(); @@ -1456,3 +1461,15 @@ void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) filter.decrementFilterCount(); } } + +LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() +{ + return &mInventoryViewModel; +} + + +const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const +{ + return &mInventoryViewModel; +} + diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 35a3f9b5e1..55edf386d5 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -42,11 +42,19 @@ class LLInvFVBridge; class LLInventoryFVBridgeBuilder; class LLInvPanelComplObserver; +class LLFolderViewModelInventory; class LLFolderViewModelItemInventory : public LLFolderViewModelItemCommon { public: + LLFolderViewModelItemInventory() + : mRootViewModel(NULL) + {} + void setRootViewModel(LLFolderViewModelInventory* root_view_model) + { + mRootViewModel = root_view_model; + } virtual const LLUUID& getUUID() const = 0; virtual time_t getCreationDate() const = 0; // UTC seconds virtual void setCreationDate(time_t creation_date_utc) = 0; @@ -68,6 +76,8 @@ public: virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); virtual void filter( LLFolderViewFilter& filter); virtual void filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); +protected: + LLFolderViewModelInventory* mRootViewModel; }; class LLInventorySort @@ -243,8 +253,8 @@ public: void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); void updateSelection(); - LLFolderViewModelInventory* getFolderViewModel() { return &mViewModel; } - const LLFolderViewModelInventory* getFolderViewModel() const { return &mViewModel; } + LLFolderViewModelInventory* getFolderViewModel(); + const LLFolderViewModelInventory* getFolderViewModel() const; protected: void openStartFolderOrMyInventory(); // open the first level of inventory @@ -262,8 +272,8 @@ protected: LLFolderView* mFolderRoot; LLScrollContainer* mScroller; - LLFolderViewModelInventory mViewModel; - + LLFolderViewModelInventory mInventoryViewModel; + std::map<LLUUID, LLFolderViewItem*> mItemMap; /** * Pointer to LLInventoryFVBridgeBuilder. diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index f3096e862d..6e5a522297 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -111,6 +111,7 @@ void LLInboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& para LLAssetType::AT_CATEGORY, LLInventoryType::IT_CATEGORY, this, + &mInventoryViewModel, NULL, root_id); diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp index 783eeb11b8..2885dd6266 100644 --- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceoutboxinventory.cpp @@ -77,6 +77,7 @@ void LLOutboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& par LLAssetType::AT_CATEGORY, LLInventoryType::IT_CATEGORY, this, + &mInventoryViewModel, NULL, root_id); diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index 97c5d531d2..af29ab7ea9 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -151,6 +151,7 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags/* = 0x00*/) const @@ -164,6 +165,7 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; } new_listener = new LLPlacesLandmarkBridge(inv_type, inventory, root, uuid, flags); + new_listener->setRootViewModel(view_model); break; case LLAssetType::AT_CATEGORY: if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) @@ -174,12 +176,14 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( actual_asset_type, inv_type, inventory, + view_model, root, uuid, flags); break; } new_listener = new LLPlacesFolderBridge(inv_type, inventory, root, uuid); + new_listener->setRootViewModel(view_model); break; default: new_listener = LLInventoryFVBridgeBuilder::createBridge( @@ -187,6 +191,7 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( actual_asset_type, inv_type, inventory, + view_model, root, uuid, flags); diff --git a/indra/newview/llplacesinventorybridge.h b/indra/newview/llplacesinventorybridge.h index 52beacef9c..791502990b 100644 --- a/indra/newview/llplacesinventorybridge.h +++ b/indra/newview/llplacesinventorybridge.h @@ -89,6 +89,7 @@ public: LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags = 0x00) const; diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index 1c2d75d88c..d95d5eac19 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -87,6 +87,7 @@ void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& par LLAssetType::AT_CATEGORY, LLInventoryType::IT_CATEGORY, this, + &mInventoryViewModel, NULL, root_id); p.parent_panel = this; -- cgit v1.2.3 From 604bbb22783d2460384e340592ca1781908f6dd8 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 28 Jun 2012 23:30:36 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose cleaned up ownership of viewmodel more filtering fixes --- indra/newview/llfolderview.h | 1 - indra/newview/llfolderviewitem.h | 1 - indra/newview/llinventoryfilter.cpp | 17 +++++++---------- indra/newview/llpanelmaininventory.cpp | 24 ++++++++++++------------ indra/newview/llpanelobjectinventory.cpp | 2 +- indra/newview/llpanelobjectinventory.h | 2 ++ 6 files changed, 22 insertions(+), 25 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index d261a5967d..8a0317f840 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -302,7 +302,6 @@ protected: LLFrameTimer mAutoOpenTimer; LLFrameTimer mSearchTimer; std::string mSearchString; - LLFolderViewFilter* mFilter; BOOL mShowSelectionContext; BOOL mShowSingleSelection; LLFrameTimer mMultiSelectionFadeTimer; diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 7e48969826..a3c92a55e8 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -281,7 +281,6 @@ protected: S32 mLastCalculatedWidth; S32 mMostFilteredDescendantGeneration; bool mNeedsSort; - bool mPassedFolderFilter; public: typedef enum e_recurse_type diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index c7e0136368..08f1e541b5 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -95,16 +95,13 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item) return passed_clipboard; } - std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos; + std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : 0; - const BOOL passed_filtertype = checkAgainstFilterType(listener); - const BOOL passed_permissions = checkAgainstPermissions(listener); - const BOOL passed_filterlink = checkAgainstFilterLinks(listener); - const BOOL passed = (passed_filtertype && - passed_permissions && - passed_filterlink && - passed_clipboard && - (mFilterSubString.size() == 0 || string_offset != std::string::npos)); + BOOL passed = string_offset != std::string::npos; + passed = passed && checkAgainstFilterType(listener); + passed = passed && checkAgainstPermissions(listener); + passed = passed && checkAgainstFilterLinks(listener); + passed = passed && passed_clipboard; return passed; } @@ -595,7 +592,7 @@ void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date) void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl) { - static LLCachedControl<U32> s_last_logoff(gSavedSettings, "LastLogoff", 0); + static LLCachedControl<U32> s_last_logoff(gSavedPerAccountSettings, "LastLogoff", 0); if (sl && !isSinceLogoff()) { setDateRange(s_last_logoff(), time_max()); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 33581160fd..6cef1f877b 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -222,21 +222,21 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) if (p.validateBlock(false)) { LLParamSDParser().writeSD(filterState, p); - filterRoot[filter->getName()] = filterState; + filterRoot[filter->getName()] = filterState; + } } } - } - LLInventoryFilter* filter = findChild<LLInventoryPanel>("Recent Items")->getFilter(); - if (filter) - { - LLSD filterState; - LLInventoryFilter::Params p; - filter->toParams(p); - LLParamSDParser parser; - parser.writeSD(filterState, p); - filterRoot[filter->getName()] = filterState; - } + LLInventoryFilter* filter = findChild<LLInventoryPanel>("Recent Items")->getFilter(); + if (filter) + { + LLSD filterState; + LLInventoryFilter::Params p; + filter->toParams(p); + LLParamSDParser parser; + parser.writeSD(filterState, p); + filterRoot[filter->getName()] = filterState; + } std::ostringstream filterSaveName; filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 6a232a26f7..d0b9072ade 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1562,7 +1562,7 @@ void LLPanelObjectInventory::reset() p.tool_tip= LLTrans::getString("PanelContentsTooltip"); p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL); p.folder_indentation = -14; // subtract space normally reserved for folder expanders - p.view_model = new LLFolderViewModelInventory(); + p.view_model = &mInventoryViewModel; mFolders = LLUICtrlFactory::create<LLFolderView>(p); // this ensures that we never say "searching..." or "no items found" //TODO RN: make this happen by manipulating filter object directly diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 607b705f7f..7e857f8b31 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -29,6 +29,7 @@ #include "llvoinventorylistener.h" #include "llpanel.h" +#include "llinventorypanel.h" // for LLFolderViewModelInventory #include "llinventory.h" @@ -94,6 +95,7 @@ private: BOOL mHaveInventory; BOOL mIsInventoryEmpty; BOOL mInventoryNeedsUpdate; + LLFolderViewModelInventory mInventoryViewModel; }; #endif // LL_LLPANELOBJECTINVENTORY_H -- cgit v1.2.3 From 07afce2ac86c4c66e8b094ecf977ee5ec5566671 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 29 Jun 2012 09:44:22 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose fixed build --- indra/newview/llfolderview.cpp | 48 +++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 0f7809d4b4..e007c58497 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -981,30 +981,30 @@ void LLFolderView::openSelectedItems( void ) void LLFolderView::propertiesSelectedItems( void ) { - if(getVisible() && getEnabled()) - { - if (mSelectedItems.size() == 1) - { - LLFolderViewItem* folder_item = mSelectedItems.front(); - if(!folder_item) return; - folder_item->getViewModelItem()->showProperties(); - } - else - { - LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - LLFloater::setFloaterHost(multi_propertiesp); - - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - (*item_it)->getViewModelItem()->showProperties(); - } - - LLFloater::setFloaterHost(NULL); - multi_propertiesp->openFloater(LLSD()); - } - } + //if(getVisible() && getEnabled()) + //{ + // if (mSelectedItems.size() == 1) + // { + // LLFolderViewItem* folder_item = mSelectedItems.front(); + // if(!folder_item) return; + // folder_item->getViewModelItem()->showProperties(); + // } + // else + // { + // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + + // LLFloater::setFloaterHost(multi_propertiesp); + + // selected_items_t::iterator item_it; + // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + // { + // (*item_it)->getViewModelItem()->showProperties(); + // } + + // LLFloater::setFloaterHost(NULL); + // multi_propertiesp->openFloater(LLSD()); + // } + //} } void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type) -- cgit v1.2.3 From 062cae9a4880f7672df7f6189e01b2bff15f42f1 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 29 Jun 2012 15:44:08 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose cleaned up some stale TODOs worked on getting initial inventory display to work consistently --- indra/newview/llfolderview.cpp | 2 +- indra/newview/llfolderviewmodel.h | 13 +++--------- indra/newview/llinventoryfilter.cpp | 3 +-- indra/newview/llinventorypanel.cpp | 34 ++++++++++++++++++++++++-------- indra/newview/llinventorypanel.h | 4 ++-- indra/newview/llpanelobjectinventory.cpp | 2 +- indra/newview/lltexturectrl.cpp | 2 +- 7 files changed, 35 insertions(+), 25 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index e007c58497..5844c58e09 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -713,7 +713,6 @@ void LLFolderView::draw() { if (!mViewModel->contentsReady() || getLastFilterGeneration() < getFolderViewModel()->getFilter()->getFirstSuccessGeneration()) { - // TODO RN: Get this from filter mStatusText = LLTrans::getString("Searching"); } else @@ -981,6 +980,7 @@ void LLFolderView::openSelectedItems( void ) void LLFolderView::propertiesSelectedItems( void ) { + //TODO RN: get working again //if(getVisible() && getEnabled()) //{ // if (mSelectedItems.size() == 1) diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index c5079712f5..5304613219 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -122,7 +122,6 @@ public: virtual void requestSortAll() = 0; virtual void sort(class LLFolderViewFolder*) = 0; - virtual void filter(class LLFolderViewFolder*) = 0; virtual bool contentsReady() = 0; virtual void setFolderView(LLFolderView* folder_view) = 0; @@ -208,12 +207,6 @@ public: } } - //TODO RN: fix this - void filter(LLFolderViewFolder* folder) - { - - } - protected: SortType mSorter; FilterType mFilter; @@ -264,7 +257,7 @@ public: virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? - virtual void filter( LLFolderViewFilter& filter) = 0; + virtual bool filter( LLFolderViewFilter& filter) = 0; virtual bool passedFilter(S32 filter_generation = -1) = 0; virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) = 0; @@ -306,8 +299,8 @@ class LLFolderViewModelItemCommon : public LLFolderViewModelItem public: LLFolderViewModelItemCommon() : mSortVersion(-1), - mPassedFilter(false), - mPassedFolderFilter(false), + mPassedFilter(true), + mPassedFolderFilter(true), mFolderViewItem(NULL), mLastFilterGeneration(-1), mMostFilteredDescendantGeneration(-1), diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 08f1e541b5..6a33130322 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -159,7 +159,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const // (e.g. versus in-world object contents). const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id); if (!cat) - return false; + return folder_id.isNull(); LLFolderType::EType cat_type = cat->getPreferredType(); if (cat_type != LLFolderType::FT_NONE && (1LL << cat_type & mFilterOps.mFilterCategoryTypes) == U64(0)) return false; @@ -1091,7 +1091,6 @@ void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) mEmptyLookupMessage = message; } -// TODO RN: turn this into a param and move to llfolderviewmodelinterface std::string LLInventoryFilter::getEmptyLookupMessage() const { LLStringUtil::format_map_t args; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 73e20fc684..e4cabcc988 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1388,10 +1388,12 @@ void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_fo mLastFilterGeneration = filter_generation; } -void LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) +bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) { + bool passed_filter_before = item->passedFilter(); S32 filter_generation = filter.getCurrentGeneration(); S32 must_pass_generation = filter.getFirstRequiredGeneration(); + bool changed = false; // mMostFilteredDescendantGeneration might have been reset // in which case we need to update it even for folders that @@ -1407,22 +1409,37 @@ void LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite } else { - //TODO RN: - item->filter( filter ); + changed |= item->filter( filter ); } } // track latest generation to pass any child items if (item->passedFilter()) { - mMostFilteredDescendantGeneration = filter_generation; - //TODO RN: ensure this still happens - //requestArrange(); + LLFolderViewModelItemInventory* view_model = this; + + while(view_model && view_model->mMostFilteredDescendantGeneration < filter_generation) + { + view_model->mMostFilteredDescendantGeneration = filter_generation; + view_model = static_cast<LLFolderViewModelItemInventory*>(view_model->mParent); + } + } + + changed |= (item->passedFilter() != passed_filter_before); + if (changed) + { + //TODO RN: ensure this still happens, but without dependency on folderview + LLFolderViewFolder* parent = mFolderViewItem->getParentFolder(); + if (parent) parent->requestArrange(); } + + return changed; } -void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) +bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) { + bool changed = false; + if(!mChildren.empty() && (getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass || descendantsPassedFilter(filter.getFirstRequiredGeneration()))) // or at least one descendant has passed the minimum requirement @@ -1432,7 +1449,7 @@ void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) iter != mChildren.end() && filter.getFilterCount() > 0; ++iter) { - filterChildItem((*iter), filter); + changed |= filterChildItem((*iter), filter); } } @@ -1460,6 +1477,7 @@ void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) //mStringMatchOffset = filter.getStringMatchOffset(this); filter.decrementFilterCount(); } + return changed; } LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 55edf386d5..3195d9a369 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -74,8 +74,8 @@ public: virtual bool passedFilter(S32 filter_generation = -1); virtual bool descendantsPassedFilter(S32 filter_generation = -1); virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); - virtual void filter( LLFolderViewFilter& filter); - virtual void filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); + virtual bool filter( LLFolderViewFilter& filter); + virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); protected: LLFolderViewModelInventory* mRootViewModel; }; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index d0b9072ade..450e1f7ed0 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1566,7 +1566,7 @@ void LLPanelObjectInventory::reset() mFolders = LLUICtrlFactory::create<LLFolderView>(p); // this ensures that we never say "searching..." or "no items found" //TODO RN: make this happen by manipulating filter object directly - //mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + static_cast<LLInventoryFilter*>(mFolders->getFolderViewModel()->getFilter())->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); if (hasFocus()) diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 654b18614a..61a0331b72 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -637,7 +637,7 @@ void LLFloaterTexturePicker::draw() { folder_view->setPinningSelectedItem(mSelectedItemPinned); folder_view->getViewModelItem()->dirtyFilter(); - //TODO RN: test + //TODO RN: test..still works without this? //folder_view->arrangeFromRoot(); mSelectedItemPinned = TRUE; -- cgit v1.2.3 From 38eb726ca8ecbc52f9afe2181474074a8bc59211 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 2 Jul 2012 15:27:19 +0300 Subject: CHUI-103 FIXED (Implement changes to compact chat view) Change coloration --- indra/newview/llchathistory.cpp | 47 ++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index dcd6d25888..80be753d9e 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -734,17 +734,23 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } LLColor4 txt_color = LLUIColorTable::instance().getColor("White"); + LLColor4 name_color(txt_color); + LLViewerChat::getChatColor(chat,txt_color); LLFontGL* fontp = LLViewerChat::getChatFont(); std::string font_name = LLFontGL::nameFromFont(fontp); std::string font_size = LLFontGL::sizeFromFont(fontp); - LLStyle::Params style_params; - style_params.color(txt_color); - style_params.readonly_color(txt_color); - style_params.font.name(font_name); - style_params.font.size(font_size); - style_params.font.style(input_append_params.font.style); + LLStyle::Params body_message_params; + body_message_params.color(txt_color); + body_message_params.readonly_color(txt_color); + body_message_params.font.name(font_name); + body_message_params.font.size(font_size); + body_message_params.font.style(input_append_params.font.style); + + LLStyle::Params name_params(body_message_params); + name_params.color(name_color); + name_params.readonly_color(name_color); std::string prefix = chat.mText.substr(0, 4); @@ -767,7 +773,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (irc_me || chat.mChatStyle == CHAT_STYLE_IRC) { delimiter = LLStringUtil::null; - style_params.font.style = "ITALIC"; + name_params.font.style = "ITALIC"; } bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY; @@ -775,18 +781,20 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (message_from_log) { txt_color = LLColor4::grey; - style_params.color(txt_color); - style_params.readonly_color(txt_color); + body_message_params.color(txt_color); + body_message_params.readonly_color(txt_color); + name_params.color(txt_color); + name_params.readonly_color(txt_color); } bool prependNewLineState = mEditor->getText().size() != 0; - // show timestamps and names in the compact mode + // compact mode: show a timestamp and name if (use_plain_text_chat_history) { square_brackets = chat.mFromName == SYSTEM_FROM; - LLStyle::Params timestamp_style(style_params); + LLStyle::Params timestamp_style(body_message_params); // out of the timestamp if (args["show_time"].asBoolean()) @@ -804,7 +812,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL // out the opening square bracket (if need) if (square_brackets) { - mEditor->appendText("[", prependNewLineState, style_params); + mEditor->appendText("[", prependNewLineState, body_message_params); prependNewLineState = false; } @@ -819,7 +827,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL // set the link for the object name to be the objectim SLapp // (don't let object names with hyperlinks override our objectim Url) - LLStyle::Params link_params(style_params); + LLStyle::Params link_params(body_message_params); LLColor4 link_color = LLUIColorTable::instance().getColor("HTMLLinkColor"); link_params.color = link_color; link_params.readonly_color = link_color; @@ -831,7 +839,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log) { - LLStyle::Params link_params(style_params); + LLStyle::Params link_params(body_message_params); link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); if (from_me) @@ -852,7 +860,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL else { mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, - prependNewLineState, style_params); + prependNewLineState, body_message_params); prependNewLineState = false; } } @@ -880,7 +888,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } else { - view = getHeader(chat, style_params, args); + view = getHeader(chat, name_params, args); if (mEditor->getText().size() == 0) p.top_pad = 0; else @@ -909,6 +917,9 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL mIsLastMessageFromLog = message_from_log; } + // body of the message processing + + // notify processing if (chat.mNotifId.notNull()) { LLNotificationPtr notification = LLNotificationsUtil::find(chat.mNotifId); @@ -932,6 +943,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL mEditor->appendWidget(params, "\n", false); } } + + // usual messages showing else { std::string message = irc_me ? chat.mText.substr(3) : chat.mText; @@ -959,7 +972,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL message += "]"; } - mEditor->appendText(message, prependNewLineState, style_params); + mEditor->appendText(message, prependNewLineState, body_message_params); prependNewLineState = false; } -- cgit v1.2.3 From f22e5df8b6890aab659916361d42479ca3825be9 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Mon, 2 Jul 2012 17:46:34 +0300 Subject: CHUI-172 WIP Fixed drawing the nearby chat toast contents. Fixed warnings when creating a nearby chat toast. --- indra/newview/llchatitemscontainerctrl.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 477bdb3967..61772b4bb7 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -96,8 +96,15 @@ void LLNearbyChatToastPanel::reshape (S32 width, S32 height, BOOL called_from_p { LLPanel::reshape(width, height,called_from_parent); - LLUICtrl* msg_text = getChild<LLUICtrl>("msg_text", false); - LLUICtrl* icon = getChild<LLUICtrl>("avatar_icon", false); + // reshape() may be called from LLView::initFromParams() before the children are created. + // We call findChild() instead of getChild() here to avoid creating dummy controls. + LLUICtrl* msg_text = findChild<LLUICtrl>("msg_text", false); + LLUICtrl* icon = findChild<LLUICtrl>("avatar_icon", false); + + if (!msg_text || !icon) + { + return; + } LLRect msg_text_rect = msg_text->getRect(); LLRect avatar_rect = icon->getRect(); @@ -355,6 +362,8 @@ BOOL LLNearbyChatToastPanel::handleRightMouseDown(S32 x, S32 y, MASK mask) } void LLNearbyChatToastPanel::draw() { + LLPanel::draw(); + if(mIsDirty) { LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon", false); -- cgit v1.2.3 From 1bd52dfbdc3607bbd9ea86c715ce63b17d5a557f Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Mon, 2 Jul 2012 17:57:29 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose refactored source files, moving logic into llfolderviewmodel*.cpp filter logic tweaks purging and moving inventory now properly cleans up view model --- indra/newview/CMakeLists.txt | 3 + indra/newview/llfolderview.cpp | 27 +--- indra/newview/llfolderviewitem.cpp | 19 +-- indra/newview/llfolderviewitem.h | 10 +- indra/newview/llfolderviewmodel.cpp | 54 +++++++ indra/newview/llfolderviewmodel.h | 25 ++- indra/newview/llfolderviewmodelinventory.cpp | 225 +++++++++++++++++++++++++++ indra/newview/llfolderviewmodelinventory.h | 107 +++++++++++++ indra/newview/llinventoryfilter.cpp | 24 --- indra/newview/llinventorypanel.cpp | 201 +----------------------- indra/newview/llinventorypanel.h | 78 +--------- indra/newview/lltexturectrl.cpp | 4 +- 12 files changed, 429 insertions(+), 348 deletions(-) create mode 100644 indra/newview/llfolderviewmodel.cpp create mode 100644 indra/newview/llfolderviewmodelinventory.cpp create mode 100644 indra/newview/llfolderviewmodelinventory.h (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 4f447fd35b..dee37bd5e8 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -253,6 +253,8 @@ set(viewer_SOURCE_FILES llfloaterworldmap.cpp llfolderview.cpp llfolderviewitem.cpp + llfolderviewmodel.cpp + llfolderviewmodelinventory.cpp llfollowcam.cpp llfriendcard.cpp llgesturelistener.cpp @@ -809,6 +811,7 @@ set(viewer_HEADER_FILES llfloaterworldmap.h llfolderview.h llfolderviewmodel.h + llfolderviewmodelinventory.h llfolderviewitem.h llfollowcam.h llfriendcard.h diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 5844c58e09..90c78d98b0 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -259,7 +259,7 @@ LLFolderView::LLFolderView(const Params& p) menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); mPopupMenuHandle = menu->getHandle(); - mListener->openItem(); + mViewModelItem->openItem(); } // Destroys the object @@ -363,11 +363,7 @@ void LLFolderView::filter( LLFolderViewFilter& filter ) LLFastTimer t2(FTM_FILTER); filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); - if (getLastFilterGeneration() < filter.getCurrentGeneration()) - { - mMinWidth = 0; - getViewModelItem()->filter(filter); - } + getViewModelItem()->filter(filter); } void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) @@ -706,20 +702,11 @@ void LLFolderView::draw() if (hasVisibleChildren()) { - mStatusText.clear(); mStatusTextBox->setVisible( FALSE ); } else if (mShowEmptyMessage) { - if (!mViewModel->contentsReady() || getLastFilterGeneration() < getFolderViewModel()->getFilter()->getFirstSuccessGeneration()) - { - mStatusText = LLTrans::getString("Searching"); - } - else - { - mStatusText = getFolderViewModel()->getFilter()->getEmptyLookupMessage(); - } - mStatusTextBox->setValue(mStatusText); + mStatusTextBox->setValue(getFolderViewModel()->getStatusText()); mStatusTextBox->setVisible( TRUE ); // firstly reshape message textbox with current size. This is necessary to @@ -1971,7 +1958,7 @@ void LLFolderView::doIdle() scrollToShowSelection(); } - BOOL filter_finished = getLastFilterGeneration() >= getFolderViewModel()->getFilter()->getCurrentGeneration() + BOOL filter_finished = getViewModelItem()->passedFilter() && mViewModel->contentsReady(); if (filter_finished || gFocusMgr.childHasKeyboardFocus(inventory_panel) @@ -2264,9 +2251,3 @@ S32 LLFolderView::getItemHeight() } return 0; } - -//TODO RN: move to llfolderviewmodel.cpp file -bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) -{ - return item->getSortVersion() < mTargetSortVersion; -} diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 685a4cbf49..ac389c9189 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -120,12 +120,12 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mDragAndDropTarget(FALSE), mLabel(p.name), mRoot(p.root), - mListener(p.listener), + mViewModelItem(p.listener), mIsMouseOverTitle(false) { - if (mListener) + if (mViewModelItem) { - mListener->setFolderViewItem(this); + mViewModelItem->setFolderViewItem(this); } } @@ -138,8 +138,8 @@ BOOL LLFolderViewItem::postBuild() // Destroys the object LLFolderViewItem::~LLFolderViewItem( void ) { - delete mListener; - mListener = NULL; + delete mViewModelItem; + mViewModelItem = NULL; } LLFolderView* LLFolderViewItem::getRoot() @@ -837,12 +837,6 @@ LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) return getRoot()->getFolderViewModel(); } -S32 LLFolderViewItem::getLastFilterGeneration() const -{ - return getViewModelItem()->getLastFilterGeneration(); -} - - ///---------------------------------------------------------------------------- /// Class LLFolderViewFolder @@ -1446,6 +1440,7 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) mItems.erase(it); } //item has been removed, need to update filter + getViewModelItem()->removeChild(item->getViewModelItem()); getViewModelItem()->dirtyFilter(); //because an item is going away regardless of filter status, force rearrange requestArrange(); @@ -1638,7 +1633,7 @@ BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = mListener->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); + BOOL accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); if (accepted) { mDragAndDropTarget = TRUE; diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index a3c92a55e8..581ec7239e 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -92,13 +92,12 @@ protected: S32 mLabelWidth; bool mLabelWidthDirty; LLFolderViewFolder* mParentFolder; - LLFolderViewModelItem* mListener; + LLFolderViewModelItem* mViewModelItem; BOOL mIsCurSelection; BOOL mSelectPending; LLFontGL::StyleFlags mLabelStyle; std::string mLabelSuffix; LLUIImagePtr mIcon; - std::string mStatusText; LLUIImagePtr mIconOpen; LLUIImagePtr mIconOverlay; BOOL mHasVisibleChildren; @@ -136,9 +135,6 @@ public: virtual S32 arrange( S32* width, S32* height ); virtual S32 getItemHeight(); - // updates filter serial number and optionally propagated value up to root - S32 getLastFilterGeneration() const; - // If 'selection' is 'this' then note that otherwise ignore. // Returns TRUE if this item ends up being selected. virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); @@ -202,8 +198,8 @@ public: LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); - const LLFolderViewModelItem* getViewModelItem( void ) const { return mListener; } - LLFolderViewModelItem* getViewModelItem( void ) { return mListener; } + const LLFolderViewModelItem* getViewModelItem( void ) const { return mViewModelItem; } + LLFolderViewModelItem* getViewModelItem( void ) { return mViewModelItem; } const LLFolderViewModelInterface* getFolderViewModel( void ) const; LLFolderViewModelInterface* getFolderViewModel( void ); diff --git a/indra/newview/llfolderviewmodel.cpp b/indra/newview/llfolderviewmodel.cpp new file mode 100644 index 0000000000..92db84156e --- /dev/null +++ b/indra/newview/llfolderviewmodel.cpp @@ -0,0 +1,54 @@ +/** + * @file llfolderviewmodel.cpp + * @brief Implementation of the view model collection of classes. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfolderviewmodel.h" +#include "lltrans.h" +#include "llviewercontrol.h" + +bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) +{ + return item->getSortVersion() < mTargetSortVersion; +} + +std::string LLFolderViewModelCommon::getStatusText() +{ + if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter()->getCurrentGeneration()) + { + return LLTrans::getString("Searching"); + } + else + { + return getFilter()->getEmptyLookupMessage(); + } +} + +void LLFolderViewModelCommon::filter() +{ + getFilter()->setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); + mFolderView->getViewModelItem()->filter(*getFilter()); +} diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 5304613219..8a16ec3eff 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -28,6 +28,7 @@ #include "lldarray.h" // *TODO: convert to std::vector #include "llfoldertype.h" #include "llfontgl.h" // just for StyleFlags enum +#include "llfolderview.h" #include "llfolderviewitem.h" #include "llinventorytype.h" #include "llpermissionsflags.h" @@ -122,11 +123,13 @@ public: virtual void requestSortAll() = 0; virtual void sort(class LLFolderViewFolder*) = 0; + virtual void filter() = 0; virtual bool contentsReady() = 0; virtual void setFolderView(LLFolderView* folder_view) = 0; virtual LLFolderViewFilter* getFilter() = 0; virtual const LLFolderViewFilter* getFilter() const = 0; + virtual std::string getStatusText() = 0; }; class LLFolderViewModelCommon : public LLFolderViewModelInterface @@ -142,6 +145,8 @@ public: // sort everything mTargetSortVersion++; } + virtual std::string getStatusText(); + virtual void filter(); void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} @@ -177,6 +182,7 @@ public: // add getStatusText and isFiltering() virtual bool contentsReady() { return true; } + struct ViewModelCompare { ViewModelCompare(const SortType& sorter) @@ -272,6 +278,7 @@ public: virtual bool hasChildren() const = 0; virtual void addChild(LLFolderViewModelItem* child) = 0; + virtual void removeChild(LLFolderViewModelItem* child) = 0; // This method will be called to determine if a drop can be // performed, and will set drop to TRUE if a drop is @@ -305,7 +312,9 @@ public: mLastFilterGeneration(-1), mMostFilteredDescendantGeneration(-1), mParent(NULL) - {} + { + std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); + } void requestSort() { mSortVersion = -1; } S32 getSortVersion() { return mSortVersion; } @@ -315,13 +324,23 @@ public: void dirtyFilter() { mLastFilterGeneration = -1; + // bubble up dirty flag all the way to root if (mParent) { mParent->dirtyFilter(); - } + } + } + virtual void addChild(LLFolderViewModelItem* child) + { + mChildren.push_back(child); + child->setParent(this); + } + virtual void removeChild(LLFolderViewModelItem* child) + { + mChildren.remove(child); + child->setParent(NULL); } - virtual void addChild(LLFolderViewModelItem* child) { mChildren.push_back(child); child->setParent(this); } protected: virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp new file mode 100644 index 0000000000..7ee1a10b15 --- /dev/null +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -0,0 +1,225 @@ +/* + * @file llfolderviewmodelinventory.cpp + * @brief Implementation of the inventory-specific view model + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfolderviewmodelinventory.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llinventorypanel.h" + +// +// class LLFolderViewModelInventory +// +static LLFastTimer::DeclareTimer FTM_INVENTORY_SORT("Sort"); + +void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) +{ + LLFastTimer _(FTM_INVENTORY_SORT); + + if (!needsSort(folder->getViewModelItem())) return; + + LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem()); + if (modelp->getUUID().isNull()) return; + + for (std::list<LLFolderViewFolder*>::iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); + it != end_it; + ++it) + { + LLFolderViewFolder* child_folderp = *it; + sort(child_folderp); + + if (child_folderp->getFoldersCount() > 0) + { + time_t most_recent_folder_time = + static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getFoldersBegin())->getViewModelItem())->getCreationDate(); + LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); + if (most_recent_folder_time > modelp->getCreationDate()) + { + modelp->setCreationDate(most_recent_folder_time); + } + } + if (child_folderp->getItemsCount() > 0) + { + time_t most_recent_item_time = + static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getItemsBegin())->getViewModelItem())->getCreationDate(); + + LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); + if (most_recent_item_time > modelp->getCreationDate()) + { + modelp->setCreationDate(most_recent_item_time); + } + } + } + base_t::sort(folder); +} + +bool LLFolderViewModelInventory::contentsReady() +{ + return !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); +} + +void LLFolderViewModelItemInventory::requestSort() +{ + LLFolderViewModelItemCommon::requestSort(); + if (mRootViewModel->getSorter().isByDate()) + { + // sort by date potentially affects parent folders which use a date + // derived from newest item in them + if (mParent) + { + mParent->requestSort(); + } + } +} + +bool LLFolderViewModelItemInventory::potentiallyVisible() +{ + return passedFilter() // we've passed the filter + || getLastFilterGeneration() < mRootViewModel->getFilter()->getFirstSuccessGeneration() // or we don't know yet + || descendantsPassedFilter(); +} + +bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) +{ + if (filter_generation < 0 && mRootViewModel) + filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); + + return mPassedFolderFilter + && mLastFilterGeneration >= filter_generation + && (mPassedFilter || descendantsPassedFilter(filter_generation)); +} + +bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) +{ + if (filter_generation < 0) filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); + return mMostFilteredDescendantGeneration >= filter_generation; +} + +void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) +{ + mPassedFilter = passed; + mPassedFolderFilter = passed_folder; + mLastFilterGeneration = filter_generation; +} + +bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) +{ + bool passed_filter_before = item->passedFilter(); + S32 filter_generation = filter.getCurrentGeneration(); + S32 must_pass_generation = filter.getFirstRequiredGeneration(); + + if (item->getLastFilterGeneration() < filter_generation) + { + if (item->getLastFilterGeneration() >= must_pass_generation + && !item->passedFilter(must_pass_generation)) + { + // failed to pass an earlier filter that was a subset of the current one + // go ahead and flag this item as done + item->filter(filter); + if (item->passedFilter()) + { + llerrs << "Invalid shortcut in inventory filtering!" << llendl; + } + item->setPassedFilter(false, false, filter_generation); + } + else + { + item->filter( filter ); + } + } + + // track latest generation to pass any child items, for each folder up to root + if (item->passedFilter()) + { + LLFolderViewModelItemInventory* view_model = this; + + while(view_model && view_model->mMostFilteredDescendantGeneration < filter_generation) + { + view_model->mMostFilteredDescendantGeneration = filter_generation; + view_model = static_cast<LLFolderViewModelItemInventory*>(view_model->mParent); + } + + return !passed_filter_before; + } + else // !item->passedfilter() + { + return passed_filter_before; + } +} + +bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) +{ + bool changed = false; + + if(!mChildren.empty() + && (getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass + || descendantsPassedFilter(filter.getFirstRequiredGeneration()))) // or at least one descendant has passed the minimum requirement + { + // now query children + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end() && filter.getFilterCount() > 0; + ++iter) + { + changed |= filterChildItem((*iter), filter); + } + } + + if (changed) + { + //TODO RN: ensure this still happens, but without dependency on folderview + LLFolderViewFolder* folder = static_cast<LLFolderViewFolder*>(mFolderViewItem); + folder->requestArrange(); + } + + // if we didn't use all filter iterations + // that means we filtered all of our descendants + // so filter ourselves now + if (filter.getFilterCount() > 0) + { + filter.decrementFilterCount(); + + const BOOL passed_filter = filter.check(this); + const BOOL passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) + ? filter.checkFolder(this) + : true; + + setPassedFilter(passed_filter, passed_filter_folder, filter.getCurrentGeneration()); + //TODO RN: create interface for string highlighting + //mStringMatchOffset = filter.getStringMatchOffset(this); + } + return changed; +} + +LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() +{ + return &mInventoryViewModel; +} + + +const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const +{ + return &mInventoryViewModel; +} + diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h new file mode 100644 index 0000000000..a8fe3f57ea --- /dev/null +++ b/indra/newview/llfolderviewmodelinventory.h @@ -0,0 +1,107 @@ +/** + * @file llfolderviewmodelinventory.h + * @brief view model implementation specific to inventory + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFOLDERVIEWMODELINVENTORY_H +#define LL_LLFOLDERVIEWMODELINVENTORY_H + +#include "llinventoryfilter.h" + +class LLFolderViewModelItemInventory + : public LLFolderViewModelItemCommon +{ +public: + LLFolderViewModelItemInventory() + : mRootViewModel(NULL) + {} + void setRootViewModel(class LLFolderViewModelInventory* root_view_model) + { + mRootViewModel = root_view_model; + } + virtual const LLUUID& getUUID() const = 0; + virtual time_t getCreationDate() const = 0; // UTC seconds + virtual void setCreationDate(time_t creation_date_utc) = 0; + virtual PermissionMask getPermissionMask() const = 0; + virtual LLFolderType::EType getPreferredType() const = 0; + virtual void showProperties(void) = 0; + virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. + virtual BOOL isUpToDate() const = 0; + virtual bool hasChildren() const = 0; + virtual LLInventoryType::EType getInventoryType() const = 0; + virtual void performAction(LLInventoryModel* model, std::string action) = 0; + virtual LLWearableType::EType getWearableType() const = 0; + virtual EInventorySortGroup getSortGroup() const = 0; + virtual LLInventoryObject* getInventoryObject() const = 0; + virtual void requestSort(); + virtual bool potentiallyVisible(); + virtual bool passedFilter(S32 filter_generation = -1); + virtual bool descendantsPassedFilter(S32 filter_generation = -1); + virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); + virtual bool filter( LLFolderViewFilter& filter); + virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); +protected: + class LLFolderViewModelInventory* mRootViewModel; +}; + +class LLInventorySort +{ +public: + LLInventorySort(U32 order = 0) + : mSortOrder(order), + mByDate(false), + mSystemToTop(false), + mFoldersByName(false) + { + mByDate = (order & LLInventoryFilter::SO_DATE); + mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); + mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); + } + + bool isByDate() const { return mByDate; } + U32 getSortOrder() const { return mSortOrder; } + + bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const; +private: + U32 mSortOrder; + bool mByDate; + bool mSystemToTop; + bool mFoldersByName; +}; + +class LLFolderViewModelInventory + : public LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> +{ +public: + typedef LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> base_t; + + virtual ~LLFolderViewModelInventory() {} + + void sort(LLFolderViewFolder* folder); + + bool contentsReady(); + +}; +#endif // LL_LLFOLDERVIEWMODELINVENTORY_H diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 6a33130322..3f38d80a39 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -779,14 +779,12 @@ const std::string& LLInventoryFilter::getFilterText() if (isFilterObjectTypesWith(LLInventoryType::IT_ANIMATION)) { - //filtered_types += " Animations,"; filtered_types += LLTrans::getString("Animations"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Animations,"; not_filtered_types += LLTrans::getString("Animations"); filtered_by_all_types = FALSE; @@ -794,140 +792,120 @@ const std::string& LLInventoryFilter::getFilterText() if (isFilterObjectTypesWith(LLInventoryType::IT_CALLINGCARD)) { - //filtered_types += " Calling Cards,"; filtered_types += LLTrans::getString("Calling Cards"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Calling Cards,"; not_filtered_types += LLTrans::getString("Calling Cards"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_WEARABLE)) { - //filtered_types += " Clothing,"; filtered_types += LLTrans::getString("Clothing"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Clothing,"; not_filtered_types += LLTrans::getString("Clothing"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_GESTURE)) { - //filtered_types += " Gestures,"; filtered_types += LLTrans::getString("Gestures"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Gestures,"; not_filtered_types += LLTrans::getString("Gestures"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_LANDMARK)) { - //filtered_types += " Landmarks,"; filtered_types += LLTrans::getString("Landmarks"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Landmarks,"; not_filtered_types += LLTrans::getString("Landmarks"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_NOTECARD)) { - //filtered_types += " Notecards,"; filtered_types += LLTrans::getString("Notecards"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Notecards,"; not_filtered_types += LLTrans::getString("Notecards"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_OBJECT) && isFilterObjectTypesWith(LLInventoryType::IT_ATTACHMENT)) { - //filtered_types += " Objects,"; filtered_types += LLTrans::getString("Objects"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Objects,"; not_filtered_types += LLTrans::getString("Objects"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_LSL)) { - //filtered_types += " Scripts,"; filtered_types += LLTrans::getString("Scripts"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Scripts,"; not_filtered_types += LLTrans::getString("Scripts"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_SOUND)) { - //filtered_types += " Sounds,"; filtered_types += LLTrans::getString("Sounds"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Sounds,"; not_filtered_types += LLTrans::getString("Sounds"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_TEXTURE)) { - //filtered_types += " Textures,"; filtered_types += LLTrans::getString("Textures"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Textures,"; not_filtered_types += LLTrans::getString("Textures"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_SNAPSHOT)) { - //filtered_types += " Snapshots,"; filtered_types += LLTrans::getString("Snapshots"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Snapshots,"; not_filtered_types += LLTrans::getString("Snapshots"); filtered_by_all_types = FALSE; } @@ -943,7 +921,6 @@ const std::string& LLInventoryFilter::getFilterText() } else { - //mFilterText += "No "; mFilterText += LLTrans::getString("No Filters"); mFilterText += not_filtered_types; } @@ -953,7 +930,6 @@ const std::string& LLInventoryFilter::getFilterText() if (isSinceLogoff()) { - //mFilterText += " - Since Logoff"; mFilterText += LLTrans::getString("Since Logoff"); } return mFilterText; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index e4cabcc988..b5fcf364dd 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -56,58 +56,6 @@ const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("Recent const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; -// -// class LLFolderViewModelInventory -// -static LLFastTimer::DeclareTimer FTM_INVENTORY_SORT("Sort"); - -void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) -{ - LLFastTimer _(FTM_INVENTORY_SORT); - - if (!needsSort(folder->getViewModelItem())) return; - - LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem()); - if (modelp->getUUID().isNull()) return; - - for (std::list<LLFolderViewFolder*>::iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); - it != end_it; - ++it) - { - LLFolderViewFolder* child_folderp = *it; - sort(child_folderp); - - if (child_folderp->getFoldersCount() > 0) - { - time_t most_recent_folder_time = - static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getFoldersBegin())->getViewModelItem())->getCreationDate(); - LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); - if (most_recent_folder_time > modelp->getCreationDate()) - { - modelp->setCreationDate(most_recent_folder_time); - } - } - if (child_folderp->getItemsCount() > 0) - { - time_t most_recent_item_time = - static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getItemsBegin())->getViewModelItem())->getCreationDate(); - - LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); - if (most_recent_item_time > modelp->getCreationDate()) - { - modelp->setCreationDate(most_recent_item_time); - } - } - } - base_t::sort(folder); -} - -bool LLFolderViewModelInventory::contentsReady() -{ - return !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); -} - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryPanelObserver // @@ -580,8 +528,8 @@ void LLInventoryPanel::modelChanged(U32 mask) else if (!model_item && view_item) { // Remove the item's UI. - view_item->destroyView(); removeItemID(viewmodel_item->getUUID()); + view_item->destroyView(); } } } @@ -1344,150 +1292,3 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params) // replace bridge builder to have necessary View bridges. mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER; } - - -void LLFolderViewModelItemInventory::requestSort() -{ - LLFolderViewModelItemCommon::requestSort(); - if (mRootViewModel->getSorter().isByDate()) - { - // sort by date potentially affects parent folders which use a date - // derived from newest item in them - if (mParent) - { - mParent->requestSort(); - } - } -} - -bool LLFolderViewModelItemInventory::potentiallyVisible() -{ - return passedFilter() // we've passed the filter - || getLastFilterGeneration() < mRootViewModel->getFilter()->getFirstSuccessGeneration() // or we don't know yet - || descendantsPassedFilter(); -} - -bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) -{ - if (filter_generation < 0) filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); - return mPassedFolderFilter - && mLastFilterGeneration >= filter_generation - && (mPassedFilter || descendantsPassedFilter(filter_generation)); -} - -bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) -{ - if (filter_generation < 0) filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); - return mMostFilteredDescendantGeneration >= filter_generation; -} - -void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) -{ - mPassedFilter = passed; - mPassedFolderFilter = passed_folder; - mLastFilterGeneration = filter_generation; -} - -bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) -{ - bool passed_filter_before = item->passedFilter(); - S32 filter_generation = filter.getCurrentGeneration(); - S32 must_pass_generation = filter.getFirstRequiredGeneration(); - bool changed = false; - - // mMostFilteredDescendantGeneration might have been reset - // in which case we need to update it even for folders that - // don't need to be filtered anymore - if (item->getLastFilterGeneration() < filter_generation) - { - if (item->getLastFilterGeneration() >= must_pass_generation && - !item->passedFilter(must_pass_generation)) - { - // failed to pass an earlier filter that was a subset of the current one - // go ahead and flag this item as done - item->setPassedFilter(false, false, filter_generation); - } - else - { - changed |= item->filter( filter ); - } - } - - // track latest generation to pass any child items - if (item->passedFilter()) - { - LLFolderViewModelItemInventory* view_model = this; - - while(view_model && view_model->mMostFilteredDescendantGeneration < filter_generation) - { - view_model->mMostFilteredDescendantGeneration = filter_generation; - view_model = static_cast<LLFolderViewModelItemInventory*>(view_model->mParent); - } - } - - changed |= (item->passedFilter() != passed_filter_before); - if (changed) - { - //TODO RN: ensure this still happens, but without dependency on folderview - LLFolderViewFolder* parent = mFolderViewItem->getParentFolder(); - if (parent) parent->requestArrange(); - } - - return changed; -} - -bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) -{ - bool changed = false; - - if(!mChildren.empty() - && (getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass - || descendantsPassedFilter(filter.getFirstRequiredGeneration()))) // or at least one descendant has passed the minimum requirement - { - // now query children - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end() && filter.getFilterCount() > 0; - ++iter) - { - changed |= filterChildItem((*iter), filter); - } - } - - // if we didn't use all filter iterations - // that means we filtered all of our descendants - // so filter ourselves now - if (filter.getFilterCount() > 0) - { - const BOOL previous_passed_filter = mPassedFilter; - const BOOL passed_filter = filter.check(this); - const BOOL passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) - ? filter.checkFolder(this) - : true; - - // If our visibility will change as a result of this filter, then - // we need to be rearranged in our parent folder - LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder(); - if (parent_folder && passed_filter != previous_passed_filter) - { - parent_folder->requestArrange(); - } - - setPassedFilter(passed_filter, passed_filter_folder, filter.getCurrentGeneration()); - //TODO RN: create interface for string highlighting - //mStringMatchOffset = filter.getStringMatchOffset(this); - filter.decrementFilterCount(); - } - return changed; -} - -LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() -{ - return &mInventoryViewModel; -} - - -const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const -{ - return &mInventoryViewModel; -} - diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 3195d9a369..a62b97aa7d 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -31,6 +31,7 @@ #include "llassetstorage.h" #include "lldarray.h" #include "llfolderviewitem.h" +#include "llfolderviewmodelinventory.h" #include "llfloater.h" #include "llinventory.h" #include "llinventoryfilter.h" @@ -42,83 +43,6 @@ class LLInvFVBridge; class LLInventoryFVBridgeBuilder; class LLInvPanelComplObserver; -class LLFolderViewModelInventory; - -class LLFolderViewModelItemInventory - : public LLFolderViewModelItemCommon -{ -public: - LLFolderViewModelItemInventory() - : mRootViewModel(NULL) - {} - void setRootViewModel(LLFolderViewModelInventory* root_view_model) - { - mRootViewModel = root_view_model; - } - virtual const LLUUID& getUUID() const = 0; - virtual time_t getCreationDate() const = 0; // UTC seconds - virtual void setCreationDate(time_t creation_date_utc) = 0; - virtual PermissionMask getPermissionMask() const = 0; - virtual LLFolderType::EType getPreferredType() const = 0; - virtual void showProperties(void) = 0; - virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. - virtual BOOL isUpToDate() const = 0; - virtual bool hasChildren() const = 0; - virtual LLInventoryType::EType getInventoryType() const = 0; - virtual void performAction(LLInventoryModel* model, std::string action) = 0; - virtual LLWearableType::EType getWearableType() const = 0; - virtual EInventorySortGroup getSortGroup() const = 0; - virtual LLInventoryObject* getInventoryObject() const = 0; - virtual void requestSort(); - virtual bool potentiallyVisible(); - virtual bool passedFilter(S32 filter_generation = -1); - virtual bool descendantsPassedFilter(S32 filter_generation = -1); - virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); - virtual bool filter( LLFolderViewFilter& filter); - virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); -protected: - LLFolderViewModelInventory* mRootViewModel; -}; - -class LLInventorySort -{ -public: - LLInventorySort(U32 order = 0) - : mSortOrder(order), - mByDate(false), - mSystemToTop(false), - mFoldersByName(false) - { - mByDate = (order & LLInventoryFilter::SO_DATE); - mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); - mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); - } - - bool isByDate() const { return mByDate; } - U32 getSortOrder() const { return mSortOrder; } - - bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const; -private: - U32 mSortOrder; - bool mByDate; - bool mSystemToTop; - bool mFoldersByName; -}; - -class LLFolderViewModelInventory - : public LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> -{ -public: - typedef LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> base_t; - - virtual ~LLFolderViewModelInventory() {} - - void sort(LLFolderViewFolder* folder); - - bool contentsReady(); - -}; - class LLInventoryPanel : public LLPanel { diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 61a0331b72..4a9e106687 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -623,9 +623,9 @@ void LLFloaterTexturePicker::draw() LLFolderView* folder_view = mInventoryPanel->getRootFolder(); if (!folder_view) return; - LLInventoryFilter* filter = static_cast<LLFolderViewModelInventory*>(folder_view->getFolderViewModel())->getFilter(); + LLFolderViewFilter* filter = static_cast<LLFolderViewModelInventory*>(folder_view->getFolderViewModel())->getFilter(); - bool is_filter_active = folder_view->getLastFilterGeneration() < filter->getCurrentGeneration() && + bool is_filter_active = folder_view->getViewModelItem()->getLastFilterGeneration() < filter->getCurrentGeneration() && filter->isNotDefault(); // After inventory panel filter is applied we have to update -- cgit v1.2.3 From 7b4f24850b94aba41ee93c6f2901b012de2b7d30 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Mon, 2 Jul 2012 19:37:11 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose fixed build post merge --- indra/newview/llimfloatercontainer.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 2bbd371e8f..9615f3f44d 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -37,7 +37,7 @@ #include "llgroupmgr.h" #include "llfolderviewitem.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" class LLButton; class LLLayoutPanel; @@ -53,7 +53,7 @@ typedef std::map<LLFloater*, LLFolderViewItem*> conversations_widgets_map; // Conversation items: we hold a list of those and create an LLFolderViewItem widget for each // that we tuck into the mConversationsListPanel. -class LLConversationItem : public LLFolderViewEventListener +class LLConversationItem : public LLFolderViewModelItemCommon { public: LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp); @@ -62,6 +62,7 @@ public: // Stub those things we won't really be using in this conversation context virtual const std::string& getName() const { return mName; } virtual const std::string& getDisplayName() const { return mName; } + virtual const std::string& getSearchableName() const { return mName; } virtual const LLUUID& getUUID() const { return mUUID; } virtual time_t getCreationDate() const { return 0; } virtual PermissionMask getPermissionMask() const { return PERM_ALL; } @@ -76,8 +77,8 @@ public: virtual BOOL isItemRemovable( void ) const { return FALSE; } virtual BOOL isItemInTrash( void) const { return FALSE; } virtual BOOL removeItem() { return FALSE; } - virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) { } - virtual void move( LLFolderViewEventListener* parent_listener ) { } + virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) { } + virtual void move( LLFolderViewModelItem* parent_listener ) { } virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL copyToClipboard() const { return FALSE; } virtual BOOL cutToClipboard() const { return FALSE; } @@ -86,10 +87,16 @@ public: virtual void pasteLinkFromClipboard() { } virtual void buildContextMenu(LLMenuGL& menu, U32 flags) { } virtual BOOL isUpToDate() const { return TRUE; } - virtual BOOL hasChildren() const { return FALSE; } + virtual bool hasChildren() const { return FALSE; } virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; } virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } + virtual bool potentiallyVisible() { return true; } + virtual bool filter( LLFolderViewFilter& filter) { return true; } + virtual bool descendantsPassedFilter(S32 filter_generation = -1) { return true; } + virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) { } + virtual bool passedFilter(S32 filter_generation = -1) { return true; } + // The action callbacks virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem( void ); @@ -102,6 +109,7 @@ public: // This method should be called when a drag begins. // Returns TRUE if the drag can begin, FALSE otherwise. + virtual LLToolDragAndDrop::ESource getDragSource() const { return LLToolDragAndDrop::SOURCE_PEOPLE; } virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const { return FALSE; } // This method will be called to determine if a drop can be -- cgit v1.2.3 From 7d0150f12d8edcbd078ef570f7c64e44194e4335 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Mon, 2 Jul 2012 19:37:28 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose started to remove newview dependencies from llfolder* --- indra/newview/llfolderview.cpp | 196 +++++++-------------------- indra/newview/llfolderview.h | 12 +- indra/newview/llfolderviewitem.cpp | 96 +------------ indra/newview/llfolderviewitem.h | 1 - indra/newview/llfolderviewmodel.h | 13 +- indra/newview/llfolderviewmodelinventory.cpp | 81 +++++++++++ indra/newview/llinventoryfunctions.cpp | 88 +++++++++++- indra/newview/llinventoryfunctions.h | 7 + indra/newview/llinventorypanel.cpp | 13 +- indra/newview/llinventorypanel.h | 2 +- indra/newview/llpanellandmarks.cpp | 4 +- indra/newview/llpanelmaininventory.cpp | 4 +- indra/newview/llpanelobjectinventory.cpp | 2 +- 13 files changed, 245 insertions(+), 274 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 90c78d98b0..6bc89cdbca 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -26,34 +26,25 @@ #include "llviewerprecompiledheaders.h" -#include "llfolderview.h" #include "llfolderview.h" -#include "llcallbacklist.h" -#include "llinventorybridge.h" #include "llclipboard.h" // *TODO: remove this once hack below gone. -#include "llinventorypanel.h" -#include "llfoldertype.h" #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" #include "llpanel.h" -#include "llpreview.h" #include "llscrollcontainer.h" // hack to allow scrolling -#include "lltooldraganddrop.h" #include "lltrans.h" #include "llui.h" -#include "llviewertexture.h" -#include "llviewertexturelist.h" -#include "llviewerjointattachment.h" -#include "llviewermenu.h" #include "lluictrlfactory.h" -#include "llviewercontrol.h" -#include "llviewerfoldertype.h" -#include "llviewerwindow.h" -#include "llvoavatar.h" -#include "llfloaterproperties.h" -#include "llnotificationsutil.h" + +// TODO RN: kill these +// newview includes +#include "llcallbacklist.h" // per-frame on-idle +#include "llfloaterproperties.h" // showProperties +#include "llviewerwindow.h" // renamer popup handling +#include "llpreview.h" // openSelectedItems +#include "llinventorypanel.h" // idle loop for filtering, sort order declarations, etc. // Linden library includes #include "lldbstrings.h" @@ -251,7 +242,7 @@ LLFolderView::LLFolderView(const Params& p) // make the popup menu available - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); if (!menu) { menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu"); @@ -361,7 +352,7 @@ static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View"); void LLFolderView::filter( LLFolderViewFilter& filter ) { LLFastTimer t2(FTM_FILTER); - filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); + filter.setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); getViewModelItem()->filter(filter); } @@ -631,7 +622,7 @@ void LLFolderView::clearSelection() } std::set<LLFolderViewItem*> LLFolderView::getSelectionList() const - { +{ std::set<LLFolderViewItem*> selection; std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin())); return selection; @@ -695,7 +686,7 @@ void LLFolderView::draw() } - if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout") || !mSearchString.size()) + if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout") || !mSearchString.size()) { mSearchString.clear(); } @@ -767,14 +758,6 @@ void LLFolderView::closeRenamer( void ) } } -void LLFolderView::removeSelectedItems( void ) -{ - if (mSelectedItems.empty()) return; - LLSD args; - args["QUESTION"] = LLTrans::getString(mSelectedItems.size() > 1 ? "DeleteItems" : "DeleteItem"); - LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLFolderView::onItemsRemovalConfirmation, this, _1, _2)); -} - bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector<LLFolderViewItem*>& selectedItems) { LLFolderViewItem* item_parent = dynamic_cast<LLFolderViewItem*>(item->getParent()); @@ -820,11 +803,8 @@ void LLFolderView::removeCutItems() } } -void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response) +void LLFolderView::removeSelectedItems() { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) return; // canceled - if(getVisible() && getEnabled()) { // just in case we're removing the renaming item. @@ -927,42 +907,44 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL } } +// TODO RN: abstract // open the selected item. void LLFolderView::openSelectedItems( void ) { - if(getVisible() && getEnabled()) - { - if (mSelectedItems.size() == 1) - { - mSelectedItems.front()->openItem(); - } - else - { - LLMultiPreview* multi_previewp = new LLMultiPreview(); - LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + //TODO RN: get working again + //if(getVisible() && getEnabled()) + //{ + // if (mSelectedItems.size() == 1) + // { + // mSelectedItems.front()->openItem(); + // } + // else + // { + // LLMultiPreview* multi_previewp = new LLMultiPreview(); + // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - // IT_{OBJECT,ATTACHMENT} creates LLProperties - // floaters; others create LLPreviews. Put - // each one in the right type of container. - LLFolderViewModelItemInventory* listener = static_cast<LLFolderViewModelItemInventory*>((*item_it)->getViewModelItem()); - bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); - if (is_prop) - LLFloater::setFloaterHost(multi_propertiesp); - else - LLFloater::setFloaterHost(multi_previewp); - listener->openItem(); - } + // selected_items_t::iterator item_it; + // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + // { + // // IT_{OBJECT,ATTACHMENT} creates LLProperties + // // floaters; others create LLPreviews. Put + // // each one in the right type of container. + // LLFolderViewModelItemInventory* listener = static_cast<LLFolderViewModelItemInventory*>((*item_it)->getViewModelItem()); + // bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); + // if (is_prop) + // LLFloater::setFloaterHost(multi_propertiesp); + // else + // LLFloater::setFloaterHost(multi_previewp); + // listener->openItem(); + // } - LLFloater::setFloaterHost(NULL); - // *NOTE: LLMulti* will safely auto-delete when open'd - // without any children. - multi_previewp->openFloater(LLSD()); - multi_propertiesp->openFloater(LLSD()); - } - } + // LLFloater::setFloaterHost(NULL); + // // *NOTE: LLMulti* will safely auto-delete when open'd + // // without any children. + // multi_previewp->openFloater(LLSD()); + // multi_propertiesp->openFloater(LLSD()); + // } + //} } void LLFolderView::propertiesSelectedItems( void ) @@ -994,15 +976,6 @@ void LLFolderView::propertiesSelectedItems( void ) //} } -void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type) -{ - LLFolderBridge *folder_bridge = LLFolderBridge::sSelf.get(); - - if (!folder_bridge) return; - LLViewerInventoryCategory *cat = folder_bridge->getCategory(); - if (!cat) return; - cat->changeType(new_folder_type); -} void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) { @@ -1521,7 +1494,7 @@ BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) } //do text search - if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout")) + if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout")) { mSearchString.clear(); } @@ -1831,81 +1804,6 @@ void LLFolderView::setShowSingleSelection(BOOL show) } } -bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) -{ - std::string action = userdata.asString(); - - if ("rename" == action) - { - startRenamingSelectedItem(); - return true; - } - if ("delete" == action) - { - removeSelectedItems(); - return true; - } - if (("copy" == action) || ("cut" == action)) - { - // Clear the clipboard before we start adding things on it - LLClipboard::instance().reset(); - } - - static const std::string change_folder_string = "change_folder_type_"; - if (action.length() > change_folder_string.length() && - (action.compare(0,change_folder_string.length(),"change_folder_type_") == 0)) - { - LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length())); - changeType(model, new_folder_type); - return true; - } - - - std::set<LLFolderViewItem*> selected_items = getSelectionList(); - - LLMultiPreview* multi_previewp = NULL; - LLMultiProperties* multi_propertiesp = NULL; - - if (("task_open" == action || "open" == action) && selected_items.size() > 1) - { - multi_previewp = new LLMultiPreview(); - gFloaterView->addChild(multi_previewp); - - LLFloater::setFloaterHost(multi_previewp); - - } - else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1) - { - multi_propertiesp = new LLMultiProperties(); - gFloaterView->addChild(multi_propertiesp); - - LLFloater::setFloaterHost(multi_propertiesp); - } - - std::set<LLFolderViewItem*>::iterator set_iter; - - for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) - { - LLFolderViewItem* folder_item = *set_iter; - if(!folder_item) continue; - LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem(); - if(!bridge) continue; - bridge->performAction(model, action); - } - - LLFloater::setFloaterHost(NULL); - if (multi_previewp) - { - multi_previewp->openFloater(LLSD()); - } - else if (multi_propertiesp) - { - multi_propertiesp->openFloater(LLSD()); - } - - return true; -} - static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select"); static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory"); diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 8a0317f840..e098119293 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -39,20 +39,17 @@ #include "lluictrl.h" #include "v4color.h" -#include "lldarray.h" #include "stdenums.h" #include "lldepthstack.h" #include "lleditmenuhandler.h" #include "llfontgl.h" #include "llscrollcontainer.h" #include "lltooldraganddrop.h" -#include "llviewertexture.h" class LLFolderViewModelInterface; class LLFolderViewFolder; class LLFolderViewItem; class LLFolderViewFilter; -class LLInventoryModel; class LLPanel; class LLLineEditor; class LLMenuGL; @@ -153,8 +150,9 @@ public: virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); virtual std::set<LLFolderViewItem*> getSelectionList() const; + S32 getNumSelectedItems() { return mSelectedItems.size(); } - // Make sure if ancestor is selected, descendents are not + // Make sure if ancestor is selected, descendants are not void sanitizeSelection(); virtual void clearSelection(); void addToSelectionList(LLFolderViewItem* item); @@ -173,9 +171,6 @@ public: void openSelectedItems( void ); void propertiesSelectedItems( void ); - // Change the folder type - void changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type); - void autoOpenItem(LLFolderViewFolder* item); void closeAutoOpenedFolders(); BOOL autoOpenTest(LLFolderViewFolder* item); @@ -228,8 +223,6 @@ public: F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } bool getUseEllipses() { return mUseEllipses; } - bool doToSelected(LLInventoryModel* model, const LLSD& userdata); - void doIdle(); // Real idle routine static void idle(void* user_data); // static glue to doIdle() @@ -270,7 +263,6 @@ protected: BOOL addNoOptions(LLMenuGL* menu) const; - void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response); protected: LLHandle<LLView> mPopupMenuHandle; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 80893c3037..e84c765ac8 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -28,16 +28,9 @@ #include "llfolderviewitem.h" // viewer includes -#include "llfolderview.h" // Items depend extensively on LLFolderViews #include "llfolderview.h" #include "llfolderviewmodel.h" -#include "llviewerfoldertype.h" -#include "llinventorybridge.h" // for LLItemBridge in LLInventorySort::operator() -#include "llinventoryfunctions.h" -#include "llinventorymodelbackgroundfetch.h" #include "llpanel.h" -#include "llviewercontrol.h" // gSavedSettings -#include "llviewerwindow.h" // Argh, only for setCursor() // linden library includes #include "llclipboard.h" @@ -529,11 +522,11 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) if (can_drag) { - gViewerWindow->setCursor(UI_CURSOR_ARROW); + getWindow()->setCursor(UI_CURSOR_ARROW); } else { - gViewerWindow->setCursor(UI_CURSOR_NOLOCKED); + getWindow()->setCursor(UI_CURSOR_NOLOCKED); } return TRUE; } @@ -541,9 +534,9 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) { if (getRoot()) { - getRoot()->setShowSelectionContext(FALSE); + getRoot()->setShowSelectionContext(FALSE); } - gViewerWindow->setCursor(UI_CURSOR_ARROW); + getWindow()->setCursor(UI_CURSOR_ARROW); // let parent handle this then... return FALSE; } @@ -2075,84 +2068,3 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it return result; } -bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const -{ - // ignore sort order for landmarks in the Favorites folder. - // they should be always sorted as in Favorites bar. See EXT-719 - //TODO RN: fix sorting in favorites folder - //if (a->getSortGroup() == SG_ITEM - // && b->getSortGroup() == SG_ITEM - // && a->getInventoryType() == LLInventoryType::IT_LANDMARK - // && b->getInventoryType() == LLInventoryType::IT_LANDMARK) - //{ - - // static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - - // LLUUID a_uuid = a->getParentFolder()->getUUID(); - // LLUUID b_uuid = b->getParentFolder()->getUUID(); - - // if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) - // { - // // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem - // // or to LLInvFVBridge - // LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a))->getItem(); - // LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b))->getItem(); - // if (!aitem || !bitem) - // return false; - // S32 a_sort = aitem->getSortField(); - // S32 b_sort = bitem->getSortField(); - // return a_sort < b_sort; - // } - //} - - // We sort by name if we aren't sorting by date - // OR if these are folders and we are sorting folders by name. - bool by_name = (!mByDate - || (mFoldersByName - && (a->getSortGroup() != SG_ITEM))); - - if (a->getSortGroup() != b->getSortGroup()) - { - if (mSystemToTop) - { - // Group order is System Folders, Trash, Normal Folders, Items - return (a->getSortGroup() < b->getSortGroup()); - } - else if (mByDate) - { - // Trash needs to go to the bottom if we are sorting by date - if ( (a->getSortGroup() == SG_TRASH_FOLDER) - || (b->getSortGroup() == SG_TRASH_FOLDER)) - { - return (b->getSortGroup() == SG_TRASH_FOLDER); - } - } - } - - if (by_name) - { - S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); - if (0 == compare) - { - return (a->getCreationDate() > b->getCreationDate()); - } - else - { - return (compare < 0); - } - } - else - { - time_t first_create = a->getCreationDate(); - time_t second_create = b->getCreationDate(); - if (first_create == second_create) - { - return (LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()) < 0); - } - else - { - return (first_create > second_create); - } - } -} - diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 581ec7239e..92923e82da 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -27,7 +27,6 @@ #define LLFOLDERVIEWITEM_H #include "llview.h" -#include "lldarray.h" // *TODO: Eliminate, forward declare #include "lluiimage.h" class LLFolderView; diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 8a16ec3eff..98b7255137 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -22,18 +22,11 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -#ifndef LLFOLDERVIEWEVENTLISTENER_H -#define LLFOLDERVIEWEVENTLISTENER_H +#ifndef LLFOLDERVIEWMODEL_H +#define LLFOLDERVIEWMODEL_H -#include "lldarray.h" // *TODO: convert to std::vector -#include "llfoldertype.h" #include "llfontgl.h" // just for StyleFlags enum #include "llfolderview.h" -#include "llfolderviewitem.h" -#include "llinventorytype.h" -#include "llpermissionsflags.h" -#include "llpointer.h" -#include "llwearabletype.h" #include "lltooldraganddrop.h" // These are grouping of inventory types. @@ -362,4 +355,4 @@ protected: }; -#endif +#endif // LLFOLDERVIEWMODEL_H diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 7ee1a10b15..99831c61bf 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -223,3 +223,84 @@ const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const return &mInventoryViewModel; } +bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const +{ + // ignore sort order for landmarks in the Favorites folder. + // they should be always sorted as in Favorites bar. See EXT-719 + //TODO RN: fix sorting in favorites folder + //if (a->getSortGroup() == SG_ITEM + // && b->getSortGroup() == SG_ITEM + // && a->getInventoryType() == LLInventoryType::IT_LANDMARK + // && b->getInventoryType() == LLInventoryType::IT_LANDMARK) + //{ + + // static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + + // LLUUID a_uuid = a->getParentFolder()->getUUID(); + // LLUUID b_uuid = b->getParentFolder()->getUUID(); + + // if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) + // { + // // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem + // // or to LLInvFVBridge + // LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a))->getItem(); + // LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b))->getItem(); + // if (!aitem || !bitem) + // return false; + // S32 a_sort = aitem->getSortField(); + // S32 b_sort = bitem->getSortField(); + // return a_sort < b_sort; + // } + //} + + // We sort by name if we aren't sorting by date + // OR if these are folders and we are sorting folders by name. + bool by_name = (!mByDate + || (mFoldersByName + && (a->getSortGroup() != SG_ITEM))); + + if (a->getSortGroup() != b->getSortGroup()) + { + if (mSystemToTop) + { + // Group order is System Folders, Trash, Normal Folders, Items + return (a->getSortGroup() < b->getSortGroup()); + } + else if (mByDate) + { + // Trash needs to go to the bottom if we are sorting by date + if ( (a->getSortGroup() == SG_TRASH_FOLDER) + || (b->getSortGroup() == SG_TRASH_FOLDER)) + { + return (b->getSortGroup() == SG_TRASH_FOLDER); + } + } + } + + if (by_name) + { + S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); + if (0 == compare) + { + return (a->getCreationDate() > b->getCreationDate()); + } + else + { + return (compare < 0); + } + } + else + { + time_t first_create = a->getCreationDate(); + time_t second_create = b->getCreationDate(); + if (first_create == second_create) + { + return (LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()) < 0); + } + else + { + return (first_create > second_create); + } + } +} + diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index ff461236a2..07f3dd8ffb 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -45,7 +45,7 @@ // newview includes #include "llappearancemgr.h" #include "llappviewer.h" -//#include "llfirstuse.h" +#include "llclipboard.h" #include "llfloaterinventory.h" #include "llfloatersidepanelcontainer.h" #include "llfocusmgr.h" @@ -74,8 +74,10 @@ #include "llsidepanelinventory.h" #include "lltabcontainer.h" #include "lltooldraganddrop.h" +#include "lltrans.h" #include "lluictrlfactory.h" #include "llviewermessage.h" +#include "llviewerfoldertype.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" #include "llviewerwindow.h" @@ -1044,3 +1046,87 @@ void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder) } } +void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root, const std::string& action) +{ + if ("rename" == action) + { + root->startRenamingSelectedItem(); + return; + } + if ("delete" == action) + { + LLSD args; + args["QUESTION"] = LLTrans::getString(root->getNumSelectedItems() > 1 ? "DeleteItems" : "DeleteItem"); + LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root)); + return; + } + if (("copy" == action) || ("cut" == action)) + { + // Clear the clipboard before we start adding things on it + LLClipboard::instance().reset(); + } + + static const std::string change_folder_string = "change_folder_type_"; + if (action.length() > change_folder_string.length() && + (action.compare(0,change_folder_string.length(),"change_folder_type_") == 0)) + { + LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length())); + LLFolderViewModelItemInventory* inventory_item = static_cast<LLFolderViewModelItemInventory*>(root->getViewModelItem()); + LLViewerInventoryCategory *cat = model->getCategory(inventory_item->getUUID()); + if (!cat) return; + cat->changeType(new_folder_type); + return; + } + + + std::set<LLFolderViewItem*> selected_items = root->getSelectionList(); + + LLMultiPreview* multi_previewp = NULL; + LLMultiProperties* multi_propertiesp = NULL; + + if (("task_open" == action || "open" == action) && selected_items.size() > 1) + { + multi_previewp = new LLMultiPreview(); + gFloaterView->addChild(multi_previewp); + + LLFloater::setFloaterHost(multi_previewp); + + } + else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1) + { + multi_propertiesp = new LLMultiProperties(); + gFloaterView->addChild(multi_propertiesp); + + LLFloater::setFloaterHost(multi_propertiesp); + } + + std::set<LLFolderViewItem*>::iterator set_iter; + + for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) + { + LLFolderViewItem* folder_item = *set_iter; + if(!folder_item) continue; + LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem(); + if(!bridge) continue; + bridge->performAction(model, action); + } + + LLFloater::setFloaterHost(NULL); + if (multi_previewp) + { + multi_previewp->openFloater(LLSD()); + } + else if (multi_propertiesp) + { + multi_propertiesp->openFloater(LLSD()); + } +} + +void LLInventoryAction::onItemsRemovalConfirmation( const LLSD& notification, const LLSD& response, LLFolderView* root ) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + root->removeSelectedItems(); + } +} diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index c6b1da0417..d8d3d9bbbb 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -427,6 +427,13 @@ public: static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction }; +struct LLInventoryAction +{ + static void doToSelected(class LLInventoryModel* model, class LLFolderView* root, const std::string& action); + + static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLFolderView* root); +}; + #endif // LL_LLINVENTORYFUNCTIONS_H diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index b5fcf364dd..ef8c5dc1cf 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -44,6 +44,7 @@ #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorymodelbackgroundfetch.h" +#include "llpreview.h" #include "llsidepanelinventory.h" #include "llviewerattachmenu.h" #include "llviewerfoldertype.h" @@ -926,11 +927,6 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it } } -void LLInventoryPanel::doToSelected(const LLSD& userdata) -{ - mFolderRoot->doToSelected(&gInventory, userdata); -} - void LLInventoryPanel::doCreate(const LLSD& userdata) { menu_create_inventory_item(this, LLFolderBridge::sSelf.get(), userdata); @@ -1260,6 +1256,13 @@ void LLInventoryPanel::updateSelection() } } +void LLInventoryPanel::doToSelected(const LLSD& userdata) +{ + LLInventoryAction::doToSelected(mInventory, mFolderRoot, userdata.asString()); + + return; +} + /************************************************************************/ /* Recent Inventory Panel related class */ diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index a62b97aa7d..58c1201e54 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -176,7 +176,7 @@ public: LLFolderViewFolder* getFolderByID(const LLUUID& id); void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); void updateSelection(); - + LLFolderViewModelInventory* getFolderViewModel(); const LLFolderViewModelInventory* getFolderViewModel() const; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 0b899d34f4..faef923338 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -851,7 +851,7 @@ void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const } else { - mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(),command_name); + mCurrentSelectedList->doToSelected(command_name); } } @@ -896,7 +896,7 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata) { if(mCurrentSelectedList) { - mCurrentSelectedList->getRootFolder()->doToSelected(&gInventory, userdata); + mCurrentSelectedList->doToSelected(userdata); } } } diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 6cef1f877b..fea27b37d3 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -294,7 +294,7 @@ BOOL LLPanelMainInventory::handleKeyHere(KEY key, MASK mask) void LLPanelMainInventory::doToSelected(const LLSD& userdata) { - getPanel()->getRootFolder()->doToSelected(&gInventory, userdata); + getPanel()->doToSelected(userdata); } void LLPanelMainInventory::closeAllFolders() @@ -970,7 +970,7 @@ void LLPanelMainInventory::onTrashButtonClick() void LLPanelMainInventory::onClipboardAction(const LLSD& userdata) { std::string command_name = userdata.asString(); - getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name); + getActivePanel()->doToSelected(command_name); } void LLPanelMainInventory::saveTexture(const LLSD& userdata) diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 450e1f7ed0..002c0c1113 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1522,7 +1522,7 @@ BOOL LLPanelObjectInventory::postBuild() void LLPanelObjectInventory::doToSelected(const LLSD& userdata) { - mFolders->doToSelected(&gInventory, userdata); + LLInventoryAction::doToSelected(&gInventory, mFolders, userdata.asString()); } void LLPanelObjectInventory::clearContents() -- cgit v1.2.3 From ad1f2eb5106a9ba0217ff1080d029f912ecc25e5 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Tue, 3 Jul 2012 22:31:58 +0300 Subject: CHUI-186 CHUI-187 FIX Removing a P2P convrsation from converstaion widget in the upper right corner when a new participant is added. End call prompt removed when adding a new participant to a P2P voice call. After adding a participant to a P2P voice conversation the resulting conference call is restarted voice invites to all participants. --- indra/newview/llavataractions.cpp | 4 +- indra/newview/llavataractions.h | 4 +- indra/newview/llimfloater.cpp | 73 ++++++++++++++++++++---------------- indra/newview/llimfloater.h | 2 +- indra/newview/llpanelpeoplemenus.cpp | 2 +- 5 files changed, 46 insertions(+), 39 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 21367c224d..56c9533e11 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -235,7 +235,7 @@ void LLAvatarActions::startCall(const LLUUID& id) } // static -void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids) +void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids, const LLUUID& floater_id) { if (ids.size() == 0) { @@ -252,7 +252,7 @@ void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids) // create the new ad hoc voice session const std::string title = LLTrans::getString("conference-title"); LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, - ids[0], id_array, true); + ids[0], id_array, true, floater_id); if (session_id == LLUUID::null) { return; diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 46830eb22c..259e87c336 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -82,9 +82,9 @@ public: static void startCall(const LLUUID& id); /** - * Start an ad-hoc conference voice call with multiple users + * Start an ad-hoc conference voice call with multiple users in a specific IM floater. */ - static void startAdhocCall(const uuid_vec_t& ids); + static void startAdhocCall(const uuid_vec_t& ids, const LLUUID& floater_id = LLUUID::null); /** * Start conference chat with the given avatars in a specific IM floater. diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 9d3c0f98ce..536d0b9a23 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -322,7 +322,7 @@ BOOL LLIMFloater::postBuild() void LLIMFloater::onAddButtonClicked() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::onAvatarPicked, this, _1, _2), TRUE, TRUE); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE); if (!picker) { return; @@ -337,25 +337,6 @@ void LLIMFloater::onAddButtonClicked() } } -void LLIMFloater::onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names) -{ - if (mIsP2PChat) - { - mStartConferenceInSameFloater = true; - onClose(false); - - uuid_vec_t temp_ids; - temp_ids.push_back(mOtherParticipantUUID); - temp_ids.insert(temp_ids.end(), ids.begin(), ids.end()); - - LLAvatarActions::startConference(temp_ids, mSessionID); - } - else - { - inviteToSession(ids); - } -} - bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) { if (!mSession @@ -388,6 +369,44 @@ bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) return true; } +void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) +{ + if (mIsP2PChat) + { + mStartConferenceInSameFloater = true; + + uuid_vec_t temp_ids; + + // Add the initial participant of a P2P session + temp_ids.push_back(mOtherParticipantUUID); + temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end()); + + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + + // first check whether this is a voice session + bool is_voice_call = voice_channel != NULL && voice_channel->isActive(); + + // then we can close the current session + gIMMgr->leaveSession(mSessionID); + LLIMConversation::onClose(false); + + // Start a new ad hoc voice call if we invite new participants to a P2P call, + // or start a text chat otherwise. + if (is_voice_call) + { + LLAvatarActions::startAdhocCall(temp_ids, mSessionID); + } + else + { + LLAvatarActions::startConference(temp_ids, mSessionID); + } + } + else + { + inviteToSession(uuids); + } +} + void LLIMFloater::boundVoiceChannel() { LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); @@ -1096,19 +1115,7 @@ bool LLIMFloater::dropPerson(LLUUID* person_id, bool drop) res = canAddSelectedToChat(ids); if(res && drop) { - if (mIsP2PChat) - { - mStartConferenceInSameFloater = true; - onClose(false); - - ids.push_back(mOtherParticipantUUID); - - LLAvatarActions::startConference(ids, mSessionID); - } - else - { - inviteToSession(ids); - } + addSessionParticipants(ids); } } diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 23f9e75e21..2e8fc84746 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -152,7 +152,7 @@ private: static void onInputEditorKeystroke(LLTextEditor* caller, void* userdata); void setTyping(bool typing); void onAddButtonClicked(); - void onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names); + void addSessionParticipants(const uuid_vec_t& uuids); bool canAddSelectedToChat(const uuid_vec_t& uuids); void onCallButtonClicked(); diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index ac2109dda4..c9eebe24d3 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -82,7 +82,7 @@ LLContextMenu* NearbyMenu::createMenu() // registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs)); // *TODO: unimplemented registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startConference, mUUIDs, LLUUID::null)); - registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs)); + registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs, LLUUID::null)); registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this)); registrar.add("Avatar.RemoveFriend",boost::bind(&LLAvatarActions::removeFriendsDialog, mUUIDs)); // registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::startIM, mUUIDs)); // *TODO: unimplemented -- cgit v1.2.3 From ac0243a006fa28e872e4ee88f7c1588eaefeaecf Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Tue, 3 Jul 2012 22:32:21 +0300 Subject: CHUI-188 FIX for crash in adding chat participants. Modified the duplicated participants check procedure LLIMFloater::canAddSelectedToChat() to use the list, updated by LLSpeakerMgr instead of LLIMSession::mInitialTargetIDs list, which is initialized at session start and not updated afterwards. --- indra/newview/llimfloater.cpp | 72 +++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 26 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 536d0b9a23..a506f0f9f3 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -339,34 +339,54 @@ void LLIMFloater::onAddButtonClicked() bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) { - if (!mSession - || mDialog == IM_SESSION_GROUP_START - || mDialog == IM_SESSION_INVITE && gAgent.isInGroup(mSessionID)) - { - return false; - } + if (!mSession + || mDialog == IM_SESSION_GROUP_START + || mDialog == IM_SESSION_INVITE && gAgent.isInGroup(mSessionID)) + { + return false; + } - for (uuid_vec_t::const_iterator id = uuids.begin(); - id != uuids.end(); ++id) - { - // Skip this check for ad hoc conferences, - // conference participants should be listed in mSession->mInitialTargetIDs. - if (mIsP2PChat && *id == mOtherParticipantUUID) - { - return false; - } - - for (uuid_vec_t::const_iterator target_id = mSession->mInitialTargetIDs.begin(); - target_id != mSession->mInitialTargetIDs.end(); ++target_id) - { - if (*id == *target_id) - { - return false; - } - } - } + if (mIsP2PChat) + { + // For a P2P session just check if we are not adding the other participant. + + for (uuid_vec_t::const_iterator id = uuids.begin(); + id != uuids.end(); ++id) + { + if (*id == mOtherParticipantUUID) + { + return false; + } + } + } + else + { + // For a conference session we need to check against the list from LLSpeakerMgr, + // because this list may change when participants join or leave the session. + + LLSpeakerMgr::speaker_list_t speaker_list; + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + speaker_mgr->getSpeakerList(&speaker_list, true); + } - return true; + for (uuid_vec_t::const_iterator id = uuids.begin(); + id != uuids.end(); ++id) + { + for (LLSpeakerMgr::speaker_list_t::const_iterator it = speaker_list.begin(); + it != speaker_list.end(); ++it) + { + const LLPointer<LLSpeaker>& speaker = *it; + if (*id == speaker->mID) + { + return false; + } + } + } + } + + return true; } void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) -- cgit v1.2.3 From a8defa513c3b2b83f476a1de115fd0332566b483 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 3 Jul 2012 17:05:28 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose removed viewer dependencies from folderview code --- indra/newview/llfolderview.cpp | 84 +++++++++---------------------------- indra/newview/llfolderview.h | 5 +-- indra/newview/llfolderviewitem.cpp | 10 ----- indra/newview/llfolderviewmodel.cpp | 3 +- indra/newview/llfolderviewmodel.h | 1 - indra/newview/llinventorybridge.cpp | 6 +-- indra/newview/llinventorypanel.cpp | 11 +++++ indra/newview/llinventorypanel.h | 79 +--------------------------------- 8 files changed, 36 insertions(+), 163 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 6bc89cdbca..10677db094 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -27,25 +27,18 @@ #include "llviewerprecompiledheaders.h" #include "llfolderview.h" - +#include "llfolderviewmodel.h" #include "llclipboard.h" // *TODO: remove this once hack below gone. #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" #include "llpanel.h" #include "llscrollcontainer.h" // hack to allow scrolling +#include "lltextbox.h" #include "lltrans.h" #include "llui.h" #include "lluictrlfactory.h" -// TODO RN: kill these -// newview includes -#include "llcallbacklist.h" // per-frame on-idle -#include "llfloaterproperties.h" // showProperties -#include "llviewerwindow.h" // renamer popup handling -#include "llpreview.h" // openSelectedItems -#include "llinventorypanel.h" // idle loop for filtering, sort order declarations, etc. - // Linden library includes #include "lldbstrings.h" #include "llfocusmgr.h" @@ -172,7 +165,6 @@ LLFolderView::LLFolderView(const Params& p) mNeedsAutoSelect( FALSE ), mAutoSelectOverride(FALSE), mNeedsAutoRename(FALSE), - mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME), // This gets overridden by a pref immediately mShowSelectionContext(FALSE), mShowSingleSelection(FALSE), mArrangeGeneration(0), @@ -199,7 +191,6 @@ LLFolderView::LLFolderView(const Params& p) mAutoOpenTimer.stop(); mKeyboardSelection = FALSE; mIndentation = p.folder_indentation; - gIdleCallbacks.addFunction(idle, this); //clear label // go ahead and render root folder as usual @@ -269,7 +260,6 @@ LLFolderView::~LLFolderView( void ) mStatusTextBox = NULL; mAutoOpenItems.removeAllNodes(); - gIdleCallbacks.deleteFunction(idle, this); if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); @@ -291,16 +281,16 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { LLFolderViewFolder::addFolder(folder); - mFolders.remove(folder); - // enforce sort order of My Inventory followed by Library - if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) - { - mFolders.push_back(folder); - } - else - { - mFolders.insert(mFolders.begin(), folder); - } + // TODO RN: enforce sort order of My Inventory followed by Library + //mFolders.remove(folder); + //if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) + //{ + // mFolders.push_back(folder); + //} + //else + //{ + // mFolders.insert(mFolders.begin(), folder); + //} return TRUE; } @@ -754,7 +744,7 @@ void LLFolderView::closeRenamer( void ) if (mRenamer && mRenamer->getVisible()) { // Triggers onRenamerLost() that actually closes the renamer. - gViewerWindow->removePopup(mRenamer); + LLUI::removePopup(mRenamer); } } @@ -785,24 +775,6 @@ bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector<LLFol return false; } -// static -void LLFolderView::removeCutItems() -{ - // There's no item in "cut" mode on the clipboard -> exit - if (!LLClipboard::instance().isCutMode()) - return; - - // Get the list of clipboard item uuids and iterate through them - LLDynamicArray<LLUUID> objects; - LLClipboard::instance().pasteFromClipboard(objects); - for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin(); - iter != objects.end(); - ++iter) - { - gInventory.removeObject(*iter); - } -} - void LLFolderView::removeSelectedItems() { if(getVisible() && getEnabled()) @@ -1126,9 +1098,9 @@ void LLFolderView::cut() if(listener) { listener->cutToClipboard(); + listener->removeItem(); } } - LLFolderView::removeCutItems(); } mSearchString.clear(); } @@ -1222,7 +1194,7 @@ void LLFolderView::startRenamingSelectedItem( void ) // set focus will fail unless item is visible mRenamer->setFocus( TRUE ); mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); - gViewerWindow->addPopup(mRenamer); + LLUI::addPopup(mRenamer); } } @@ -1808,16 +1780,10 @@ static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select"); static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory"); // Main idle routine -void LLFolderView::doIdle() +void LLFolderView::update() { // If this is associated with the user's inventory, don't do anything // until that inventory is loaded up. - const LLInventoryPanel *inventory_panel = dynamic_cast<LLInventoryPanel*>(mParentPanel); - if (inventory_panel && !inventory_panel->getIsViewsInitialized()) - { - return; - } - LLFastTimer t2(FTM_INVENTORY); if (getFolderViewModel()->getFilter()->isModified() && getFolderViewModel()->getFilter()->isNotDefault()) @@ -1859,8 +1825,8 @@ void LLFolderView::doIdle() BOOL filter_finished = getViewModelItem()->passedFilter() && mViewModel->contentsReady(); if (filter_finished - || gFocusMgr.childHasKeyboardFocus(inventory_panel) - || gFocusMgr.childHasMouseCapture(inventory_panel)) + || gFocusMgr.childHasKeyboardFocus(getParent()) // assume we are inside a scroll container + || gFocusMgr.childHasMouseCapture(getParent())) { // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process mNeedsAutoSelect = FALSE; @@ -1919,7 +1885,6 @@ void LLFolderView::doIdle() constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); } - BOOL is_visible = isInVisibleChain(); if ( is_visible ) @@ -1954,17 +1919,6 @@ void LLFolderView::doIdle() mSignalSelectCallback = FALSE; } - -//static -void LLFolderView::idle(void* user_data) -{ - LLFolderView* self = (LLFolderView*)user_data; - if ( self ) - { // Do the real idle - self->doIdle(); - } -} - void LLFolderView::dumpSelectionInformation() { llinfos << "LLFolderView::dumpSelectionInformation()" << llendl; @@ -1988,7 +1942,7 @@ void LLFolderView::updateRenamerPosition() screenPointToLocal( x, y, &x, &y ); mRenamer->setOrigin( x, y ); - LLRect scroller_rect(0, 0, gViewerWindow->getWindowWidthScaled(), 0); + LLRect scroller_rect(0, 0, LLUI::getWindowSize().mV[VX], 0); if (mScrollContainer) { scroller_rect = mScrollContainer->getContentWindowRect(); diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index e098119293..78f1d8aff2 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -165,7 +165,6 @@ public: // Deletion functionality void removeSelectedItems(); - static void removeCutItems(); // Open the selected item void openSelectedItems( void ); @@ -223,8 +222,7 @@ public: F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } bool getUseEllipses() { return mUseEllipses; } - void doIdle(); // Real idle routine - static void idle(void* user_data); // static glue to doIdle() + void update(); // needs to be called periodically (e.g. once per frame) BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; } BOOL needsAutoRename() { return mNeedsAutoRename; } @@ -288,7 +286,6 @@ protected: bool mUseLabelSuffix; bool mShowItemLinkOverlays; - U32 mSortOrder; LLDepthStack<LLFolderViewFolder> mAutoOpenItems; LLFolderViewFolder* mAutoOpenCandidate; LLFrameTimer mAutoOpenTimer; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 3937d4332b..dee3fe7218 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -1798,16 +1798,6 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) { - /* Disable outfit double click to wear - const LLUUID &cat_uuid = getViewModelItem()->getUUID(); - const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid); - if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) - { - getViewModelItem()->performAction(NULL, NULL,"replaceoutfit"); - return TRUE; - } - */ - BOOL handled = FALSE; if( isOpen() ) { diff --git a/indra/newview/llfolderviewmodel.cpp b/indra/newview/llfolderviewmodel.cpp index 92db84156e..ca6225aca7 100644 --- a/indra/newview/llfolderviewmodel.cpp +++ b/indra/newview/llfolderviewmodel.cpp @@ -28,7 +28,6 @@ #include "llfolderviewmodel.h" #include "lltrans.h" -#include "llviewercontrol.h" bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) { @@ -49,6 +48,6 @@ std::string LLFolderViewModelCommon::getStatusText() void LLFolderViewModelCommon::filter() { - getFilter()->setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); + getFilter()->setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); mFolderView->getViewModelItem()->filter(*getFilter()); } diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 98b7255137..079409c2a4 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -27,7 +27,6 @@ #include "llfontgl.h" // just for StyleFlags enum #include "llfolderview.h" -#include "lltooldraganddrop.h" // These are grouping of inventory types. // Order matters when sorting system folders to the top. diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 002278601a..d17c25d9f3 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1400,7 +1400,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) else if ("cut" == action) { cutToClipboard(); - LLFolderView::removeCutItems(); + gInventory.removeObject(mUUID); return; } else if ("copy" == action) @@ -1680,14 +1680,12 @@ BOOL LLItemBridge::renameItem(const std::string& new_name) return FALSE; } - BOOL LLItemBridge::removeItem() { if(!isItemRemovable()) { return FALSE; } - // move it to the trash LLPreview::hide(mUUID, TRUE); @@ -2870,7 +2868,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) else if ("cut" == action) { cutToClipboard(); - LLFolderView::removeCutItems(); + gInventory.removeObject(mUUID); return; } else if ("copy" == action) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index c1ffe89184..fed9893158 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -258,6 +258,8 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) LLInventoryPanel::~LLInventoryPanel() { + gIdleCallbacks.deleteFunction(idle, this); + U32 sort_order = getFolderViewModel()->getSorter().getSortOrder(); if (mSortOrderSetting != INHERIT_SORT_ORDER) { @@ -566,12 +568,21 @@ void LLInventoryPanel::onIdle(void *userdata) } } +void LLInventoryPanel::idle(void* user_data) +{ + LLInventoryPanel* panel = (LLInventoryPanel*)user_data; + panel->mFolderRoot->doIdle(); +} + + void LLInventoryPanel::initializeViews() { if (!gInventory.isInventoryUsable()) return; rebuildViewsFor(gInventory.getRootFolderID()); + gIdleCallbacks.addFunction(idle, this); + mViewsInitialized = true; openStartFolderOrMyInventory(); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 1061f12575..465ccdd582 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -45,82 +45,6 @@ class LLInventoryFVBridgeBuilder; class LLInvPanelComplObserver; class LLFolderViewModelInventory; -class LLFolderViewModelItemInventory - : public LLFolderViewModelItemCommon -{ -public: - LLFolderViewModelItemInventory() - : mRootViewModel(NULL) - {} - void setRootViewModel(LLFolderViewModelInventory* root_view_model) - { - mRootViewModel = root_view_model; - } - virtual const LLUUID& getUUID() const = 0; - virtual time_t getCreationDate() const = 0; // UTC seconds - virtual void setCreationDate(time_t creation_date_utc) = 0; - virtual PermissionMask getPermissionMask() const = 0; - virtual LLFolderType::EType getPreferredType() const = 0; - virtual void showProperties(void) = 0; - virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. - virtual BOOL isUpToDate() const = 0; - virtual bool hasChildren() const = 0; - virtual LLInventoryType::EType getInventoryType() const = 0; - virtual void performAction(LLInventoryModel* model, std::string action) = 0; - virtual LLWearableType::EType getWearableType() const = 0; - virtual EInventorySortGroup getSortGroup() const = 0; - virtual LLInventoryObject* getInventoryObject() const = 0; - virtual void requestSort(); - virtual bool potentiallyVisible(); - virtual bool passedFilter(S32 filter_generation = -1); - virtual bool descendantsPassedFilter(S32 filter_generation = -1); - virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); - virtual bool filter( LLFolderViewFilter& filter); - virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); -protected: - LLFolderViewModelInventory* mRootViewModel; -}; - -class LLInventorySort -{ -public: - LLInventorySort(U32 order = 0) - : mSortOrder(order), - mByDate(false), - mSystemToTop(false), - mFoldersByName(false) - { - mByDate = (order & LLInventoryFilter::SO_DATE); - mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); - mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); - } - - bool isByDate() const { return mByDate; } - U32 getSortOrder() const { return mSortOrder; } - - bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const; -private: - U32 mSortOrder; - bool mByDate; - bool mSystemToTop; - bool mFoldersByName; -}; - -class LLFolderViewModelInventory - : public LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> -{ -public: - typedef LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> base_t; - - virtual ~LLFolderViewModelInventory() {} - - void sort(LLFolderViewFolder* folder); - - bool contentsReady(); - -}; - - class LLInventoryPanel : public LLPanel { //-------------------------------------------------------------------- @@ -232,7 +156,8 @@ public: void doCreate(const LLSD& userdata); bool beginIMSession(); bool attachObject(const LLSD& userdata); - + static void idle(void* user_data); + // DEBUG ONLY: static void dumpSelectionInformation(void* user_data); -- cgit v1.2.3 From 52bf9e20454181d8acb0ac419a882cc1a0e3af9e Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 3 Jul 2012 18:11:14 -0700 Subject: CHUI-174 : Fixed crash in forced response to notifications. Use an empty form in that case and allow the notification to not be in the notifications list. --- indra/newview/llviewermessage.cpp | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index dd78bbd491..7e1f186769 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1481,7 +1481,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& } LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); - llassert(notification_ptr != NULL); // For muting, we need to add the mute, then decline the offer. // This must be done here because: @@ -1504,7 +1503,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& bool busy = gAgent.getBusy(); - LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); + LLNotificationFormPtr modified_form(notification_ptr ? new LLNotificationForm(*notification_ptr->getForm()) : new LLNotificationForm()); switch(button) { @@ -1550,7 +1549,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& break; } - modified_form->setElementEnabled("Show", false); + if (modified_form != NULL) + { + modified_form->setElementEnabled("Show", false); + } break; // end switch (mIM) @@ -1567,7 +1569,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& break; case IOR_MUTE: - modified_form->setElementEnabled("Mute", false); + if (modified_form != NULL) + { + modified_form->setElementEnabled("Mute", false); + } // MUTE falls through to decline case IOR_DECLINE: { @@ -1604,8 +1609,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& busy_message(gMessageSystem, mFromID); } - modified_form->setElementEnabled("Show", false); - modified_form->setElementEnabled("Discard", false); + if (modified_form != NULL) + { + modified_form->setElementEnabled("Show", false); + modified_form->setElementEnabled("Discard", false); + } break; } @@ -1627,8 +1635,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& delete this; } - notification_ptr->updateForm(modified_form); - notification_ptr->repost(); + if (notification_ptr != NULL) + { + notification_ptr->updateForm(modified_form); + notification_ptr->repost(); + } return false; } -- cgit v1.2.3 From cea3c37dcb09eb30cb986ecac4d29a4ff1cc0898 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 3 Jul 2012 19:58:49 -0700 Subject: CHUI-164 : Fix crash when closing conversations using the conversation widget. Populated the sessionRemoved() method with code to close the floater and clean up the list. --- indra/newview/llimfloatercontainer.cpp | 11 +++++++++-- indra/newview/llimfloatercontainer.h | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 261b5f33a2..08ace601a3 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -73,8 +73,15 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { - LLIMFloater::show(session_id); -}; + LLIMFloater::show(session_id); +} + +void LLIMFloaterContainer::sessionRemoved(const LLUUID& session_id) +{ + LLIMFloater* floaterp = LLIMFloater::findInstance(session_id); + LLFloater::onClickClose(floaterp); + removeConversationListItem(floaterp); +} BOOL LLIMFloaterContainer::postBuild() { diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 2bbd371e8f..c062127bee 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -158,7 +158,7 @@ public: // LLIMSessionObserver observe triggers /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id); - /*virtual*/ void sessionRemoved(const LLUUID& session_id) {}; + /*virtual*/ void sessionRemoved(const LLUUID& session_id); /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {}; private: -- cgit v1.2.3 From 1494a1058f41c5aa00a8ed08fe71123f63e92e81 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 3 Jul 2012 23:55:39 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose move llfolderview* into LLUI! --- indra/llui/CMakeLists.txt | 6 + indra/llui/llfolderview.cpp | 2078 +++++++++++++++++++++++++ indra/llui/llfolderview.h | 388 +++++ indra/llui/llfolderviewitem.cpp | 2032 +++++++++++++++++++++++++ indra/llui/llfolderviewitem.h | 420 +++++ indra/llui/llfolderviewmodel.cpp | 53 + indra/llui/llfolderviewmodel.h | 353 +++++ indra/newview/CMakeLists.txt | 6 - indra/newview/llfolderview.cpp | 2105 -------------------------- indra/newview/llfolderview.h | 393 ----- indra/newview/llfolderviewitem.cpp | 2060 ------------------------- indra/newview/llfolderviewitem.h | 418 ----- indra/newview/llfolderviewmodel.cpp | 53 - indra/newview/llfolderviewmodel.h | 357 ----- indra/newview/llfolderviewmodelinventory.cpp | 26 + indra/newview/llfolderviewmodelinventory.h | 13 +- indra/newview/llimfloatercontainer.h | 9 - indra/newview/llinventorybridge.h | 3 +- indra/newview/llinventorypanel.cpp | 19 +- indra/newview/llpanelobjectinventory.cpp | 2 +- indra/newview/lltexturectrl.cpp | 1 + 21 files changed, 5389 insertions(+), 5406 deletions(-) create mode 100644 indra/llui/llfolderview.cpp create mode 100644 indra/llui/llfolderview.h create mode 100644 indra/llui/llfolderviewitem.cpp create mode 100644 indra/llui/llfolderviewitem.h create mode 100644 indra/llui/llfolderviewmodel.cpp create mode 100644 indra/llui/llfolderviewmodel.h delete mode 100644 indra/newview/llfolderview.cpp delete mode 100644 indra/newview/llfolderview.h delete mode 100644 indra/newview/llfolderviewitem.cpp delete mode 100644 indra/newview/llfolderviewitem.h delete mode 100644 indra/newview/llfolderviewmodel.cpp delete mode 100644 indra/newview/llfolderviewmodel.h (limited to 'indra') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index b50ed2342d..a9ad0a3c0b 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -54,6 +54,9 @@ set(llui_SOURCE_FILES llfloaterreglistener.cpp llflyoutbutton.cpp llfocusmgr.cpp + llfolderview.cpp + llfolderviewitem.cpp + llfolderviewmodel.cpp llfunctorregistry.cpp lliconctrl.cpp llkeywords.cpp @@ -154,6 +157,9 @@ set(llui_HEADER_FILES llfloaterreglistener.h llflyoutbutton.h llfocusmgr.h + llfolderview.h + llfolderviewitem.h + llfolderviewmodel.h llfunctorregistry.h llhandle.h llhelp.h diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp new file mode 100644 index 0000000000..0d3bc44ae4 --- /dev/null +++ b/indra/llui/llfolderview.cpp @@ -0,0 +1,2078 @@ +/** + * @file llfolderview.cpp + * @brief Implementation of the folder view collection of classes. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llfolderview.h" +#include "llfolderviewmodel.h" +#include "llclipboard.h" // *TODO: remove this once hack below gone. +#include "llkeyboard.h" +#include "lllineeditor.h" +#include "llmenugl.h" +#include "llpanel.h" +#include "llscrollcontainer.h" // hack to allow scrolling +#include "lltextbox.h" +#include "lltrans.h" +#include "llui.h" +#include "lluictrlfactory.h" + +// Linden library includes +#include "lldbstrings.h" +#include "llfocusmgr.h" +#include "llfontgl.h" +#include "llgl.h" +#include "llrender.h" + +// Third-party library includes +#include <algorithm> + +///---------------------------------------------------------------------------- +/// Local function declarations, constants, enums, and typedefs +///---------------------------------------------------------------------------- + +const S32 RENAME_WIDTH_PAD = 4; +const S32 RENAME_HEIGHT_PAD = 1; +const S32 AUTO_OPEN_STACK_DEPTH = 16; +const S32 MIN_ITEM_WIDTH_VISIBLE = LLFolderViewItem::ICON_WIDTH + + LLFolderViewItem::ICON_PAD + + LLFolderViewItem::ARROW_SIZE + + LLFolderViewItem::TEXT_PAD + + /*first few characters*/ 40; +const S32 MINIMUM_RENAMER_WIDTH = 80; + +// *TODO: move in params in xml if necessary. Requires modification of LLFolderView & LLInventoryPanel Params. +const S32 STATUS_TEXT_HPAD = 6; +const S32 STATUS_TEXT_VPAD = 8; + +enum { + SIGNAL_NO_KEYBOARD_FOCUS = 1, + SIGNAL_KEYBOARD_FOCUS = 2 +}; + +F32 LLFolderView::sAutoOpenTime = 1.f; + +//--------------------------------------------------------------------------- + +// Tells all folders in a folderview to close themselves +// For efficiency, calls setOpenArrangeRecursively(). +// The calling function must then call: +// LLFolderView* root = getRoot(); +// if( root ) +// { +// root->arrange( NULL, NULL ); +// root->scrollToShowSelection(); +// } +// to patch things up. +class LLCloseAllFoldersFunctor : public LLFolderViewFunctor +{ +public: + LLCloseAllFoldersFunctor(BOOL close) { mOpen = !close; } + virtual ~LLCloseAllFoldersFunctor() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); + + BOOL mOpen; +}; + + +void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder) +{ + folder->setOpenArrangeRecursively(mOpen); +} + +// Do nothing. +void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item) +{ } + +///---------------------------------------------------------------------------- +/// Class LLFolderViewScrollContainer +///---------------------------------------------------------------------------- + +// virtual +const LLRect LLFolderViewScrollContainer::getScrolledViewRect() const +{ + LLRect rect = LLRect::null; + if (mScrolledView) + { + LLFolderView* folder_view = dynamic_cast<LLFolderView*>(mScrolledView); + if (folder_view) + { + S32 height = folder_view->getRect().getHeight(); + + rect = mScrolledView->getRect(); + rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); + } + } + + return rect; +} + +LLFolderViewScrollContainer::LLFolderViewScrollContainer(const LLScrollContainer::Params& p) +: LLScrollContainer(p) +{} + +///---------------------------------------------------------------------------- +/// Class LLFolderView +///---------------------------------------------------------------------------- +LLFolderView::Params::Params() +: title("title"), + use_label_suffix("use_label_suffix"), + allow_multiselect("allow_multiselect", true), + show_empty_message("show_empty_message", true), + use_ellipses("use_ellipses", false) +{ + folder_indentation = -4; +} + + +// Default constructor +LLFolderView::LLFolderView(const Params& p) +: LLFolderViewFolder(p), + mScrollContainer( NULL ), + mPopupMenuHandle(), + mAllowMultiSelect(p.allow_multiselect), + mShowEmptyMessage(p.show_empty_message), + mShowFolderHierarchy(FALSE), + mRenameItem( NULL ), + mNeedsScroll( FALSE ), + mUseLabelSuffix(p.use_label_suffix), + mPinningSelectedItem(FALSE), + mNeedsAutoSelect( FALSE ), + mAutoSelectOverride(FALSE), + mNeedsAutoRename(FALSE), + mShowSelectionContext(FALSE), + mShowSingleSelection(FALSE), + mArrangeGeneration(0), + mSignalSelectCallback(0), + mMinWidth(0), + mDragAndDropThisFrame(FALSE), + mCallbackRegistrar(NULL), + mParentPanel(p.parent_panel), + mUseEllipses(p.use_ellipses), + mDraggingOverItem(NULL), + mStatusTextBox(NULL), + mShowItemLinkOverlays(p.show_item_link_overlays), + mViewModel(p.view_model) +{ + mViewModel->setFolderView(this); + mRoot = this; + + LLRect rect = p.rect; + LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); + setRect( rect ); + reshape(rect.getWidth(), rect.getHeight()); + mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); + mAutoOpenCandidate = NULL; + mAutoOpenTimer.stop(); + mKeyboardSelection = FALSE; + mIndentation = p.folder_indentation; + + //clear label + // go ahead and render root folder as usual + // just make sure the label ("Inventory Folder") never shows up + mLabel = LLStringUtil::null; + + // Escape is handled by reverting the rename, not commiting it (default behavior) + LLLineEditor::Params params; + params.name("ren"); + params.rect(rect); + params.font(getLabelFontForStyle(LLFontGL::NORMAL)); + params.max_length.bytes(DB_INV_ITEM_NAME_STR_LEN); + params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); + params.prevalidate_callback(&LLTextValidate::validateASCIIPrintableNoPipe); + params.commit_on_focus_lost(true); + params.visible(false); + mRenamer = LLUICtrlFactory::create<LLLineEditor> (params); + addChild(mRenamer); + + // Textbox + LLTextBox::Params text_p; + LLFontGL* font = getLabelFontForStyle(mLabelStyle); + LLRect new_r = LLRect(rect.mLeft + ICON_PAD, + rect.mTop - TEXT_PAD, + rect.mRight, + rect.mTop - TEXT_PAD - font->getLineHeight()); + text_p.rect(new_r); + text_p.name(std::string(p.name)); + text_p.font(font); + text_p.visible(false); + text_p.parse_urls(true); + text_p.wrap(true); // allow multiline text. See EXT-7564, EXT-7047 + // set text padding the same as in People panel. EXT-7047, EXT-4837 + text_p.h_pad(STATUS_TEXT_HPAD); + text_p.v_pad(STATUS_TEXT_VPAD); + mStatusTextBox = LLUICtrlFactory::create<LLTextBox> (text_p); + mStatusTextBox->setFollowsLeft(); + mStatusTextBox->setFollowsTop(); + //addChild(mStatusTextBox); + + + // make the popup menu available + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (!menu) + { + menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu"); + } + menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); + mPopupMenuHandle = menu->getHandle(); + + mViewModelItem->openItem(); +} + +// Destroys the object +LLFolderView::~LLFolderView( void ) +{ + closeRenamer(); + + // The release focus call can potentially call the + // scrollcontainer, which can potentially be called with a partly + // destroyed scollcontainer. Just null it out here, and no worries + // about calling into the invalid scroll container. + // Same with the renamer. + mScrollContainer = NULL; + mRenameItem = NULL; + mRenamer = NULL; + mStatusTextBox = NULL; + + mAutoOpenItems.removeAllNodes(); + + if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); + + mAutoOpenItems.removeAllNodes(); + clearSelection(); + mItems.clear(); + mFolders.clear(); + + delete mViewModel; + mViewModel = NULL; +} + +BOOL LLFolderView::canFocusChildren() const +{ + return FALSE; +} + +BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) +{ + LLFolderViewFolder::addFolder(folder); + + // TODO RN: enforce sort order of My Inventory followed by Library + //mFolders.remove(folder); + //if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) + //{ + // mFolders.push_back(folder); + //} + //else + //{ + // mFolders.insert(mFolders.begin(), folder); + //} + + return TRUE; +} + +void LLFolderView::closeAllFolders() +{ + // Close all the folders + setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); + arrangeAll(); +} + +void LLFolderView::openTopLevelFolders() +{ + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setOpen(TRUE); + } +} + +// This view grows and shrinks to enclose all of its children items and folders. +// *width should be 0 +// conform show folder state works +S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) +{ + mMinWidth = 0; + S32 target_height; + + LLFolderViewFolder::arrange(&mMinWidth, &target_height); + + LLRect scroll_rect = mScrollContainer->getContentWindowRect(); + reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); + + LLRect new_scroll_rect = mScrollContainer->getContentWindowRect(); + if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) + { + reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); + } + + // move item renamer text field to item's new position + updateRenamerPosition(); + + return llround(mTargetHeight); +} + +static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View"); + +void LLFolderView::filter( LLFolderViewFilter& filter ) +{ + LLFastTimer t2(FTM_FILTER); + filter.setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); + + getViewModelItem()->filter(filter); +} + +void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + LLRect scroll_rect; + if (mScrollContainer) + { + LLView::reshape(width, height, called_from_parent); + scroll_rect = mScrollContainer->getContentWindowRect(); + } + width = llmax(mMinWidth, scroll_rect.getWidth()); + height = llmax(llround(mCurHeight), scroll_rect.getHeight()); + + // Restrict width within scroll container's width + if (mUseEllipses && mScrollContainer) + { + width = scroll_rect.getWidth(); + } + + LLView::reshape(width, height, called_from_parent); + mReshapeSignal(mSelectedItems, FALSE); +} + +void LLFolderView::addToSelectionList(LLFolderViewItem* item) +{ + if (item->isSelected()) + { + removeFromSelectionList(item); + } + if (mSelectedItems.size()) + { + mSelectedItems.back()->setIsCurSelection(FALSE); + } + item->setIsCurSelection(TRUE); + mSelectedItems.push_back(item); +} + +void LLFolderView::removeFromSelectionList(LLFolderViewItem* item) +{ + if (mSelectedItems.size()) + { + mSelectedItems.back()->setIsCurSelection(FALSE); + } + + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end();) + { + if (*item_iter == item) + { + item_iter = mSelectedItems.erase(item_iter); + } + else + { + ++item_iter; + } + } + if (mSelectedItems.size()) + { + mSelectedItems.back()->setIsCurSelection(TRUE); + } +} + +LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) +{ + if(mSelectedItems.size()) + { + LLFolderViewItem* itemp = mSelectedItems.back(); + llassert(itemp->getIsCurSelection()); + return itemp; + } + return NULL; +} + + +// Record the selected item and pass it down the hierachy. +BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, + BOOL take_keyboard_focus) +{ + mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; + + if( selection == this ) + { + return FALSE; + } + + if( selection && take_keyboard_focus) + { + mParentPanel->setFocus(TRUE); + } + + // clear selection down here because change of keyboard focus can potentially + // affect selection + clearSelection(); + + if(selection) + { + addToSelectionList(selection); + } + + BOOL rv = LLFolderViewFolder::setSelection(selection, openitem, take_keyboard_focus); + if(openitem && selection) + { + selection->getParentFolder()->requestArrange(); + } + + llassert(mSelectedItems.size() <= 1); + + return rv; +} + +BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) +{ + BOOL rv = FALSE; + + // can't select root folder + if(!selection || selection == this) + { + return FALSE; + } + + if (!mAllowMultiSelect) + { + clearSelection(); + } + + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) + { + if (*item_iter == selection) + { + break; + } + } + + BOOL on_list = (item_iter != mSelectedItems.end()); + + if(selected && !on_list) + { + addToSelectionList(selection); + } + if(!selected && on_list) + { + removeFromSelectionList(selection); + } + + rv = LLFolderViewFolder::changeSelection(selection, selected); + + mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; + + return rv; +} + +static LLFastTimer::DeclareTimer FTM_SANITIZE_SELECTION("Sanitize Selection"); +void LLFolderView::sanitizeSelection() +{ + LLFastTimer _(FTM_SANITIZE_SELECTION); + // store off current item in case it is automatically deselected + // and we want to preserve context + LLFolderViewItem* original_selected_item = getCurSelectedItem(); + + std::vector<LLFolderViewItem*> items_to_remove; + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) + { + LLFolderViewItem* item = *item_iter; + + // ensure that each ancestor is open and potentially passes filtering + BOOL visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item + // modify with parent open and filters states + LLFolderViewFolder* parent_folder = item->getParentFolder(); + // Move up through parent folders and see what's visible + while(parent_folder) + { + visible = visible && parent_folder->isOpen() && parent_folder->getViewModelItem()->potentiallyVisible(); + parent_folder = parent_folder->getParentFolder(); + } + + // deselect item if any ancestor is closed or didn't pass filter requirements. + if (!visible) + { + items_to_remove.push_back(item); + } + + // disallow nested selections (i.e. folder items plus one or more ancestors) + // could check cached mum selections count and only iterate if there are any + // but that may be a premature optimization. + selected_items_t::iterator other_item_iter; + for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) + { + LLFolderViewItem* other_item = *other_item_iter; + for( parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) + { + if (parent_folder == item) + { + // this is a descendent of the current folder, remove from list + items_to_remove.push_back(other_item); + break; + } + } + } + + // Don't allow invisible items (such as root folders) to be selected. + if (item == getRoot()) + { + items_to_remove.push_back(item); + } + } + + std::vector<LLFolderViewItem*>::iterator item_it; + for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) + { + changeSelection(*item_it, FALSE); // toggle selection (also removes from list) + } + + // if nothing selected after prior constraints... + if (mSelectedItems.empty()) + { + // ...select first available parent of original selection + LLFolderViewItem* new_selection = NULL; + if (original_selected_item) + { + for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder(); + parent_folder; + parent_folder = parent_folder->getParentFolder()) + { + if (parent_folder->getViewModelItem()->potentiallyVisible()) + { + // give initial selection to first ancestor folder that potentially passes the filter + if (!new_selection) + { + new_selection = parent_folder; + } + + // if any ancestor folder of original item is closed, move the selection up + // to the highest closed + if (!parent_folder->isOpen()) + { + new_selection = parent_folder; + } + } + } + } + else + { + new_selection = NULL; + } + + if (new_selection) + { + setSelection(new_selection, FALSE, FALSE); + } + } +} + +void LLFolderView::clearSelection() +{ + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); + item_it != mSelectedItems.end(); + ++item_it) + { + (*item_it)->setUnselected(); + } + + mSelectedItems.clear(); +} + +std::set<LLFolderViewItem*> LLFolderView::getSelectionList() const +{ + std::set<LLFolderViewItem*> selection; + std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin())); + return selection; +} + +bool LLFolderView::startDrag() +{ + std::vector<LLFolderViewModelItem*> selected_items; + selected_items_t::iterator item_it; + + if (!mSelectedItems.empty()) + { + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + selected_items.push_back((*item_it)->getViewModelItem()); + } + + return getFolderViewModel()->startDrag(selected_items); + } + return false; +} + +void LLFolderView::commitRename( const LLSD& data ) +{ + finishRenamingItem(); +} + +void LLFolderView::draw() +{ + //LLFontGL* font = getLabelFontForStyle(mLabelStyle); + + // if cursor has moved off of me during drag and drop + // close all auto opened folders + if (!mDragAndDropThisFrame) + { + closeAutoOpenedFolders(); + } + + if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout") || !mSearchString.size()) + { + mSearchString.clear(); + } + + if (hasVisibleChildren()) + { + mStatusTextBox->setVisible( FALSE ); + } + else if (mShowEmptyMessage) + { + mStatusTextBox->setValue(getFolderViewModel()->getStatusText()); + mStatusTextBox->setVisible( TRUE ); + + // firstly reshape message textbox with current size. This is necessary to + // LLTextBox::getTextPixelHeight works properly + const LLRect local_rect = getLocalRect(); + mStatusTextBox->setShape(local_rect); + + // get preferable text height... + S32 pixel_height = mStatusTextBox->getTextPixelHeight(); + bool height_changed = local_rect.getHeight() != pixel_height; + if (height_changed) + { + // ... if it does not match current height, lets rearrange current view. + // This will indirectly call ::arrange and reshape of the status textbox. + // We should call this method to also notify parent about required rect. + // See EXT-7564, EXT-7047. + S32 height = 0; + S32 width = 0; + S32 total_height = arrange( &width, &height ); + notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); + + LLUI::popMatrix(); + LLUI::pushMatrix(); + LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); + } + } + + // skip over LLFolderViewFolder::draw since we don't want the folder icon, label, + // and arrow for the root folder + LLView::draw(); + + mDragAndDropThisFrame = FALSE; +} + +void LLFolderView::finishRenamingItem( void ) +{ + if(!mRenamer) + { + return; + } + if( mRenameItem ) + { + mRenameItem->rename( mRenamer->getText() ); + } + + closeRenamer(); + + // List is re-sorted alphabetically, so scroll to make sure the selected item is visible. + scrollToShowSelection(); +} + +void LLFolderView::closeRenamer( void ) +{ + if (mRenamer && mRenamer->getVisible()) + { + // Triggers onRenamerLost() that actually closes the renamer. + LLUI::removePopup(mRenamer); + } +} + +bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector<LLFolderViewItem*>& selectedItems) +{ + LLFolderViewItem* item_parent = dynamic_cast<LLFolderViewItem*>(item->getParent()); + + if (item_parent) + { + for(std::vector<LLFolderViewItem*>::const_iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) + { + const LLFolderViewItem* const selected_item = (*it); + + LLFolderViewItem* parent = item_parent; + + while (parent) + { + if (selected_item == parent) + { + return true; + } + + parent = dynamic_cast<LLFolderViewItem*>(parent->getParent()); + } + } + } + + return false; +} + +void LLFolderView::removeSelectedItems() +{ + if(getVisible() && getEnabled()) + { + // just in case we're removing the renaming item. + mRenameItem = NULL; + + // create a temporary structure which we will use to remove + // items, since the removal will futz with internal data + // structures. + std::vector<LLFolderViewItem*> items; + S32 count = mSelectedItems.size(); + if(count == 0) return; + LLFolderViewItem* item = NULL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + item = *item_it; + if (item && item->isRemovable()) + { + items.push_back(item); + } + else + { + llinfos << "Cannot delete " << item->getName() << llendl; + return; + } + } + + // iterate through the new container. + count = items.size(); + LLUUID new_selection_id; + if(count == 1) + { + LLFolderViewItem* item_to_delete = items[0]; + LLFolderViewFolder* parent = item_to_delete->getParentFolder(); + LLFolderViewItem* new_selection = item_to_delete->getNextOpenNode(FALSE); + if (!new_selection) + { + new_selection = item_to_delete->getPreviousOpenNode(FALSE); + } + if(parent) + { + if (item_to_delete->remove()) + { + // change selection on successful delete + if (new_selection) + { + getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); + } + else + { + getRoot()->setSelection(NULL, mParentPanel->hasFocus()); + } + } + } + arrangeAll(); + } + else if (count > 1) + { + LLDynamicArray<LLFolderViewModelItem*> listeners; + LLFolderViewModelItem* listener; + LLFolderViewItem* last_item = items[count - 1]; + LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); + while(new_selection && new_selection->isSelected()) + { + new_selection = new_selection->getNextOpenNode(FALSE); + } + if (!new_selection) + { + new_selection = last_item->getPreviousOpenNode(FALSE); + while (new_selection && (new_selection->isSelected() || isDescendantOfASelectedItem(new_selection, items))) + { + new_selection = new_selection->getPreviousOpenNode(FALSE); + } + } + if (new_selection) + { + getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); + } + else + { + getRoot()->setSelection(NULL, mParentPanel->hasFocus()); + } + + for(S32 i = 0; i < count; ++i) + { + listener = items[i]->getViewModelItem(); + if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewModelItem*>::FAIL)) + { + listeners.put(listener); + } + } + listener = static_cast<LLFolderViewModelItem*>(listeners.get(0)); + if(listener) + { + listener->removeBatch(listeners); + } + } + arrangeAll(); + scrollToShowSelection(); + } +} + +// TODO RN: abstract +// open the selected item. +void LLFolderView::openSelectedItems( void ) +{ + //TODO RN: get working again + //if(getVisible() && getEnabled()) + //{ + // if (mSelectedItems.size() == 1) + // { + // mSelectedItems.front()->openItem(); + // } + // else + // { + // LLMultiPreview* multi_previewp = new LLMultiPreview(); + // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + + // selected_items_t::iterator item_it; + // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + // { + // // IT_{OBJECT,ATTACHMENT} creates LLProperties + // // floaters; others create LLPreviews. Put + // // each one in the right type of container. + // LLFolderViewModelItemInventory* listener = static_cast<LLFolderViewModelItemInventory*>((*item_it)->getViewModelItem()); + // bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); + // if (is_prop) + // LLFloater::setFloaterHost(multi_propertiesp); + // else + // LLFloater::setFloaterHost(multi_previewp); + // listener->openItem(); + // } + + // LLFloater::setFloaterHost(NULL); + // // *NOTE: LLMulti* will safely auto-delete when open'd + // // without any children. + // multi_previewp->openFloater(LLSD()); + // multi_propertiesp->openFloater(LLSD()); + // } + //} +} + +void LLFolderView::propertiesSelectedItems( void ) +{ + //TODO RN: get working again + //if(getVisible() && getEnabled()) + //{ + // if (mSelectedItems.size() == 1) + // { + // LLFolderViewItem* folder_item = mSelectedItems.front(); + // if(!folder_item) return; + // folder_item->getViewModelItem()->showProperties(); + // } + // else + // { + // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + + // LLFloater::setFloaterHost(multi_propertiesp); + + // selected_items_t::iterator item_it; + // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + // { + // (*item_it)->getViewModelItem()->showProperties(); + // } + + // LLFloater::setFloaterHost(NULL); + // multi_propertiesp->openFloater(LLSD()); + // } + //} +} + + +void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) +{ + if ((mAutoOpenItems.check() == item) || + (mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) || + item->isOpen()) + { + return; + } + + // close auto-opened folders + LLFolderViewFolder* close_item = mAutoOpenItems.check(); + while (close_item && close_item != item->getParentFolder()) + { + mAutoOpenItems.pop(); + close_item->setOpenArrangeRecursively(FALSE); + close_item = mAutoOpenItems.check(); + } + + item->requestArrange(); + + mAutoOpenItems.push(item); + + item->setOpen(TRUE); + LLRect content_rect = mScrollContainer->getContentWindowRect(); + LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0); + scrollToShowItem(item, constraint_rect); +} + +void LLFolderView::closeAutoOpenedFolders() +{ + while (mAutoOpenItems.check()) + { + LLFolderViewFolder* close_item = mAutoOpenItems.pop(); + close_item->setOpen(FALSE); + } + + if (mAutoOpenCandidate) + { + mAutoOpenCandidate->setAutoOpenCountdown(0.f); + } + mAutoOpenCandidate = NULL; + mAutoOpenTimer.stop(); +} + +BOOL LLFolderView::autoOpenTest(LLFolderViewFolder* folder) +{ + if (folder && mAutoOpenCandidate == folder) + { + if (mAutoOpenTimer.getStarted()) + { + if (!mAutoOpenCandidate->isOpen()) + { + mAutoOpenCandidate->setAutoOpenCountdown(clamp_rescale(mAutoOpenTimer.getElapsedTimeF32(), 0.f, sAutoOpenTime, 0.f, 1.f)); + } + if (mAutoOpenTimer.getElapsedTimeF32() > sAutoOpenTime) + { + autoOpenItem(folder); + mAutoOpenTimer.stop(); + return TRUE; + } + } + return FALSE; + } + + // otherwise new candidate, restart timer + if (mAutoOpenCandidate) + { + mAutoOpenCandidate->setAutoOpenCountdown(0.f); + } + mAutoOpenCandidate = folder; + mAutoOpenTimer.start(); + return FALSE; +} + +BOOL LLFolderView::canCopy() const +{ + if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) + { + return FALSE; + } + + for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) + { + const LLFolderViewItem* item = *selected_it; + if (!item->getViewModelItem()->isItemCopyable()) + { + return FALSE; + } + } + return TRUE; +} + +// copy selected item +void LLFolderView::copy() +{ + // *NOTE: total hack to clear the inventory clipboard + LLClipboard::instance().reset(); + S32 count = mSelectedItems.size(); + if(getVisible() && getEnabled() && (count > 0)) + { + LLFolderViewModelItem* listener = NULL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + listener = (*item_it)->getViewModelItem(); + if(listener) + { + listener->copyToClipboard(); + } + } + } + mSearchString.clear(); +} + +BOOL LLFolderView::canCut() const +{ + if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) + { + return FALSE; + } + + for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) + { + const LLFolderViewItem* item = *selected_it; + const LLFolderViewModelItem* listener = item->getViewModelItem(); + + if (!listener || !listener->isItemRemovable()) + { + return FALSE; + } + } + return TRUE; +} + +void LLFolderView::cut() +{ + // clear the inventory clipboard + LLClipboard::instance().reset(); + S32 count = mSelectedItems.size(); + if(getVisible() && getEnabled() && (count > 0)) + { + LLFolderViewModelItem* listener = NULL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + listener = (*item_it)->getViewModelItem(); + if(listener) + { + listener->cutToClipboard(); + listener->removeItem(); + } + } + } + mSearchString.clear(); +} + +BOOL LLFolderView::canPaste() const +{ + if (mSelectedItems.empty()) + { + return FALSE; + } + + if(getVisible() && getEnabled()) + { + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); + item_it != mSelectedItems.end(); ++item_it) + { + // *TODO: only check folders and parent folders of items + const LLFolderViewItem* item = (*item_it); + const LLFolderViewModelItem* listener = item->getViewModelItem(); + if(!listener || !listener->isClipboardPasteable()) + { + const LLFolderViewFolder* folderp = item->getParentFolder(); + listener = folderp->getViewModelItem(); + if (!listener || !listener->isClipboardPasteable()) + { + return FALSE; + } + } + } + return TRUE; + } + return FALSE; +} + +// paste selected item +void LLFolderView::paste() +{ + if(getVisible() && getEnabled()) + { + // find set of unique folders to paste into + std::set<LLFolderViewFolder*> folder_set; + + selected_items_t::iterator selected_it; + for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) + { + LLFolderViewItem* item = *selected_it; + LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(item); + if (folder == NULL) + { + item = item->getParentFolder(); + } + folder_set.insert(folder); + } + + std::set<LLFolderViewFolder*>::iterator set_iter; + for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) + { + LLFolderViewModelItem* listener = (*set_iter)->getViewModelItem(); + if(listener && listener->isClipboardPasteable()) + { + listener->pasteFromClipboard(); + } + } + } + mSearchString.clear(); +} + +// public rename functionality - can only start the process +void LLFolderView::startRenamingSelectedItem( void ) +{ + // make sure selection is visible + scrollToShowSelection(); + + S32 count = mSelectedItems.size(); + LLFolderViewItem* item = NULL; + if(count > 0) + { + item = mSelectedItems.front(); + } + if(getVisible() && getEnabled() && (count == 1) && item && item->getViewModelItem() && + item->getViewModelItem()->isItemRenameable()) + { + mRenameItem = item; + + updateRenamerPosition(); + + + mRenamer->setText(item->getName()); + mRenamer->selectAll(); + mRenamer->setVisible( TRUE ); + // set focus will fail unless item is visible + mRenamer->setFocus( TRUE ); + mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); + LLUI::addPopup(mRenamer); + } +} + +BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) +{ + BOOL handled = FALSE; + + // SL-51858: Key presses are not being passed to the Popup menu. + // A proper fix is non-trivial so instead just close the menu. + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->isOpen()) + { + LLMenuGL::sMenuContainer->hideMenus(); + } + + LLView *item = NULL; + if (getChildCount() > 0) + { + item = *(getChildList()->begin()); + } + + switch( key ) + { + case KEY_F2: + mSearchString.clear(); + startRenamingSelectedItem(); + handled = TRUE; + break; + + case KEY_RETURN: + if (mask == MASK_NONE) + { + if( mRenameItem && mRenamer->getVisible() ) + { + finishRenamingItem(); + mSearchString.clear(); + handled = TRUE; + } + else + { + LLFolderView::openSelectedItems(); + handled = TRUE; + } + } + break; + + case KEY_ESCAPE: + if( mRenameItem && mRenamer->getVisible() ) + { + closeRenamer(); + handled = TRUE; + } + mSearchString.clear(); + break; + + case KEY_PAGE_UP: + mSearchString.clear(); + mScrollContainer->pageUp(30); + handled = TRUE; + break; + + case KEY_PAGE_DOWN: + mSearchString.clear(); + mScrollContainer->pageDown(30); + handled = TRUE; + break; + + case KEY_HOME: + mSearchString.clear(); + mScrollContainer->goToTop(); + handled = TRUE; + break; + + case KEY_END: + mSearchString.clear(); + mScrollContainer->goToBottom(); + break; + + case KEY_DOWN: + if((mSelectedItems.size() > 0) && mScrollContainer) + { + LLFolderViewItem* last_selected = getCurSelectedItem(); + + if (!mKeyboardSelection) + { + setSelection(last_selected, FALSE, TRUE); + mKeyboardSelection = TRUE; + } + + LLFolderViewItem* next = NULL; + if (mask & MASK_SHIFT) + { + // don't shift select down to children of folders (they are implicitly selected through parent) + next = last_selected->getNextOpenNode(FALSE); + if (next) + { + if (next->isSelected()) + { + // shrink selection + getRoot()->changeSelection(last_selected, FALSE); + } + else if (last_selected->getParentFolder() == next->getParentFolder()) + { + // grow selection + getRoot()->changeSelection(next, TRUE); + } + } + } + else + { + next = last_selected->getNextOpenNode(); + if( next ) + { + if (next == last_selected) + { + //special case for LLAccordionCtrl + if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed + { + clearSelection(); + return TRUE; + } + return FALSE; + } + setSelection( next, FALSE, TRUE ); + } + else + { + //special case for LLAccordionCtrl + if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed + { + clearSelection(); + return TRUE; + } + return FALSE; + } + } + scrollToShowSelection(); + mSearchString.clear(); + handled = TRUE; + } + break; + + case KEY_UP: + if((mSelectedItems.size() > 0) && mScrollContainer) + { + LLFolderViewItem* last_selected = mSelectedItems.back(); + + if (!mKeyboardSelection) + { + setSelection(last_selected, FALSE, TRUE); + mKeyboardSelection = TRUE; + } + + LLFolderViewItem* prev = NULL; + if (mask & MASK_SHIFT) + { + // don't shift select down to children of folders (they are implicitly selected through parent) + prev = last_selected->getPreviousOpenNode(FALSE); + if (prev) + { + if (prev->isSelected()) + { + // shrink selection + getRoot()->changeSelection(last_selected, FALSE); + } + else if (last_selected->getParentFolder() == prev->getParentFolder()) + { + // grow selection + getRoot()->changeSelection(prev, TRUE); + } + } + } + else + { + prev = last_selected->getPreviousOpenNode(); + if( prev ) + { + if (prev == this) + { + // If case we are in accordion tab notify parent to go to the previous accordion + if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed + { + clearSelection(); + return TRUE; + } + + return FALSE; + } + setSelection( prev, FALSE, TRUE ); + } + } + scrollToShowSelection(); + mSearchString.clear(); + + handled = TRUE; + } + break; + + case KEY_RIGHT: + if(mSelectedItems.size()) + { + LLFolderViewItem* last_selected = getCurSelectedItem(); + last_selected->setOpen( TRUE ); + mSearchString.clear(); + handled = TRUE; + } + break; + + case KEY_LEFT: + if(mSelectedItems.size()) + { + LLFolderViewItem* last_selected = getCurSelectedItem(); + LLFolderViewItem* parent_folder = last_selected->getParentFolder(); + if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder()) + { + setSelection(parent_folder, FALSE, TRUE); + } + else + { + last_selected->setOpen( FALSE ); + } + mSearchString.clear(); + scrollToShowSelection(); + handled = TRUE; + } + break; + } + + if (!handled && mParentPanel->hasFocus()) + { + if (key == KEY_BACKSPACE) + { + mSearchTimer.reset(); + if (mSearchString.size()) + { + mSearchString.erase(mSearchString.size() - 1, 1); + } + search(getCurSelectedItem(), mSearchString, FALSE); + handled = TRUE; + } + } + + return handled; +} + + +BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) +{ + if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL + { + return FALSE; + } + + if (uni_char > 0x7f) + { + llwarns << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << llendl; + return FALSE; + } + + BOOL handled = FALSE; + if (mParentPanel->hasFocus()) + { + // SL-51858: Key presses are not being passed to the Popup menu. + // A proper fix is non-trivial so instead just close the menu. + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->isOpen()) + { + LLMenuGL::sMenuContainer->hideMenus(); + } + + //do text search + if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout")) + { + mSearchString.clear(); + } + mSearchTimer.reset(); + if (mSearchString.size() < 128) + { + mSearchString += uni_char; + } + search(getCurSelectedItem(), mSearchString, FALSE); + + handled = TRUE; + } + + return handled; +} + + +BOOL LLFolderView::canDoDelete() const +{ + if (mSelectedItems.size() == 0) return FALSE; + + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + if (!(*item_it)->getViewModelItem()->isItemRemovable()) + { + return FALSE; + } + } + return TRUE; +} + +void LLFolderView::doDelete() +{ + if(mSelectedItems.size() > 0) + { + removeSelectedItems(); + } +} + + +BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + mKeyboardSelection = FALSE; + mSearchString.clear(); + + mParentPanel->setFocus(TRUE); + + LLEditMenuHandler::gEditMenuHandler = this; + + return LLView::handleMouseDown( x, y, mask ); +} + +BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward) +{ + // get first selected item + LLFolderViewItem* search_item = first_item; + + // make sure search string is upper case + std::string upper_case_string = search_string; + LLStringUtil::toUpper(upper_case_string); + + // if nothing selected, select first item in folder + if (!search_item) + { + // start from first item + search_item = getNextFromChild(NULL); + } + + // search over all open nodes for first substring match (with wrapping) + BOOL found = FALSE; + LLFolderViewItem* original_search_item = search_item; + do + { + // wrap at end + if (!search_item) + { + if (backward) + { + search_item = getPreviousFromChild(NULL); + } + else + { + search_item = getNextFromChild(NULL); + } + if (!search_item || search_item == original_search_item) + { + break; + } + } + + const std::string current_item_label(search_item->getViewModelItem()->getSearchableName()); + S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); + if (!current_item_label.compare(0, search_string_length, upper_case_string)) + { + found = TRUE; + break; + } + if (backward) + { + search_item = search_item->getPreviousOpenNode(); + } + else + { + search_item = search_item->getNextOpenNode(); + } + + } while(search_item != original_search_item); + + + if (found) + { + setSelection(search_item, FALSE, TRUE); + scrollToShowSelection(); + } + + return found; +} + +BOOL LLFolderView::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + // skip LLFolderViewFolder::handleDoubleClick() + return LLView::handleDoubleClick( x, y, mask ); +} + +BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + // all user operations move keyboard focus to inventory + // this way, we know when to stop auto-updating a search + mParentPanel->setFocus(TRUE); + + BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL; + S32 count = mSelectedItems.size(); + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if ( handled + && ( count > 0 && (hasVisibleChildren()) ) // show menu only if selected items are visible + && menu ) + { + if (mCallbackRegistrar) + mCallbackRegistrar->pushScope(); + + updateMenuOptions(menu); + + menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, menu, x, y); + if (mCallbackRegistrar) + mCallbackRegistrar->popScope(); + } + else + { + if (menu && menu->getVisible()) + { + menu->setVisible(FALSE); + } + setSelection(NULL, FALSE, TRUE); + } + return handled; +} + +// Add "--no options--" if the menu is completely blank. +BOOL LLFolderView::addNoOptions(LLMenuGL* menu) const +{ + const std::string nooptions_str = "--no options--"; + LLView *nooptions_item = NULL; + + const LLView::child_list_t *list = menu->getChildList(); + for (LLView::child_list_t::const_iterator itor = list->begin(); + itor != list->end(); + ++itor) + { + LLView *menu_item = (*itor); + if (menu_item->getVisible()) + { + return FALSE; + } + std::string name = menu_item->getName(); + if (menu_item->getName() == nooptions_str) + { + nooptions_item = menu_item; + } + } + if (nooptions_item) + { + nooptions_item->setVisible(TRUE); + nooptions_item->setEnabled(FALSE); + return TRUE; + } + return FALSE; +} + +BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask ) +{ + return LLView::handleHover( x, y, mask ); +} + +BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + mDragAndDropThisFrame = TRUE; + // have children handle it first + BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, + accept, tooltip_msg); + + // when drop is not handled by child, it should be handled + // by the folder which is the hierarchy root. + if (!handled) + { + handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + + return handled; +} + +void LLFolderView::deleteAllChildren() +{ + closeRenamer(); + if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); + mPopupMenuHandle = LLHandle<LLView>(); + mScrollContainer = NULL; + mRenameItem = NULL; + mRenamer = NULL; + mStatusTextBox = NULL; + + clearSelection(); + LLView::deleteAllChildren(); +} + +void LLFolderView::scrollToShowSelection() +{ + if ( mSelectedItems.size() ) + { + mNeedsScroll = TRUE; + } +} + +// If the parent is scroll container, scroll it to make the selection +// is maximally visible. +void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect) +{ + if (!mScrollContainer) return; + + // don't scroll to items when mouse is being used to scroll/drag and drop + if (gFocusMgr.childHasMouseCapture(mScrollContainer)) + { + mNeedsScroll = FALSE; + return; + } + + // if item exists and is in visible portion of parent folder... + if(item) + { + LLRect local_rect = item->getLocalRect(); + LLRect item_scrolled_rect; // item position relative to display area of scroller + LLRect visible_doc_rect = mScrollContainer->getVisibleContentRect(); + + S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); + S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight(); + // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder + S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); + + // get portion of item that we want to see... + LLRect item_local_rect = LLRect(item->getIndentation(), + local_rect.getHeight(), + llmin(MIN_ITEM_WIDTH_VISIBLE, local_rect.getWidth()), + llmax(0, local_rect.getHeight() - max_height_to_show)); + + LLRect item_doc_rect; + + item->localRectToOtherView(item_local_rect, &item_doc_rect, this); + + mScrollContainer->scrollToShowRect( item_doc_rect, constraint_rect ); + + } +} + +LLRect LLFolderView::getVisibleRect() +{ + S32 visible_height = mScrollContainer->getRect().getHeight(); + S32 visible_width = mScrollContainer->getRect().getWidth(); + LLRect visible_rect; + visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height); + return visible_rect; +} + +BOOL LLFolderView::getShowSelectionContext() +{ + if (mShowSelectionContext) + { + return TRUE; + } + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->getVisible()) + { + return TRUE; + } + return FALSE; +} + +void LLFolderView::setShowSingleSelection(BOOL show) +{ + if (show != mShowSingleSelection) + { + mMultiSelectionFadeTimer.reset(); + mShowSingleSelection = show; + } +} + +static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select"); +static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory"); + +// Main idle routine +void LLFolderView::update() +{ + // If this is associated with the user's inventory, don't do anything + // until that inventory is loaded up. + LLFastTimer t2(FTM_INVENTORY); + + if (getFolderViewModel()->getFilter()->isModified() && getFolderViewModel()->getFilter()->isNotDefault()) + { + mNeedsAutoSelect = TRUE; + } + getFolderViewModel()->getFilter()->clearModified(); + + // filter to determine visibility before arranging + filter(*(getFolderViewModel()->getFilter())); + + // automatically show matching items, and select first one if we had a selection + if (mNeedsAutoSelect) + { + LLFastTimer t3(FTM_AUTO_SELECT); + // select new item only if a filtered item not currently selected + LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); + if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->getViewModelItem()->potentiallyVisible())) + { + // these are named variables to get around gcc not binding non-const references to rvalues + // and functor application is inherently non-const to allow for stateful functors + LLSelectFirstFilteredItem functor; + applyFunctorRecursively(functor); + } + + // Open filtered folders for folder views with mAutoSelectOverride=TRUE. + // Used by LLPlacesFolderView. + if (getFolderViewModel()->getFilter()->showAllResults()) + { + // these are named variables to get around gcc not binding non-const references to rvalues + // and functor application is inherently non-const to allow for stateful functors + LLOpenFilteredFolders functor; + applyFunctorRecursively(functor); + } + + scrollToShowSelection(); + } + + BOOL filter_finished = getViewModelItem()->passedFilter() + && mViewModel->contentsReady(); + if (filter_finished + || gFocusMgr.childHasKeyboardFocus(getParent()) // assume we are inside a scroll container + || gFocusMgr.childHasMouseCapture(getParent())) + { + // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process + mNeedsAutoSelect = FALSE; + } + + + // during filtering process, try to pin selected item's location on screen + // this will happen when searching your inventory and when new items arrive + if (!filter_finished) + { + // calculate rectangle to pin item to at start of animated rearrange + if (!mPinningSelectedItem && !mSelectedItems.empty()) + { + // lets pin it! + mPinningSelectedItem = TRUE; + + LLRect visible_content_rect = mScrollContainer->getVisibleContentRect(); + LLFolderViewItem* selected_item = mSelectedItems.back(); + + LLRect item_rect; + selected_item->localRectToOtherView(selected_item->getLocalRect(), &item_rect, this); + // if item is visible in scrolled region + if (visible_content_rect.overlaps(item_rect)) + { + // then attempt to keep it in same place on screen + mScrollConstraintRect = item_rect; + mScrollConstraintRect.translate(-visible_content_rect.mLeft, -visible_content_rect.mBottom); + } + else + { + // otherwise we just want it onscreen somewhere + LLRect content_rect = mScrollContainer->getContentWindowRect(); + mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); + } + } + } + else + { + // stop pinning selected item after folders stop rearranging + if (!needsArrange()) + { + mPinningSelectedItem = FALSE; + } + } + + LLRect constraint_rect; + if (mPinningSelectedItem) + { + // use last known constraint rect for pinned item + constraint_rect = mScrollConstraintRect; + } + else + { + // during normal use (page up/page down, etc), just try to fit item on screen + LLRect content_rect = mScrollContainer->getContentWindowRect(); + constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); + } + + BOOL is_visible = isInVisibleChain(); + + if ( is_visible ) + { + sanitizeSelection(); + if( needsArrange() ) + { + S32 height = 0; + S32 width = 0; + S32 total_height = arrange( &width, &height ); + notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); + } + } + + if (mSelectedItems.size() && mNeedsScroll) + { + scrollToShowItem(mSelectedItems.back(), constraint_rect); + // continue scrolling until animated layout change is done + if (filter_finished + && (!needsArrange() || !is_visible)) + { + mNeedsScroll = FALSE; + } + } + + if (mSignalSelectCallback) + { + //RN: we use keyboard focus as a proxy for user-explicit actions + BOOL take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS); + mSelectSignal(mSelectedItems, take_keyboard_focus); + } + mSignalSelectCallback = FALSE; +} + +void LLFolderView::dumpSelectionInformation() +{ + llinfos << "LLFolderView::dumpSelectionInformation()" << llendl; + llinfos << "****************************************" << llendl; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + llinfos << " " << (*item_it)->getName() << llendl; + } + llinfos << "****************************************" << llendl; +} + +void LLFolderView::updateRenamerPosition() +{ + if(mRenameItem) + { + // See also LLFolderViewItem::draw() + S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mRenameItem->getIndentation(); + S32 y = mRenameItem->getRect().getHeight() - mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; + mRenameItem->localPointToScreen( x, y, &x, &y ); + screenPointToLocal( x, y, &x, &y ); + mRenamer->setOrigin( x, y ); + + LLRect scroller_rect(0, 0, LLUI::getWindowSize().mV[VX], 0); + if (mScrollContainer) + { + scroller_rect = mScrollContainer->getContentWindowRect(); + } + + S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); + S32 height = mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; + mRenamer->reshape( width, height, TRUE ); + } +} + +// Update visibility and availability (i.e. enabled/disabled) of context menu items. +void LLFolderView::updateMenuOptions(LLMenuGL* menu) +{ + const LLView::child_list_t *list = menu->getChildList(); + + LLView::child_list_t::const_iterator menu_itor; + for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor) + { + (*menu_itor)->setVisible(FALSE); + (*menu_itor)->pushVisible(TRUE); + (*menu_itor)->setEnabled(TRUE); + } + + // Successively filter out invalid options + + U32 flags = FIRST_SELECTED_ITEM; + for (selected_items_t::iterator item_itor = mSelectedItems.begin(); + item_itor != mSelectedItems.end(); + ++item_itor) + { + LLFolderViewItem* selected_item = (*item_itor); + selected_item->buildContextMenu(*menu, flags); + flags = 0x0; + } + + addNoOptions(menu); +} + +// Refresh the context menu (that is already shown). +void LLFolderView::updateMenu() +{ + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->getVisible()) + { + updateMenuOptions(menu); + menu->needsArrange(); // update menu height if needed + } +} + +bool LLFolderView::selectFirstItem() +{ + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();++iter) + { + LLFolderViewFolder* folder = (*iter ); + if (folder->getVisible()) + { + LLFolderViewItem* itemp = folder->getNextFromChild(0,true); + if(itemp) + setSelection(itemp,FALSE,TRUE); + return true; + } + + } + for(items_t::iterator iit = mItems.begin(); + iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + if (itemp->getVisible()) + { + setSelection(itemp,FALSE,TRUE); + return true; + } + } + return false; +} +bool LLFolderView::selectLastItem() +{ + for(items_t::reverse_iterator iit = mItems.rbegin(); + iit != mItems.rend(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + if (itemp->getVisible()) + { + setSelection(itemp,FALSE,TRUE); + return true; + } + } + for (folders_t::reverse_iterator iter = mFolders.rbegin(); + iter != mFolders.rend();++iter) + { + LLFolderViewFolder* folder = (*iter); + if (folder->getVisible()) + { + LLFolderViewItem* itemp = folder->getPreviousFromChild(0,true); + if(itemp) + setSelection(itemp,FALSE,TRUE); + return true; + } + } + return false; +} + + +S32 LLFolderView::notify(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "select_first") + { + setFocus(true); + selectFirstItem(); + scrollToShowSelection(); + return 1; + + } + else if(str_action == "select_last") + { + setFocus(true); + selectLastItem(); + scrollToShowSelection(); + return 1; + } + } + return 0; +} + + +///---------------------------------------------------------------------------- +/// Local function definitions +///---------------------------------------------------------------------------- + +void LLFolderView::onRenamerLost() +{ + if (mRenamer && mRenamer->getVisible()) + { + mRenamer->setVisible(FALSE); + + // will commit current name (which could be same as original name) + mRenamer->setFocus(FALSE); + } + + if( mRenameItem ) + { + setSelection( mRenameItem, TRUE ); + mRenameItem = NULL; + } +} + +S32 LLFolderView::getItemHeight() +{ + if(!hasVisibleChildren()) + { + //We need to display status textbox, let's reserve some place for it + return llmax(0, mStatusTextBox->getTextPixelHeight()); + } + return 0; +} diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h new file mode 100644 index 0000000000..ba37a11bbe --- /dev/null +++ b/indra/llui/llfolderview.h @@ -0,0 +1,388 @@ +/** + * @file llfolderview.h + * @brief Definition of the folder view collection of classes. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +/** + * + * The folder view collection of classes provides an interface for + * making a 'folder view' similar to the way the a single pane file + * folder interface works. + * + */ + +#ifndef LL_LLFOLDERVIEW_H +#define LL_LLFOLDERVIEW_H + +#include "llfolderviewitem.h" // because LLFolderView is-a LLFolderViewFolder + +#include "lluictrl.h" +#include "v4color.h" +#include "stdenums.h" +#include "lldepthstack.h" +#include "lleditmenuhandler.h" +#include "llfontgl.h" +#include "llscrollcontainer.h" + +class LLFolderViewModelInterface; +class LLFolderViewFolder; +class LLFolderViewItem; +class LLFolderViewFilter; +class LLPanel; +class LLLineEditor; +class LLMenuGL; +class LLUICtrl; +class LLTextBox; + +/** + * Class LLFolderViewScrollContainer + * + * A scroll container which provides the information about the height + * of currently displayed folder view contents. + * Used for updating vertical scroll bar visibility in inventory panel. + * See LLScrollContainer::calcVisibleSize(). + */ +class LLFolderViewScrollContainer : public LLScrollContainer +{ +public: + /*virtual*/ ~LLFolderViewScrollContainer() {}; + /*virtual*/ const LLRect getScrolledViewRect() const; + +protected: + LLFolderViewScrollContainer(const LLScrollContainer::Params& p); + friend class LLUICtrlFactory; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderView +// +// The LLFolderView represents the root level folder view object. +// It manages the screen region of the folder view. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler +{ +public: + struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params> + { + Mandatory<LLPanel*> parent_panel; + Optional<std::string> title; + Optional<bool> use_label_suffix, + allow_multiselect, + show_empty_message, + use_ellipses, + show_item_link_overlays; + Mandatory<LLFolderViewModelInterface*> view_model; + + Params(); + }; + + friend class LLFolderViewScrollContainer; + + LLFolderView(const Params&); + virtual ~LLFolderView( void ); + + virtual BOOL canFocusChildren() const; + + virtual const LLFolderView* getRoot() const { return this; } + virtual LLFolderView* getRoot() { return this; } + + LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } + const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; } + + typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t; + void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } + void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } + + bool getAllowMultiSelect() { return mAllowMultiSelect; } + + // Close all folders in the view + void closeAllFolders(); + void openTopLevelFolders(); + + virtual BOOL addFolder( LLFolderViewFolder* folder); + + // Find width and height of this object and its children. Also + // makes sure that this view and its children are the right size. + virtual S32 arrange( S32* width, S32* height ); + virtual S32 getItemHeight(); + + void arrangeAll() { mArrangeGeneration++; } + S32 getArrangeGeneration() { return mArrangeGeneration; } + + // applies filters to control visibility of items + virtual void filter( LLFolderViewFilter& filter); + + // Get the last selected item + virtual LLFolderViewItem* getCurSelectedItem( void ); + + // Record the selected item and pass it down the hierarchy. + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, + BOOL take_keyboard_focus = TRUE); + + // This method is used to toggle the selection of an item. Walks + // children, and keeps track of selected objects. + virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); + + virtual std::set<LLFolderViewItem*> getSelectionList() const; + S32 getNumSelectedItems() { return mSelectedItems.size(); } + + // Make sure if ancestor is selected, descendants are not + void sanitizeSelection(); + virtual void clearSelection(); + void addToSelectionList(LLFolderViewItem* item); + void removeFromSelectionList(LLFolderViewItem* item); + + bool startDrag(); + void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; } + void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; } + LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; } + + // Deletion functionality + void removeSelectedItems(); + + // Open the selected item + void openSelectedItems( void ); + void propertiesSelectedItems( void ); + + void autoOpenItem(LLFolderViewFolder* item); + void closeAutoOpenedFolders(); + BOOL autoOpenTest(LLFolderViewFolder* item); + BOOL isOpen() const { return TRUE; } // root folder always open + + // Copy & paste + virtual void copy(); + virtual BOOL canCopy() const; + + virtual void cut(); + virtual BOOL canCut() const; + + virtual void paste(); + virtual BOOL canPaste() const; + + virtual void doDelete(); + virtual BOOL canDoDelete() const; + + // Public rename functionality - can only start the process + void startRenamingSelectedItem( void ); + + // LLView functionality + ///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent ); + /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); + /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char); + /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) { setShowSelectionContext(FALSE); } + virtual void draw(); + virtual void deleteAllChildren(); + + void scrollToShowSelection(); + void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect); + void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; } + LLRect getVisibleRect(); + + BOOL search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward); + void setShowSelectionContext(BOOL show) { mShowSelectionContext = show; } + BOOL getShowSelectionContext(); + void setShowSingleSelection(BOOL show); + BOOL getShowSingleSelection() { return mShowSingleSelection; } + F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } + bool getUseEllipses() { return mUseEllipses; } + + void update(); // needs to be called periodically (e.g. once per frame) + + BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; } + BOOL needsAutoRename() { return mNeedsAutoRename; } + void setNeedsAutoRename(BOOL val) { mNeedsAutoRename = val; } + void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; } + void setAutoSelectOverride(BOOL val) { mAutoSelectOverride = val; } + + bool showItemLinkOverlays() { return mShowItemLinkOverlays; } + + void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } + + LLPanel* getParentPanel() { return mParentPanel; } + // DEBUG only + void dumpSelectionInformation(); + + virtual S32 notify(const LLSD& info) ; + + bool useLabelSuffix() { return mUseLabelSuffix; } + void updateMenu(); + +private: + void updateMenuOptions(LLMenuGL* menu); + void updateRenamerPosition(); + +protected: + LLScrollContainer* mScrollContainer; // NULL if this is not a child of a scroll container. + + void commitRename( const LLSD& data ); + void onRenamerLost(); + + void finishRenamingItem( void ); + void closeRenamer( void ); + + bool selectFirstItem(); + bool selectLastItem(); + + BOOL addNoOptions(LLMenuGL* menu) const; + + +protected: + LLHandle<LLView> mPopupMenuHandle; + + typedef std::deque<LLFolderViewItem*> selected_items_t; + selected_items_t mSelectedItems; + BOOL mKeyboardSelection; + BOOL mAllowMultiSelect; + BOOL mShowEmptyMessage; + BOOL mShowFolderHierarchy; + + // Renaming variables and methods + LLFolderViewItem* mRenameItem; // The item currently being renamed + LLLineEditor* mRenamer; + + BOOL mNeedsScroll; + BOOL mPinningSelectedItem; + LLRect mScrollConstraintRect; + BOOL mNeedsAutoSelect; + BOOL mAutoSelectOverride; + BOOL mNeedsAutoRename; + bool mUseLabelSuffix; + bool mShowItemLinkOverlays; + + LLDepthStack<LLFolderViewFolder> mAutoOpenItems; + LLFolderViewFolder* mAutoOpenCandidate; + LLFrameTimer mAutoOpenTimer; + LLFrameTimer mSearchTimer; + std::string mSearchString; + BOOL mShowSelectionContext; + BOOL mShowSingleSelection; + LLFrameTimer mMultiSelectionFadeTimer; + S32 mArrangeGeneration; + + signal_t mSelectSignal; + signal_t mReshapeSignal; + S32 mSignalSelectCallback; + S32 mMinWidth; + BOOL mDragAndDropThisFrame; + + LLPanel* mParentPanel; + + LLFolderViewModelInterface* mViewModel; + + /** + * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. + * NOTE: For now it's used only to cut LLFolderViewItem::mLabel text for Landmarks in Places Panel. + */ + bool mUseEllipses; // See EXT-719 + + /** + * Contains item under mouse pointer while dragging + */ + LLFolderViewItem* mDraggingOverItem; // See EXT-719 + + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar; + +public: + static F32 sAutoOpenTime; + LLTextBox* mStatusTextBox; + +}; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderViewFunctor +// +// Simple abstract base class for applying a functor to folders and +// items in a folder view hierarchy. This is suboptimal for algorithms +// that only work folders or only work on items, but I'll worry about +// that later when it's determined to be too slow. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLFolderViewFunctor +{ +public: + virtual ~LLFolderViewFunctor() {} + virtual void doFolder(LLFolderViewFolder* folder) = 0; + virtual void doItem(LLFolderViewItem* item) = 0; +}; + +class LLSelectFirstFilteredItem : public LLFolderViewFunctor +{ +public: + LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} + virtual ~LLSelectFirstFilteredItem() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); + BOOL wasItemSelected() { return mItemSelected; } +protected: + BOOL mItemSelected; +}; + +class LLOpenFilteredFolders : public LLFolderViewFunctor +{ +public: + LLOpenFilteredFolders() {} + virtual ~LLOpenFilteredFolders() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + +class LLSaveFolderState : public LLFolderViewFunctor +{ +public: + LLSaveFolderState() : mApply(FALSE) {} + virtual ~LLSaveFolderState() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item) {} + void setApply(BOOL apply); + void clearOpenFolders() { mOpenFolders.clear(); } +protected: + std::set<LLUUID> mOpenFolders; + BOOL mApply; +}; + +class LLOpenFoldersWithSelection : public LLFolderViewFunctor +{ +public: + LLOpenFoldersWithSelection() {} + virtual ~LLOpenFoldersWithSelection() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + +// Flags for buildContextMenu() +const U32 SUPPRESS_OPEN_ITEM = 0x1; +const U32 FIRST_SELECTED_ITEM = 0x2; + +#endif // LL_LLFOLDERVIEW_H diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp new file mode 100644 index 0000000000..741fc9c324 --- /dev/null +++ b/indra/llui/llfolderviewitem.cpp @@ -0,0 +1,2032 @@ +/** +* @file llfolderviewitem.cpp +* @brief Items and folders that can appear in a hierarchical folder view +* +* $LicenseInfo:firstyear=2001&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#include "linden_common.h" +#include "llfolderviewitem.h" + +#include "llfolderview.h" +#include "llfolderviewmodel.h" +#include "llpanel.h" +#include "llcriticaldamp.h" +#include "llclipboard.h" +#include "llfocusmgr.h" // gFocusMgr +#include "lltrans.h" +#include "llwindow.h" + +///---------------------------------------------------------------------------- +/// Class LLFolderViewItem +///---------------------------------------------------------------------------- + +static LLDefaultChildRegistry::Register<LLFolderViewItem> r("folder_view_item"); + +// statics +std::map<U8, LLFontGL*> LLFolderViewItem::sFonts; // map of styles to fonts + +// only integers can be initialized in header +const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f; +const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f; + +const LLColor4U DEFAULT_WHITE(255, 255, 255); + + +//static +LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) +{ + LLFontGL* rtn = sFonts[style]; + if (!rtn) // grab label font with this style, lazily + { + LLFontDescriptor labelfontdesc("SansSerif", "Small", style); + rtn = LLFontGL::getFont(labelfontdesc); + if (!rtn) + { + rtn = LLFontGL::getFontDefault(); + } + sFonts[style] = rtn; + } + return rtn; +} + +//static +void LLFolderViewItem::initClass() +{ +} + +//static +void LLFolderViewItem::cleanupClass() +{ + sFonts.clear(); +} + + +// NOTE: Optimize this, we call it a *lot* when opening a large inventory +LLFolderViewItem::Params::Params() +: root(), + listener(), + folder_arrow_image("folder_arrow_image"), + folder_indentation("folder_indentation"), + selection_image("selection_image"), + item_height("item_height"), + item_top_pad("item_top_pad"), + creation_date() +{} + +// Default constructor +LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) +: LLView(p), + mLabelWidth(0), + mLabelWidthDirty(false), + mParentFolder( NULL ), + mIsSelected( FALSE ), + mIsCurSelection( FALSE ), + mSelectPending(FALSE), + mLabelStyle( LLFontGL::NORMAL ), + mHasVisibleChildren(FALSE), + mIndentation(0), + mItemHeight(p.item_height), + //TODO RN: create interface for string highlighting + //mStringMatchOffset(std::string::npos), + mControlLabelRotation(0.f), + mDragAndDropTarget(FALSE), + mLabel(p.name), + mRoot(p.root), + mViewModelItem(p.listener), + mIsMouseOverTitle(false) +{ + if (mViewModelItem) + { + mViewModelItem->setFolderViewItem(this); + } +} + +BOOL LLFolderViewItem::postBuild() +{ + refresh(); + return TRUE; +} + +// Destroys the object +LLFolderViewItem::~LLFolderViewItem( void ) +{ + delete mViewModelItem; + mViewModelItem = NULL; +} + +LLFolderView* LLFolderViewItem::getRoot() +{ + return mRoot; +} + +const LLFolderView* LLFolderViewItem::getRoot() const +{ + return mRoot; +} +// Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. +BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) +{ + LLFolderViewItem* root = this; + while( root->mParentFolder ) + { + if( root->mParentFolder == potential_ancestor ) + { + return TRUE; + } + root = root->mParentFolder; + } + return FALSE; +} + +LLFolderViewItem* LLFolderViewItem::getNextOpenNode(BOOL include_children) +{ + if (!mParentFolder) + { + return NULL; + } + + LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children ); + while(itemp && !itemp->getVisible()) + { + LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children ); + if (itemp == next_itemp) + { + // hit last item + return itemp->getVisible() ? itemp : this; + } + itemp = next_itemp; + } + + return itemp; +} + +LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) +{ + if (!mParentFolder) + { + return NULL; + } + + LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children ); + + // Skip over items that are invisible or are hidden from the UI. + while(itemp && !itemp->getVisible()) + { + LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children ); + if (itemp == next_itemp) + { + // hit first item + return itemp->getVisible() ? itemp : this; + } + itemp = next_itemp; + } + + return itemp; +} + +BOOL LLFolderViewItem::passedFilter(S32 filter_generation) +{ + return getViewModelItem()->passedFilter(filter_generation); +} + +void LLFolderViewItem::refresh() +{ + LLFolderViewModelItem& vmi = *getViewModelItem(); + + mLabel = vmi.getDisplayName(); + + setToolTip(mLabel); + mIcon = vmi.getIcon(); + mIconOpen = vmi.getIconOpen(); + mIconOverlay = vmi.getIconOverlay(); + + if (mRoot->useLabelSuffix()) + { + mLabelStyle = vmi.getLabelStyle(); + mLabelSuffix = vmi.getLabelSuffix(); + } + + //TODO RN: make sure this logic still fires + //std::string searchable_label(mLabel); + //searchable_label.append(mLabelSuffix); + //LLStringUtil::toUpper(searchable_label); + + //if (mSearchableLabel.compare(searchable_label)) + //{ + // mSearchableLabel.assign(searchable_label); + // vmi.dirtyFilter(); + // // some part of label has changed, so overall width has potentially changed, and sort order too + // if (mParentFolder) + // { + // mParentFolder->requestSort(); + // mParentFolder->requestArrange(); + // } + //} + + mLabelWidthDirty = true; + vmi.dirtyFilter(); +} + +// Utility function for LLFolderView +void LLFolderViewItem::arrangeAndSet(BOOL set_selection, + BOOL take_keyboard_focus) +{ + LLFolderView* root = getRoot(); + if (getParentFolder()) + { + getParentFolder()->requestArrange(); + } + if(set_selection) + { + getRoot()->setSelection(this, TRUE, take_keyboard_focus); + if(root) + { + root->scrollToShowSelection(); + } + } +} + + +std::set<LLFolderViewItem*> LLFolderViewItem::getSelectionList() const +{ + std::set<LLFolderViewItem*> selection; + return selection; +} + +// addToFolder() returns TRUE if it succeeds. FALSE otherwise +BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) +{ + return folder->addItem(this); +} + + +// Finds width and height of this object and its children. Also +// makes sure that this view and its children are the right size. +S32 LLFolderViewItem::arrange( S32* width, S32* height ) +{ + const Params& p = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); + S32 indentation = p.folder_indentation(); + // Only indent deeper items in hierarchy + mIndentation = (getParentFolder()) + ? getParentFolder()->getIndentation() + indentation + : 0; + if (mLabelWidthDirty) + { + mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + TEXT_PAD_RIGHT; + mLabelWidthDirty = false; + } + + *width = llmax(*width, mLabelWidth + mIndentation); + + // determine if we need to use ellipses to avoid horizontal scroll. EXT-719 + bool use_ellipses = getRoot()->getUseEllipses(); + if (use_ellipses) + { + // limit to set rect to avoid horizontal scrollbar + *width = llmin(*width, getRoot()->getRect().getWidth()); + } + *height = getItemHeight(); + return *height; +} + +S32 LLFolderViewItem::getItemHeight() +{ + return mItemHeight; +} + +// *TODO: This can be optimized a lot by simply recording that it is +// selected in the appropriate places, and assuming that set selection +// means 'deselect' for a leaf item. Do this optimization after +// multiple selection is implemented to make sure it all plays nice +// together. +BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus) +{ + if (selection == this && !mIsSelected) + { + selectItem(); + } + else if (mIsSelected) // Deselect everything else. + { + deselectItem(); + } + return mIsSelected; +} + +BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected) +{ + if (selection == this) + { + if (mIsSelected) + { + deselectItem(); + } + else + { + selectItem(); + } + return TRUE; + } + return FALSE; +} + +void LLFolderViewItem::deselectItem(void) +{ + mIsSelected = FALSE; +} + +void LLFolderViewItem::selectItem(void) +{ + if (mIsSelected == FALSE) + { + getViewModelItem()->selectItem(); + mIsSelected = TRUE; + } +} + +BOOL LLFolderViewItem::isMovable() +{ + return getViewModelItem()->isItemMovable(); +} + +BOOL LLFolderViewItem::isRemovable() +{ + return getViewModelItem()->isItemRemovable(); +} + +void LLFolderViewItem::destroyView() +{ + getRoot()->removeFromSelectionList(this); + + if (mParentFolder) + { + // removeView deletes me + mParentFolder->extractItem(this); + } + delete this; +} + +// Call through to the viewed object and return true if it can be +// removed. +//BOOL LLFolderViewItem::removeRecursively(BOOL single_item) +BOOL LLFolderViewItem::remove() +{ + if(!isRemovable()) + { + return FALSE; + } + return getViewModelItem()->removeItem(); +} + +// Build an appropriate context menu for the item. +void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + getViewModelItem()->buildContextMenu(menu, flags); +} + +void LLFolderViewItem::openItem( void ) +{ + getViewModelItem()->openItem(); +} + +void LLFolderViewItem::rename(const std::string& new_name) +{ + if( !new_name.empty() ) + { + getViewModelItem()->renameItem(new_name); + + if(mParentFolder) + { + mParentFolder->requestSort(); + } + } + } + +const std::string& LLFolderViewItem::getName( void ) const +{ + return getViewModelItem()->getName(); +} + +// LLView functionality +BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + if(!mIsSelected) + { + getRoot()->setSelection(this, FALSE); + } + make_ui_sound("UISndClick"); + return TRUE; +} + +BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + if (LLView::childrenHandleMouseDown(x, y, mask)) + { + return TRUE; + } + + // No handler needed for focus lost since this class has no + // state that depends on it. + gFocusMgr.setMouseCapture( this ); + + if (!mIsSelected) + { + if(mask & MASK_CONTROL) + { + getRoot()->changeSelection(this, !mIsSelected); + } + else if (mask & MASK_SHIFT) + { + getParentFolder()->extendSelectionTo(this); + } + else + { + getRoot()->setSelection(this, FALSE); + } + make_ui_sound("UISndClick"); + } + else + { + mSelectPending = TRUE; + } + + mDragStartX = x; + mDragStartY = y; + return TRUE; +} + +BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) +{ + static LLCachedControl<S32> drag_and_drop_threshold(*LLUI::sSettingGroups["config"],"DragAndDropDistanceThreshold"); + + mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); + + if( hasMouseCapture() && isMovable() ) + { + LLFolderView* root = getRoot(); + + if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > drag_and_drop_threshold() * drag_and_drop_threshold() + && root->getCurSelectedItem() + && root->startDrag()) + { + // RN: when starting drag and drop, clear out last auto-open + root->autoOpenTest(NULL); + root->setShowSelectionContext(TRUE); + + // Release keyboard focus, so that if stuff is dropped into the + // world, pressing the delete key won't blow away the inventory + // item. + gFocusMgr.setKeyboardFocus(NULL); + + getWindow()->setCursor(UI_CURSOR_ARROW); + return TRUE; + } + else + { + getWindow()->setCursor(UI_CURSOR_NOLOCKED); + return TRUE; + } + } + else + { + getRoot()->setShowSelectionContext(FALSE); + getWindow()->setCursor(UI_CURSOR_ARROW); + // let parent handle this then... + return FALSE; + } +} + + +BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + getViewModelItem()->openItem(); + return TRUE; +} + +BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) +{ + if (LLView::childrenHandleMouseUp(x, y, mask)) + { + return TRUE; + } + + // if mouse hasn't moved since mouse down... + if ( pointInView(x, y) && mSelectPending ) + { + //...then select + if(mask & MASK_CONTROL) + { + getRoot()->changeSelection(this, !mIsSelected); + } + else if (mask & MASK_SHIFT) + { + getParentFolder()->extendSelectionTo(this); + } + else + { + getRoot()->setSelection(this, FALSE); + } + } + + mSelectPending = FALSE; + + if( hasMouseCapture() ) + { + if (getRoot()) + { + getRoot()->setShowSelectionContext(FALSE); + } + gFocusMgr.setMouseCapture( NULL ); + } + return TRUE; +} + +void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mIsMouseOverTitle = false; +} + +BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL handled = FALSE; + BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + handled = accepted; + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + if(mParentFolder && !handled) + { + // store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event. + mRoot->setDraggingOverItem(this); + handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); + mRoot->setDraggingOverItem(NULL); + } + if (handled) + { + lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewItem" << llendl; + } + + return handled; +} + +void LLFolderViewItem::draw() +{ + static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); + static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); + static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); + static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); + static LLUIColor sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); + static LLUIColor sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); + static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); + static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + + const Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); + const S32 TOP_PAD = default_params.item_top_pad; + const S32 FOCUS_LEFT = 1; + const LLFontGL* font = getLabelFontForStyle(mLabelStyle); + + getViewModelItem()->update(); + + //--------------------------------------------------------------------------------// + // Draw open folder arrow + // + if (hasVisibleChildren() || getViewModelItem()->hasChildren()) + { + LLUIImage* arrow_image = default_params.folder_arrow_image; + gl_draw_scaled_rotated_image( + mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD - TOP_PAD, + ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, arrow_image->getImage(), sFgColor); + } + + + //--------------------------------------------------------------------------------// + // Draw highlight for selected items + // + const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); + const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled + const S32 focus_top = getRect().getHeight(); + const S32 focus_bottom = getRect().getHeight() - mItemHeight; + const bool folder_open = (getRect().getHeight() > mItemHeight + 4); + if (mIsSelected) // always render "current" item. Only render other selected items if mShowSingleSelection is FALSE + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLColor4 bg_color = sHighlightBgColor; + if (!mIsCurSelection) + { + // do time-based fade of extra objects + F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); + if (getRoot() && getRoot()->getShowSingleSelection()) + { + // fading out + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); + } + else + { + // fading in + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); + } + } + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + bg_color, filled); + if (mIsCurSelection) + { + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + sFocusOutlineColor, FALSE); + } + if (folder_open) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect + getRect().getWidth() - 2, + 0, + sFocusOutlineColor, FALSE); + if (show_context) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, + getRect().getWidth() - 2, + 0, + sHighlightBgColor, TRUE); + } + } + } + else if (mIsMouseOverTitle) + { + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + sMouseOverColor, FALSE); + } + + //--------------------------------------------------------------------------------// + // Draw DragNDrop highlight + // + if (mDragAndDropTarget) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + sHighlightBgColor, FALSE); + if (folder_open) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect + getRect().getWidth() - 2, + 0, + sHighlightBgColor, FALSE); + } + mDragAndDropTarget = FALSE; + } + + //--------------------------------------------------------------------------------// + // Draw open icon + // + const S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; + if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders + { + mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); + } + else if (mIcon) + { + mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + } + + if (mIconOverlay && getRoot()->showItemLinkOverlays()) + { + mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + } + + //--------------------------------------------------------------------------------// + // Exit if no label to draw + // + if (mLabel.empty()) + { + return; + } + + LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; + //TODO RN: implement this in terms of getColor() + //if (highlight_link) color = sLinkColor; + //if (gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; + + F32 right_x = 0; + F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); + + //--------------------------------------------------------------------------------// + // Draw the actual label text + // + font->renderUTF8(mLabel, 0, text_left, y, color, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); + + //--------------------------------------------------------------------------------// + // Draw label suffix + // + if (!mLabelSuffix.empty()) + { + font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, S32_MAX, &right_x, FALSE ); + } + + //--------------------------------------------------------------------------------// + // Highlight string match + // + //TODO RN: expose interface for highlighting + //if (mStringMatchOffset != std::string::npos) + //{ + // // don't draw backgrounds for zero-length strings + // S32 filter_string_length = getRoot()->getFilterSubString().size(); + // if (filter_string_length > 0) + // { + // std::string combined_string = mLabel + mLabelSuffix; + // S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; + // S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; + // S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); + // S32 top = getRect().getHeight() - TOP_PAD; + // + // LLUIImage* box_image = default_params.selection_image; + // LLRect box_rect(left, top, right, bottom); + // box_image->draw(box_rect, sFilterBGColor); + // F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); + // F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + // font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, + // sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + // filter_string_length, S32_MAX, &right_x, FALSE ); + // } + //} +} + +const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const + { + return getRoot()->getFolderViewModel(); +} + +LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) + { + return getRoot()->getFolderViewModel(); +} + + +///---------------------------------------------------------------------------- +/// Class LLFolderViewFolder +///---------------------------------------------------------------------------- + +LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): + LLFolderViewItem( p ), + mIsOpen(FALSE), + mExpanderHighlighted(FALSE), + mCurHeight(0.f), + mTargetHeight(0.f), + mAutoOpenCountdown(0.f), + mLastArrangeGeneration( -1 ), + mLastCalculatedWidth(0) +{ +} + +// Destroys the object +LLFolderViewFolder::~LLFolderViewFolder( void ) +{ + // The LLView base class takes care of object destruction. make sure that we + // don't have mouse or keyboard focus + gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() +} + +// addToFolder() returns TRUE if it succeeds. FALSE otherwise +BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) +{ + return folder->addFolder(this); +} + +static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); + +// Finds width and height of this object and its children. Also +// makes sure that this view and its children are the right size. +S32 LLFolderViewFolder::arrange( S32* width, S32* height ) +{ + // sort before laying out contents + getRoot()->getFolderViewModel()->sort(this); + + LLFastTimer t2(FTM_ARRANGE); + + // evaluate mHasVisibleChildren + mHasVisibleChildren = false; + if (getViewModelItem()->descendantsPassedFilter()) + { + // We have to verify that there's at least one child that's not filtered out + bool found = false; + // Try the items first + for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + found = itemp->passedFilter(); + if (found) + break; + } + if (!found) + { + // If no item found, try the folders + for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) + { + LLFolderViewFolder* folderp = (*fit); + found = folderp->passedFilter(); + if (found) + break; + } + } + + mHasVisibleChildren = found; + } + + // calculate height as a single item (without any children), and reshapes rectangle to match + LLFolderViewItem::arrange( width, height ); + + // clamp existing animated height so as to never get smaller than a single item + mCurHeight = llmax((F32)*height, mCurHeight); + + // initialize running height value as height of single item in case we have no children + F32 running_height = (F32)*height; + F32 target_height = (F32)*height; + + // are my children visible? + if (needsArrange()) + { + // set last arrange generation first, in case children are animating + // and need to be arranged again + mLastArrangeGeneration = getRoot()->getArrangeGeneration(); + if (isOpen()) + { + // Add sizes of children + S32 parent_item_height = getRect().getHeight(); + + for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) + { + LLFolderViewFolder* folderp = (*fit); + folderp->setVisible(folderp->passedFilter()); // passed filter or has descendants that passed filter + + if (folderp->getVisible()) + { + S32 child_width = *width; + S32 child_height = 0; + S32 child_top = parent_item_height - llround(running_height); + + target_height += folderp->arrange( &child_width, &child_height ); + + running_height += (F32)child_height; + *width = llmax(*width, child_width); + folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() ); + } + } + for(items_t::iterator iit = mItems.begin(); + iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + itemp->setVisible(itemp->passedFilter()); + + if (itemp->getVisible()) + { + S32 child_width = *width; + S32 child_height = 0; + S32 child_top = parent_item_height - llround(running_height); + + target_height += itemp->arrange( &child_width, &child_height ); + // don't change width, as this item is as wide as its parent folder by construction + itemp->reshape( itemp->getRect().getWidth(), child_height); + + running_height += (F32)child_height; + *width = llmax(*width, child_width); + itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() ); + } + } + } + + mTargetHeight = target_height; + // cache this width so next time we can just return it + mLastCalculatedWidth = *width; + } + else + { + // just use existing width + *width = mLastCalculatedWidth; + } + + // animate current height towards target height + if (llabs(mCurHeight - mTargetHeight) > 1.f) + { + mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); + + requestArrange(); + + // hide child elements that fall out of current animated height + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + // number of pixels that bottom of folder label is from top of parent folder + if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight() + > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) + { + // hide if beyond current folder height + (*fit)->setVisible(FALSE); + } + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + // number of pixels that bottom of item label is from top of parent folder + if (getRect().getHeight() - (*iit)->getRect().mBottom + > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) + { + (*iit)->setVisible(FALSE); + } + } + } + else + { + mCurHeight = mTargetHeight; + } + + // don't change width as this item is already as wide as its parent folder + reshape(getRect().getWidth(),llround(mCurHeight)); + + // pass current height value back to parent + *height = llround(mCurHeight); + + return llround(mTargetHeight); +} + +BOOL LLFolderViewFolder::needsArrange() +{ + return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); +} + +void LLFolderViewFolder::requestSort() +{ + getViewModelItem()->requestSort(); +} + +//TODO RN: get height resetting working +//void LLFolderViewFolder::setPassedFilter(BOOL passed, BOOL passed_folder, S32 filter_generation) +//{ +// // if this folder is now filtered, but wasn't before +// // (it just passed) +// if (passed && !passedFilter(filter_generation)) +// { +// // reset current height, because last time we drew it +// // it might have had more visible items than now +// mCurHeight = 0.f; +// } +// +// LLFolderViewItem::setPassedFilter(passed, passed_folder, filter_generation); +//} + + +// Passes selection information on to children and record selection +// information if necessary. +BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, + BOOL take_keyboard_focus) +{ + BOOL rv = FALSE; + if (selection == this) + { + if (!isSelected()) + { + selectItem(); + } + rv = TRUE; + } + else + { + if (isSelected()) + { + deselectItem(); + } + rv = FALSE; + } + BOOL child_selected = FALSE; + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if((*fit)->setSelection(selection, openitem, take_keyboard_focus)) + { + rv = TRUE; + child_selected = TRUE; + } + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if((*iit)->setSelection(selection, openitem, take_keyboard_focus)) + { + rv = TRUE; + child_selected = TRUE; + } + } + if(openitem && child_selected) + { + setOpenArrangeRecursively(TRUE); + } + return rv; +} + +// This method is used to change the selection of an item. +// Recursively traverse all children; if 'selection' is 'this' then change +// the select status if necessary. +// Returns TRUE if the selection state of this folder, or of a child, was changed. +BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selected) +{ + BOOL rv = FALSE; + if(selection == this) + { + if (isSelected() != selected) + { + rv = TRUE; + if (selected) + { + selectItem(); + } + else + { + deselectItem(); + } + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if((*fit)->changeSelection(selection, selected)) + { + rv = TRUE; + } + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if((*iit)->changeSelection(selection, selected)) + { + rv = TRUE; + } + } + return rv; +} + +LLFolderViewFolder* LLFolderViewFolder::getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse) +{ + if (!item_a->getParentFolder() || !item_b->getParentFolder()) return NULL; + + std::deque<LLFolderViewFolder*> item_a_ancestors; + + LLFolderViewFolder* parent = item_a->getParentFolder(); + while(parent) + { + item_a_ancestors.push_back(parent); + parent = parent->getParentFolder(); + } + + std::deque<LLFolderViewFolder*> item_b_ancestors; + + parent = item_b->getParentFolder(); + while(parent) + { + item_b_ancestors.push_back(parent); + parent = parent->getParentFolder(); + } + + LLFolderViewFolder* common_ancestor = item_a->getRoot(); + + while(item_a_ancestors.size() > item_b_ancestors.size()) + { + item_a = item_a_ancestors.front(); + item_a_ancestors.pop_front(); + } + + while(item_b_ancestors.size() > item_a_ancestors.size()) + { + item_b = item_b_ancestors.front(); + item_b_ancestors.pop_front(); + } + + while(item_a_ancestors.size()) + { + common_ancestor = item_a_ancestors.front(); + + if (item_a_ancestors.front() == item_b_ancestors.front()) + { + // which came first, sibling a or sibling b? + for (folders_t::iterator it = common_ancestor->mFolders.begin(), end_it = common_ancestor->mFolders.end(); + it != end_it; + ++it) + { + LLFolderViewItem* item = *it; + + if (item == item_a) + { + reverse = false; + return common_ancestor; + } + if (item == item_b) + { + reverse = true; + return common_ancestor; + } + } + + for (items_t::iterator it = common_ancestor->mItems.begin(), end_it = common_ancestor->mItems.end(); + it != end_it; + ++it) + { + LLFolderViewItem* item = *it; + + if (item == item_a) + { + reverse = false; + return common_ancestor; + } + if (item == item_b) + { + reverse = true; + return common_ancestor; + } + } + break; + } + + item_a = item_a_ancestors.front(); + item_a_ancestors.pop_front(); + item_b = item_b_ancestors.front(); + item_b_ancestors.pop_front(); + } + + return NULL; +} + +void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items) +{ + bool selecting = start == NULL; + if (reverse) + { + for (items_t::reverse_iterator it = mItems.rbegin(), end_it = mItems.rend(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + if (selecting) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + for (folders_t::reverse_iterator it = mFolders.rbegin(), end_it = mFolders.rend(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + + if (selecting) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + } + else + { + for (folders_t::iterator it = mFolders.begin(), end_it = mFolders.end(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + + if (selecting) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + for (items_t::iterator it = mItems.begin(), end_it = mItems.end(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + + if (selecting) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + } +} + +void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) +{ + if (getRoot()->getAllowMultiSelect() == FALSE) return; + + LLFolderViewItem* cur_selected_item = getRoot()->getCurSelectedItem(); + if (cur_selected_item == NULL) + { + cur_selected_item = new_selection; + } + + + bool reverse = false; + LLFolderViewFolder* common_ancestor = getCommonAncestor(cur_selected_item, new_selection, reverse); + if (!common_ancestor) return; + + LLFolderViewItem* last_selected_item_from_cur = cur_selected_item; + LLFolderViewFolder* cur_folder = cur_selected_item->getParentFolder(); + + std::vector<LLFolderViewItem*> items_to_select_forward; + + while(cur_folder != common_ancestor) + { + cur_folder->gatherChildRangeExclusive(last_selected_item_from_cur, NULL, reverse, items_to_select_forward); + + last_selected_item_from_cur = cur_folder; + cur_folder = cur_folder->getParentFolder(); + } + + std::vector<LLFolderViewItem*> items_to_select_reverse; + + LLFolderViewItem* last_selected_item_from_new = new_selection; + cur_folder = new_selection->getParentFolder(); + while(cur_folder != common_ancestor) + { + cur_folder->gatherChildRangeExclusive(last_selected_item_from_new, NULL, !reverse, items_to_select_reverse); + + last_selected_item_from_new = cur_folder; + cur_folder = cur_folder->getParentFolder(); + } + + common_ancestor->gatherChildRangeExclusive(last_selected_item_from_cur, last_selected_item_from_new, reverse, items_to_select_forward); + + for (std::vector<LLFolderViewItem*>::reverse_iterator it = items_to_select_reverse.rbegin(), end_it = items_to_select_reverse.rend(); + it != end_it; + ++it) + { + items_to_select_forward.push_back(*it); + } + + LLFolderView* root = getRoot(); + + for (std::vector<LLFolderViewItem*>::iterator it = items_to_select_forward.begin(), end_it = items_to_select_forward.end(); + it != end_it; + ++it) + { + LLFolderViewItem* item = *it; + if (item->isSelected()) + { + root->removeFromSelectionList(item); + } + else + { + item->selectItem(); + } + root->addToSelectionList(item); + } + + if (new_selection->isSelected()) + { + root->removeFromSelectionList(new_selection); + } + else + { + new_selection->selectItem(); + } + root->addToSelectionList(new_selection); +} + + +void LLFolderViewFolder::destroyView() +{ + std::for_each(mItems.begin(), mItems.end(), DeletePointer()); + mItems.clear(); + + while (!mFolders.empty()) + { + LLFolderViewFolder *folderp = mFolders.back(); + folderp->destroyView(); // removes entry from mFolders + } + + LLFolderViewItem::destroyView(); +} + +// extractItem() removes the specified item from the folder, but +// doesn't delete it. +void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) +{ + items_t::iterator it = std::find(mItems.begin(), mItems.end(), item); + if(it == mItems.end()) + { + // This is an evil downcast. However, it's only doing + // pointer comparison to find if (which it should be ) the + // item is in the container, so it's pretty safe. + LLFolderViewFolder* f = static_cast<LLFolderViewFolder*>(item); + folders_t::iterator ft; + ft = std::find(mFolders.begin(), mFolders.end(), f); + if (ft != mFolders.end()) + { + mFolders.erase(ft); + } + } + else + { + mItems.erase(it); + } + //item has been removed, need to update filter + getViewModelItem()->removeChild(item->getViewModelItem()); + getViewModelItem()->dirtyFilter(); + //because an item is going away regardless of filter status, force rearrange + requestArrange(); + removeChild(item); +} + +BOOL LLFolderViewFolder::isMovable() +{ + if( !(getViewModelItem()->isItemMovable()) ) + { + return FALSE; + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isMovable()) + { + return FALSE; + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isMovable()) + { + return FALSE; + } + } + return TRUE; +} + + +BOOL LLFolderViewFolder::isRemovable() +{ + if( !(getViewModelItem()->isItemRemovable()) ) + { + return FALSE; + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isRemovable()) + { + return FALSE; + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isRemovable()) + { + return FALSE; + } + } + return TRUE; +} + +// this is an internal method used for adding items to folders. +BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) +{ + if (item->getParentFolder()) + { + item->getParentFolder()->extractItem(item); + } + item->setParentFolder(this); + + mItems.push_back(item); + + item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); + item->setVisible(FALSE); + + addChild(item); + + item->getViewModelItem()->dirtyFilter(); + + // Handle sorting + requestArrange(); + requestSort(); + + getViewModelItem()->addChild(item->getViewModelItem()); + + //TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria + //// Traverse parent folders and update creation date and resort, if necessary + //LLFolderViewFolder* parentp = this; + //while (parentp) + //{ + // if (parentp->mSortFunction.isByDate()) + // { + // // parent folder doesn't have a time stamp yet, so get it from us + // parentp->requestSort(); + // } + + // parentp = parentp->getParentFolder(); + //} + + return TRUE; +} + +// this is an internal method used for adding items to folders. +BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) +{ + if (folder->mParentFolder) + { + folder->mParentFolder->extractItem(folder); + } + folder->mParentFolder = this; + mFolders.push_back(folder); + folder->setOrigin(0, 0); + folder->reshape(getRect().getWidth(), 0); + folder->setVisible(FALSE); + addChild( folder ); + folder->getViewModelItem()->dirtyFilter(); + // rearrange all descendants too, as our indentation level might have changed + folder->requestArrange(); + requestSort(); + + getViewModelItem()->addChild(folder->getViewModelItem()); + + return TRUE; +} + +void LLFolderViewFolder::requestArrange() +{ + mLastArrangeGeneration = -1; + // flag all items up to root + if (mParentFolder) + { + mParentFolder->requestArrange(); + } +} + +void LLFolderViewFolder::toggleOpen() +{ + setOpen(!isOpen()); +} + +// Force a folder open or closed +void LLFolderViewFolder::setOpen(BOOL openitem) +{ + setOpenArrangeRecursively(openitem); +} + +void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) +{ + BOOL was_open = isOpen(); + mIsOpen = openitem; + if(!was_open && openitem) + { + getViewModelItem()->openItem(); + } + else if(was_open && !openitem) + { + getViewModelItem()->closeItem(); + } + + if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) + { + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */ + } + } + if (mParentFolder + && (recurse == RECURSE_UP + || recurse == RECURSE_UP_DOWN)) + { + mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP); + } + + if (was_open != isOpen()) + { + requestArrange(); + } +} + +BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, + BOOL drop, + EDragAndDropType c_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + + // drag and drop to child item, so clear pending auto-opens + getRoot()->autoOpenTest(NULL); + + return TRUE; +} + +void LLFolderViewFolder::openItem( void ) +{ + toggleOpen(); +} + +void LLFolderViewFolder::applyFunctorToChildren(LLFolderViewFunctor& functor) +{ + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + functor.doItem((*fit)); + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + functor.doItem((*iit)); + } +} + +void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) +{ + functor.doFolder(this); + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->applyFunctorRecursively(functor); + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + functor.doItem((*iit)); + } +} + +// LLView functionality +BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL handled = FALSE; + + if (isOpen()) + { + handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL); + } + + if (!handled) + { + handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + + lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl; + } + + return TRUE; +} + +BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + + if (!drop && accepted) + { + getRoot()->autoOpenTest(this); + } + + return TRUE; +} + + +BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + BOOL handled = FALSE; + + if( isOpen() ) + { + handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; + } + if (!handled) + { + handled = LLFolderViewItem::handleRightMouseDown( x, y, mask ); + } + return handled; +} + + +BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) +{ + mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); + + BOOL handled = LLView::handleHover(x, y, mask); + + if (!handled) + { + // this doesn't do child processing + handled = LLFolderViewItem::handleHover(x, y, mask); + } + + return handled; +} + +BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + BOOL handled = FALSE; + if( isOpen() ) + { + handled = childrenHandleMouseDown(x,y,mask) != NULL; + } + if( !handled ) + { + if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD) + { + toggleOpen(); + handled = TRUE; + } + else + { + // do normal selection logic + handled = LLFolderViewItem::handleMouseDown(x, y, mask); + } + } + + return handled; +} + +BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + BOOL handled = FALSE; + if( isOpen() ) + { + handled = childrenHandleDoubleClick( x, y, mask ) != NULL; + } + if( !handled ) + { + if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD) + { + // don't select when user double-clicks plus sign + // so as not to contradict single-click behavior + toggleOpen(); + } + else + { + getRoot()->setSelection(this, FALSE); + toggleOpen(); + } + handled = TRUE; + } + return handled; +} + +void LLFolderViewFolder::draw() +{ + if (mAutoOpenCountdown != 0.f) + { + mControlLabelRotation = mAutoOpenCountdown * -90.f; + } + else if (isOpen()) + { + mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); + } + else + { + mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); + } + + LLFolderViewItem::draw(); + + // draw children if root folder, or any other folder that is open or animating to closed state + if( getRoot() == this || (isOpen() || mCurHeight != mTargetHeight )) + { + LLView::draw(); + } + + mExpanderHighlighted = FALSE; +} + +// this does prefix traversal, as folders are listed above their contents +LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children ) +{ + BOOL found_item = FALSE; + + LLFolderViewItem* result = NULL; + // when not starting from a given item, start at beginning + if(item == NULL) + { + found_item = TRUE; + } + + // find current item among children + folders_t::iterator fit = mFolders.begin(); + folders_t::iterator fend = mFolders.end(); + + items_t::iterator iit = mItems.begin(); + items_t::iterator iend = mItems.end(); + + // if not trivially starting at the beginning, we have to find the current item + if (!found_item) + { + // first, look among folders, since they are always above items + for(; fit != fend; ++fit) + { + if(item == (*fit)) + { + found_item = TRUE; + // if we are on downwards traversal + if (include_children && (*fit)->isOpen()) + { + // look for first descendant + return (*fit)->getNextFromChild(NULL, TRUE); + } + // otherwise advance to next folder + ++fit; + include_children = TRUE; + break; + } + } + + // didn't find in folders? Check items... + if (!found_item) + { + for(; iit != iend; ++iit) + { + if(item == (*iit)) + { + found_item = TRUE; + // point to next item + ++iit; + break; + } + } + } + } + + if (!found_item) + { + // you should never call this method with an item that isn't a child + // so we should always find something + llassert(FALSE); + return NULL; + } + + // at this point, either iit or fit point to a candidate "next" item + // if both are out of range, we need to punt up to our parent + + // now, starting from found folder, continue through folders + // searching for next visible folder + while(fit != fend && !(*fit)->getVisible()) + { + // turn on downwards traversal for next folder + ++fit; + } + + if (fit != fend) + { + result = (*fit); + } + else + { + // otherwise, scan for next visible item + while(iit != iend && !(*iit)->getVisible()) + { + ++iit; + } + + // check to see if we have a valid item + if (iit != iend) + { + result = (*iit); + } + } + + if( !result && mParentFolder ) + { + // If there are no siblings or children to go to, recurse up one level in the tree + // and skip children for this folder, as we've already discounted them + result = mParentFolder->getNextFromChild(this, FALSE); + } + + return result; +} + +// this does postfix traversal, as folders are listed above their contents +LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, BOOL include_children ) +{ + BOOL found_item = FALSE; + + LLFolderViewItem* result = NULL; + // when not starting from a given item, start at end + if(item == NULL) + { + found_item = TRUE; + } + + // find current item among children + folders_t::reverse_iterator fit = mFolders.rbegin(); + folders_t::reverse_iterator fend = mFolders.rend(); + + items_t::reverse_iterator iit = mItems.rbegin(); + items_t::reverse_iterator iend = mItems.rend(); + + // if not trivially starting at the end, we have to find the current item + if (!found_item) + { + // first, look among items, since they are always below the folders + for(; iit != iend; ++iit) + { + if(item == (*iit)) + { + found_item = TRUE; + // point to next item + ++iit; + break; + } + } + + // didn't find in items? Check folders... + if (!found_item) + { + for(; fit != fend; ++fit) + { + if(item == (*fit)) + { + found_item = TRUE; + // point to next folder + ++fit; + break; + } + } + } + } + + if (!found_item) + { + // you should never call this method with an item that isn't a child + // so we should always find something + llassert(FALSE); + return NULL; + } + + // at this point, either iit or fit point to a candidate "next" item + // if both are out of range, we need to punt up to our parent + + // now, starting from found item, continue through items + // searching for next visible item + while(iit != iend && !(*iit)->getVisible()) + { + ++iit; + } + + if (iit != iend) + { + // we found an appropriate item + result = (*iit); + } + else + { + // otherwise, scan for next visible folder + while(fit != fend && !(*fit)->getVisible()) + { + ++fit; + } + + // check to see if we have a valid folder + if (fit != fend) + { + // try selecting child element of this folder + if ((*fit)->isOpen()) + { + result = (*fit)->getPreviousFromChild(NULL); + } + else + { + result = (*fit); + } + } + } + + if( !result ) + { + // If there are no siblings or children to go to, recurse up one level in the tree + // which gets back to this folder, which will only be visited if it is a valid, visible item + result = this; + } + + return result; +} + diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h new file mode 100644 index 0000000000..9cb885066a --- /dev/null +++ b/indra/llui/llfolderviewitem.h @@ -0,0 +1,420 @@ +/** +* @file llfolderviewitem.h +* @brief Items and folders that can appear in a hierarchical folder view +* +* $LicenseInfo:firstyear=2001&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#ifndef LLFOLDERVIEWITEM_H +#define LLFOLDERVIEWITEM_H + +#include "llview.h" +#include "lluiimage.h" + +class LLFolderView; +class LLFolderViewModelItem; +class LLFolderViewFolder; +class LLFolderViewFunctor; +class LLFolderViewFilter; +class LLFolderViewModelInterface; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderViewItem +// +// An instance of this class represents a single item in a folder view +// such as an inventory item or a file. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFolderViewItem : public LLView +{ +public: + static void initClass(); + static void cleanupClass(); + + struct Params : public LLInitParam::Block<Params, LLView::Params> + { + Optional<LLUIImage*> folder_arrow_image, + selection_image; + Optional<LLFolderView*> root; + Mandatory<LLFolderViewModelItem*> listener; + + Optional<S32> folder_indentation, // pixels + item_height, + item_top_pad; + + Optional<time_t> creation_date; + + Params(); + }; + + // layout constants + static const S32 LEFT_PAD = 5; + // LEFT_INDENTATION is set via folder_indentation above + static const S32 ICON_PAD = 2; + static const S32 ICON_WIDTH = 16; + static const S32 TEXT_PAD = 1; + static const S32 TEXT_PAD_RIGHT = 4; + static const S32 ARROW_SIZE = 12; + static const S32 MAX_FOLDER_ITEM_OVERLAP = 2; + // animation parameters + static const F32 FOLDER_CLOSE_TIME_CONSTANT; + static const F32 FOLDER_OPEN_TIME_CONSTANT; + +private: + BOOL mIsSelected; + +protected: + friend class LLUICtrlFactory; + friend class LLFolderViewModelItem; + + LLFolderViewItem(const Params& p); + + std::string mLabel; + S32 mLabelWidth; + bool mLabelWidthDirty; + LLFolderViewFolder* mParentFolder; + LLFolderViewModelItem* mViewModelItem; + BOOL mIsCurSelection; + BOOL mSelectPending; + LLFontGL::StyleFlags mLabelStyle; + std::string mLabelSuffix; + LLUIImagePtr mIcon; + LLUIImagePtr mIconOpen; + LLUIImagePtr mIconOverlay; + BOOL mHasVisibleChildren; + S32 mIndentation; + S32 mItemHeight; + S32 mDragStartX, + mDragStartY; + + //TODO RN: create interface for string highlighting + //std::string::size_type mStringMatchOffset; + F32 mControlLabelRotation; + LLFolderView* mRoot; + BOOL mDragAndDropTarget; + bool mIsMouseOverTitle; + + // this is an internal method used for adding items to folders. A + // no-op at this level, but reimplemented in derived classes. + virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } + virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; } + + static LLFontGL* getLabelFontForStyle(U8 style); + +public: + BOOL postBuild(); + + virtual void openItem( void ); + + void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus); + + virtual ~LLFolderViewItem( void ); + + // addToFolder() returns TRUE if it succeeds. FALSE otherwise + virtual BOOL addToFolder(LLFolderViewFolder* folder); + + // Finds width and height of this object and it's children. Also + // makes sure that this view and it's children are the right size. + virtual S32 arrange( S32* width, S32* height ); + virtual S32 getItemHeight(); + + // If 'selection' is 'this' then note that otherwise ignore. + // Returns TRUE if this item ends up being selected. + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); + + // This method is used to set the selection state of an item. + // If 'selection' is 'this' then note selection. + // Returns TRUE if the selection state of this item was changed. + virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); + + // this method is used to deselect this element + void deselectItem(); + + // this method is used to select this element + virtual void selectItem(); + + // gets multiple-element selection + virtual std::set<LLFolderViewItem*> getSelectionList() const; + + // Returns true is this object and all of its children can be removed (deleted by user) + virtual BOOL isRemovable(); + + // Returns true is this object and all of its children can be moved + virtual BOOL isMovable(); + + // destroys this item recursively + virtual void destroyView(); + + BOOL isSelected() const { return mIsSelected; } + + void setUnselected() { mIsSelected = FALSE; } + + void setIsCurSelection(BOOL select) { mIsCurSelection = select; } + + BOOL getIsCurSelection() { return mIsCurSelection; } + + BOOL hasVisibleChildren() { return mHasVisibleChildren; } + + // Call through to the viewed object and return true if it can be + // removed. Returns true if it's removed. + //virtual BOOL removeRecursively(BOOL single_item); + BOOL remove(); + + // Build an appropriate context menu for the item. Flags unused. + void buildContextMenu(class LLMenuGL& menu, U32 flags); + + // This method returns the actual name of the thing being + // viewed. This method will ask the viewed object itself. + const std::string& getName( void ) const; + + // This method returns the label displayed on the view. This + // method was primarily added to allow sorting on the folder + // contents possible before the entire view has been constructed. + const std::string& getLabel() const { return mLabel; } + + + LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } + const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } + + void setParentFolder(LLFolderViewFolder* parent) { mParentFolder = parent; } + + LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); + LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); + + const LLFolderViewModelItem* getViewModelItem( void ) const { return mViewModelItem; } + LLFolderViewModelItem* getViewModelItem( void ) { return mViewModelItem; } + + const LLFolderViewModelInterface* getFolderViewModel( void ) const; + LLFolderViewModelInterface* getFolderViewModel( void ); + + // just rename the object. + void rename(const std::string& new_name); + + + // Show children (unfortunate that this is called "open") + virtual void setOpen(BOOL open = TRUE) {}; + virtual BOOL isOpen() const { return FALSE; } + + virtual LLFolderView* getRoot(); + virtual const LLFolderView* getRoot() const; + BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); + S32 getIndentation() { return mIndentation; } + + virtual BOOL passedFilter(S32 filter_generation = -1); + + // refresh information from the object being viewed. + virtual void refresh(); + + // LLView functionality + virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleHover( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); + virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); + + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + + virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return NULL; } + + // virtual void handleDropped(); + virtual void draw(); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + +private: + static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderViewFolder +// +// An instance of an LLFolderViewFolder represents a collection of +// more folders and items. This is used to build the hierarchy of +// items found in the folder view. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFolderViewFolder : public LLFolderViewItem +{ +protected: + LLFolderViewFolder( const LLFolderViewItem::Params& ); + friend class LLUICtrlFactory; + +public: + + typedef std::list<LLFolderViewItem*> items_t; + typedef std::list<LLFolderViewFolder*> folders_t; + +protected: + items_t mItems; + folders_t mFolders; + + BOOL mIsOpen; + BOOL mExpanderHighlighted; + F32 mCurHeight; + F32 mTargetHeight; + F32 mAutoOpenCountdown; + S32 mLastArrangeGeneration; + S32 mLastCalculatedWidth; + S32 mMostFilteredDescendantGeneration; + bool mNeedsSort; + +public: + typedef enum e_recurse_type + { + RECURSE_NO, + RECURSE_UP, + RECURSE_DOWN, + RECURSE_UP_DOWN + } ERecurseType; + + + virtual ~LLFolderViewFolder( void ); + + LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); + LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); + + // addToFolder() returns TRUE if it succeeds. FALSE otherwise + virtual BOOL addToFolder(LLFolderViewFolder* folder); + + // Finds width and height of this object and it's children. Also + // makes sure that this view and it's children are the right size. + virtual S32 arrange( S32* width, S32* height ); + + BOOL needsArrange(); + + bool descendantsPassedFilter(S32 filter_generation = -1); + + // Passes selection information on to children and record + // selection information if necessary. + // Returns TRUE if this object (or a child) ends up being selected. + // If 'openitem' is TRUE then folders are opened up along the way to the selection. + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus = TRUE); + + // This method is used to change the selection of an item. + // Recursively traverse all children; if 'selection' is 'this' then change + // the select status if necessary. + // Returns TRUE if the selection state of this folder, or of a child, was changed. + virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); + + // this method is used to group select items + void extendSelectionTo(LLFolderViewItem* selection); + + // Returns true is this object and all of its children can be removed. + virtual BOOL isRemovable(); + + // Returns true is this object and all of its children can be moved + virtual BOOL isMovable(); + + // destroys this folder, and all children + virtual void destroyView(); + + // If this folder can be removed, remove all children that can be + // removed, return TRUE if this is empty after the operation and + // it's viewed folder object can be removed. + //virtual BOOL removeRecursively(BOOL single_item); + //virtual BOOL remove(); + + // extractItem() removes the specified item from the folder, but + // doesn't delete it. + virtual void extractItem( LLFolderViewItem* item ); + + // This function is called by a child that needs to be resorted. + void resort(LLFolderViewItem* item); + + void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; } + + // folders can be opened. This will usually be called by internal + // methods. + virtual void toggleOpen(); + + // Force a folder open or closed + virtual void setOpen(BOOL openitem = TRUE); + + // Called when a child is refreshed. + virtual void requestArrange(); + + virtual void requestSort(); + + // internal method which doesn't update the entire view. This + // method was written because the list iterators destroy the state + // of other iterations, thus, we can't arrange while iterating + // through the children (such as when setting which is selected. + virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO); + + // Get the current state of the folder. + virtual BOOL isOpen() const { return mIsOpen; } + + // special case if an object is dropped on the child. + BOOL handleDragAndDropFromChild(MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + + void applyFunctorRecursively(LLFolderViewFunctor& functor); + + // Just apply this functor to the folder's immediate children. + void applyFunctorToChildren(LLFolderViewFunctor& functor); + + virtual void openItem( void ); + virtual BOOL addItem(LLFolderViewItem* item); + virtual BOOL addFolder( LLFolderViewFolder* folder); + + // LLView functionality + virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + BOOL handleDragAndDropToThisFolder(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + virtual void draw(); + + folders_t::iterator getFoldersBegin() { return mFolders.begin(); } + folders_t::iterator getFoldersEnd() { return mFolders.end(); } + folders_t::size_type getFoldersCount() const { return mFolders.size(); } + + items_t::const_iterator getItemsBegin() const { return mItems.begin(); } + items_t::const_iterator getItemsEnd() const { return mItems.end(); } + items_t::size_type getItemsCount() const { return mItems.size(); } + + LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); + void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items); + +public: + //WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead + template<typename SORT_FUNC> void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); } + template<typename SORT_FUNC> void sortItems(const SORT_FUNC& func) { mItems.sort(func); } +}; + + +#endif // LLFOLDERVIEWITEM_H diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp new file mode 100644 index 0000000000..dc6e4d754b --- /dev/null +++ b/indra/llui/llfolderviewmodel.cpp @@ -0,0 +1,53 @@ +/** + * @file llfolderviewmodel.cpp + * @brief Implementation of the view model collection of classes. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llfolderviewmodel.h" +#include "lltrans.h" + +bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) +{ + return item->getSortVersion() < mTargetSortVersion; +} + +std::string LLFolderViewModelCommon::getStatusText() +{ + if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter()->getCurrentGeneration()) + { + return LLTrans::getString("Searching"); + } + else + { + return getFilter()->getEmptyLookupMessage(); + } +} + +void LLFolderViewModelCommon::filter() +{ + getFilter()->setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); + mFolderView->getViewModelItem()->filter(*getFilter()); +} diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h new file mode 100644 index 0000000000..0f5f9a1f50 --- /dev/null +++ b/indra/llui/llfolderviewmodel.h @@ -0,0 +1,353 @@ +/** + * @file llfolderviewmodel.h + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LLFOLDERVIEWMODEL_H +#define LLFOLDERVIEWMODEL_H + +#include "llfontgl.h" // just for StyleFlags enum +#include "llfolderview.h" + +// These are grouping of inventory types. +// Order matters when sorting system folders to the top. +enum EInventorySortGroup +{ + SG_SYSTEM_FOLDER, + SG_TRASH_FOLDER, + SG_NORMAL_FOLDER, + SG_ITEM +}; + +class LLFontGL; +class LLInventoryModel; +class LLMenuGL; +class LLUIImage; +class LLUUID; +class LLFolderViewItem; +class LLFolderViewFolder; + +class LLFolderViewFilter +{ +public: + enum EFilterModified + { + FILTER_NONE, // nothing to do, already filtered + FILTER_RESTART, // restart filtering from scratch + FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter + FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one + }; + +public: + + LLFolderViewFilter() {} + virtual ~LLFolderViewFilter() {} + + // +-------------------------------------------------------------------+ + // + Execution And Results + // +-------------------------------------------------------------------+ + virtual bool check(const LLFolderViewModelItem* item) = 0; + virtual bool checkFolder(const LLFolderViewModelItem* folder) const = 0; + + virtual void setEmptyLookupMessage(const std::string& message) = 0; + virtual std::string getEmptyLookupMessage() const = 0; + + virtual bool showAllResults() const = 0; + + // +-------------------------------------------------------------------+ + // + Status + // +-------------------------------------------------------------------+ + virtual bool isActive() const = 0; + virtual bool isModified() const = 0; + virtual void clearModified() = 0; + virtual const std::string& getName() const = 0; + virtual const std::string& getFilterText() = 0; + //RN: this is public to allow system to externally force a global refilter + virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0; + + // +-------------------------------------------------------------------+ + // + Count + // +-------------------------------------------------------------------+ + virtual void setFilterCount(S32 count) = 0; + virtual S32 getFilterCount() const = 0; + virtual void decrementFilterCount() = 0; + + // +-------------------------------------------------------------------+ + // + Default + // +-------------------------------------------------------------------+ + virtual bool isDefault() const = 0; + virtual bool isNotDefault() const = 0; + virtual void markDefault() = 0; + virtual void resetDefault() = 0; + + // +-------------------------------------------------------------------+ + // + Generation + // +-------------------------------------------------------------------+ + virtual S32 getCurrentGeneration() const = 0; + virtual S32 getFirstSuccessGeneration() const = 0; + virtual S32 getFirstRequiredGeneration() const = 0; +}; + +class LLFolderViewModelInterface +{ +public: + virtual ~LLFolderViewModelInterface() {} + virtual void requestSortAll() = 0; + + virtual void sort(class LLFolderViewFolder*) = 0; + virtual void filter() = 0; + + virtual bool contentsReady() = 0; + virtual void setFolderView(LLFolderView* folder_view) = 0; + virtual LLFolderViewFilter* getFilter() = 0; + virtual const LLFolderViewFilter* getFilter() const = 0; + virtual std::string getStatusText() = 0; + + virtual bool startDrag(std::vector<LLFolderViewModelItem*>& items) = 0; +}; + +class LLFolderViewModelCommon : public LLFolderViewModelInterface +{ +public: + LLFolderViewModelCommon() + : mTargetSortVersion(0), + mFolderView(NULL) + {} + + virtual void requestSortAll() + { + // sort everything + mTargetSortVersion++; + } + virtual std::string getStatusText(); + virtual void filter(); + + void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} + +protected: + bool needsSort(class LLFolderViewModelItem* item); + + S32 mTargetSortVersion; + LLFolderView* mFolderView; + +}; + +template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE> +class LLFolderViewModel : public LLFolderViewModelCommon +{ +public: + LLFolderViewModel(){} + virtual ~LLFolderViewModel() {} + + typedef SORT_TYPE SortType; + typedef ITEM_TYPE ItemType; + typedef FOLDER_TYPE FolderType; + typedef FILTER_TYPE FilterType; + + virtual SortType& getSorter() { return mSorter; } + virtual const SortType& getSorter() const { return mSorter; } + virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } + + virtual FilterType* getFilter() { return &mFilter; } + virtual const FilterType* getFilter() const { return &mFilter; } + virtual void setFilter(const FilterType& filter) { mFilter = filter; } + + // TODO RN: remove this and put all filtering logic in view model + // add getStatusText and isFiltering() + virtual bool contentsReady() { return true; } + + + struct ViewModelCompare + { + ViewModelCompare(const SortType& sorter) + : mSorter(sorter) + {} + + bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const + { + return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); + } + + bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const + { + return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); + } + + const SortType& mSorter; + }; + + void sort(LLFolderViewFolder* folder) + { + if (needsSort(folder->getViewModelItem())) + { + folder->sortFolders(ViewModelCompare(getSorter())); + folder->sortItems(ViewModelCompare(getSorter())); + folder->getViewModelItem()->setSortVersion(mTargetSortVersion); + folder->requestArrange(); + } + } + +protected: + SortType mSorter; + FilterType mFilter; +}; + +// This is am abstract base class that users of the folderview classes +// would use to bridge the folder view with the underlying data +class LLFolderViewModelItem +{ +public: + virtual ~LLFolderViewModelItem( void ) {}; + + virtual void update() {} //called when drawing + virtual const std::string& getName() const = 0; + virtual const std::string& getDisplayName() const = 0; + virtual const std::string& getSearchableName() const = 0; + + virtual LLPointer<LLUIImage> getIcon() const = 0; + virtual LLPointer<LLUIImage> getIconOpen() const { return getIcon(); } + virtual LLPointer<LLUIImage> getIconOverlay() const { return NULL; } + + virtual LLFontGL::StyleFlags getLabelStyle() const = 0; + virtual std::string getLabelSuffix() const = 0; + + virtual void openItem( void ) = 0; + virtual void closeItem( void ) = 0; + virtual void selectItem(void) = 0; + + virtual BOOL isItemRenameable() const = 0; + virtual BOOL renameItem(const std::string& new_name) = 0; + + virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder + virtual void move( LLFolderViewModelItem* parent_listener ) = 0; + + virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed + virtual BOOL removeItem() = 0; + virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0; + + virtual BOOL isItemCopyable() const = 0; + virtual BOOL copyToClipboard() const = 0; + virtual BOOL cutToClipboard() const = 0; + + virtual BOOL isClipboardPasteable() const = 0; + virtual void pasteFromClipboard() = 0; + virtual void pasteLinkFromClipboard() = 0; + + virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; + + virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? + + virtual bool filter( LLFolderViewFilter& filter) = 0; + virtual bool passedFilter(S32 filter_generation = -1) = 0; + virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; + virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) = 0; + virtual void dirtyFilter() = 0; + + virtual S32 getLastFilterGeneration() const = 0; + + virtual bool hasChildren() const = 0; + virtual void addChild(LLFolderViewModelItem* child) = 0; + virtual void removeChild(LLFolderViewModelItem* child) = 0; + + // This method will be called to determine if a drop can be + // performed, and will set drop to TRUE if a drop is + // requested. Returns TRUE if a drop is possible/happened, + // otherwise FALSE. + virtual BOOL dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + std::string& tooltip_msg) = 0; + + virtual void requestSort() = 0; + virtual S32 getSortVersion() = 0; + virtual void setSortVersion(S32 version) = 0; + virtual void setParent(LLFolderViewModelItem* parent) = 0; + +protected: + + friend class LLFolderViewItem; + virtual void setFolderViewItem(LLFolderViewItem* folder_view_item) = 0; + +}; + +class LLFolderViewModelItemCommon : public LLFolderViewModelItem +{ +public: + LLFolderViewModelItemCommon() + : mSortVersion(-1), + mPassedFilter(true), + mPassedFolderFilter(true), + mFolderViewItem(NULL), + mLastFilterGeneration(-1), + mMostFilteredDescendantGeneration(-1), + mParent(NULL) + { + std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); + } + + void requestSort() { mSortVersion = -1; } + S32 getSortVersion() { return mSortVersion; } + void setSortVersion(S32 version) { mSortVersion = version;} + + S32 getLastFilterGeneration() const { return mLastFilterGeneration; } + void dirtyFilter() + { + mLastFilterGeneration = -1; + + // bubble up dirty flag all the way to root + if (mParent) + { + mParent->dirtyFilter(); + } + } + virtual void addChild(LLFolderViewModelItem* child) + { + mChildren.push_back(child); + child->setParent(this); + } + virtual void removeChild(LLFolderViewModelItem* child) + { + mChildren.remove(child); + child->setParent(NULL); + } + +protected: + virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } + + S32 mSortVersion; + bool mPassedFilter; + bool mPassedFolderFilter; + + S32 mLastFilterGeneration; + S32 mMostFilteredDescendantGeneration; + + + typedef std::list<LLFolderViewModelItem*> child_list_t; + child_list_t mChildren; + LLFolderViewModelItem* mParent; + + void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} + LLFolderViewItem* mFolderViewItem; +}; + + +#endif // LLFOLDERVIEWMODEL_H diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 64bc70da58..b31b99f47c 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -253,9 +253,6 @@ set(viewer_SOURCE_FILES llfloaterwhitelistentry.cpp llfloaterwindowsize.cpp llfloaterworldmap.cpp - llfolderview.cpp - llfolderviewitem.cpp - llfolderviewmodel.cpp llfolderviewmodelinventory.cpp llfollowcam.cpp llfriendcard.cpp @@ -813,10 +810,7 @@ set(viewer_HEADER_FILES llfloaterwhitelistentry.h llfloaterwindowsize.h llfloaterworldmap.h - llfolderview.h - llfolderviewmodel.h llfolderviewmodelinventory.h - llfolderviewitem.h llfollowcam.h llfriendcard.h llgesturelistener.h diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp deleted file mode 100644 index 10677db094..0000000000 --- a/indra/newview/llfolderview.cpp +++ /dev/null @@ -1,2105 +0,0 @@ -/** - * @file llfolderview.cpp - * @brief Implementation of the folder view collection of classes. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfolderview.h" -#include "llfolderviewmodel.h" -#include "llclipboard.h" // *TODO: remove this once hack below gone. -#include "llkeyboard.h" -#include "lllineeditor.h" -#include "llmenugl.h" -#include "llpanel.h" -#include "llscrollcontainer.h" // hack to allow scrolling -#include "lltextbox.h" -#include "lltrans.h" -#include "llui.h" -#include "lluictrlfactory.h" - -// Linden library includes -#include "lldbstrings.h" -#include "llfocusmgr.h" -#include "llfontgl.h" -#include "llgl.h" -#include "llrender.h" - -// Third-party library includes -#include <algorithm> - -///---------------------------------------------------------------------------- -/// Local function declarations, constants, enums, and typedefs -///---------------------------------------------------------------------------- - -const S32 RENAME_WIDTH_PAD = 4; -const S32 RENAME_HEIGHT_PAD = 1; -const S32 AUTO_OPEN_STACK_DEPTH = 16; -const S32 MIN_ITEM_WIDTH_VISIBLE = LLFolderViewItem::ICON_WIDTH - + LLFolderViewItem::ICON_PAD - + LLFolderViewItem::ARROW_SIZE - + LLFolderViewItem::TEXT_PAD - + /*first few characters*/ 40; -const S32 MINIMUM_RENAMER_WIDTH = 80; - -// *TODO: move in params in xml if necessary. Requires modification of LLFolderView & LLInventoryPanel Params. -const S32 STATUS_TEXT_HPAD = 6; -const S32 STATUS_TEXT_VPAD = 8; - -enum { - SIGNAL_NO_KEYBOARD_FOCUS = 1, - SIGNAL_KEYBOARD_FOCUS = 2 -}; - -F32 LLFolderView::sAutoOpenTime = 1.f; - -//--------------------------------------------------------------------------- - -// Tells all folders in a folderview to close themselves -// For efficiency, calls setOpenArrangeRecursively(). -// The calling function must then call: -// LLFolderView* root = getRoot(); -// if( root ) -// { -// root->arrange( NULL, NULL ); -// root->scrollToShowSelection(); -// } -// to patch things up. -class LLCloseAllFoldersFunctor : public LLFolderViewFunctor -{ -public: - LLCloseAllFoldersFunctor(BOOL close) { mOpen = !close; } - virtual ~LLCloseAllFoldersFunctor() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - - BOOL mOpen; -}; - - -void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder) -{ - folder->setOpenArrangeRecursively(mOpen); -} - -// Do nothing. -void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item) -{ } - -///---------------------------------------------------------------------------- -/// Class LLFolderViewScrollContainer -///---------------------------------------------------------------------------- - -// virtual -const LLRect LLFolderViewScrollContainer::getScrolledViewRect() const -{ - LLRect rect = LLRect::null; - if (mScrolledView) - { - LLFolderView* folder_view = dynamic_cast<LLFolderView*>(mScrolledView); - if (folder_view) - { - S32 height = folder_view->getRect().getHeight(); - - rect = mScrolledView->getRect(); - rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); - } - } - - return rect; -} - -LLFolderViewScrollContainer::LLFolderViewScrollContainer(const LLScrollContainer::Params& p) -: LLScrollContainer(p) -{} - -///---------------------------------------------------------------------------- -/// Class LLFolderView -///---------------------------------------------------------------------------- -LLFolderView::Params::Params() -: task_id("task_id"), - title("title"), - use_label_suffix("use_label_suffix"), - allow_multiselect("allow_multiselect", true), - show_empty_message("show_empty_message", true), - use_ellipses("use_ellipses", false) -{ - folder_indentation = -4; -} - - -// Default constructor -LLFolderView::LLFolderView(const Params& p) -: LLFolderViewFolder(p), - mScrollContainer( NULL ), - mPopupMenuHandle(), - mAllowMultiSelect(p.allow_multiselect), - mShowEmptyMessage(p.show_empty_message), - mShowFolderHierarchy(FALSE), - mSourceID(p.task_id), - mRenameItem( NULL ), - mNeedsScroll( FALSE ), - mUseLabelSuffix(p.use_label_suffix), - mPinningSelectedItem(FALSE), - mNeedsAutoSelect( FALSE ), - mAutoSelectOverride(FALSE), - mNeedsAutoRename(FALSE), - mShowSelectionContext(FALSE), - mShowSingleSelection(FALSE), - mArrangeGeneration(0), - mSignalSelectCallback(0), - mMinWidth(0), - mDragAndDropThisFrame(FALSE), - mCallbackRegistrar(NULL), - mParentPanel(p.parent_panel), - mUseEllipses(p.use_ellipses), - mDraggingOverItem(NULL), - mStatusTextBox(NULL), - mShowItemLinkOverlays(p.show_item_link_overlays), - mViewModel(p.view_model) -{ - mViewModel->setFolderView(this); - mRoot = this; - - LLRect rect = p.rect; - LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); - setRect( rect ); - reshape(rect.getWidth(), rect.getHeight()); - mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); - mAutoOpenCandidate = NULL; - mAutoOpenTimer.stop(); - mKeyboardSelection = FALSE; - mIndentation = p.folder_indentation; - - //clear label - // go ahead and render root folder as usual - // just make sure the label ("Inventory Folder") never shows up - mLabel = LLStringUtil::null; - - // Escape is handled by reverting the rename, not commiting it (default behavior) - LLLineEditor::Params params; - params.name("ren"); - params.rect(rect); - params.font(getLabelFontForStyle(LLFontGL::NORMAL)); - params.max_length.bytes(DB_INV_ITEM_NAME_STR_LEN); - params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); - params.prevalidate_callback(&LLTextValidate::validateASCIIPrintableNoPipe); - params.commit_on_focus_lost(true); - params.visible(false); - mRenamer = LLUICtrlFactory::create<LLLineEditor> (params); - addChild(mRenamer); - - // Textbox - LLTextBox::Params text_p; - LLFontGL* font = getLabelFontForStyle(mLabelStyle); - LLRect new_r = LLRect(rect.mLeft + ICON_PAD, - rect.mTop - TEXT_PAD, - rect.mRight, - rect.mTop - TEXT_PAD - font->getLineHeight()); - text_p.rect(new_r); - text_p.name(std::string(p.name)); - text_p.font(font); - text_p.visible(false); - text_p.parse_urls(true); - text_p.wrap(true); // allow multiline text. See EXT-7564, EXT-7047 - // set text padding the same as in People panel. EXT-7047, EXT-4837 - text_p.h_pad(STATUS_TEXT_HPAD); - text_p.v_pad(STATUS_TEXT_VPAD); - mStatusTextBox = LLUICtrlFactory::create<LLTextBox> (text_p); - mStatusTextBox->setFollowsLeft(); - mStatusTextBox->setFollowsTop(); - //addChild(mStatusTextBox); - - - // make the popup menu available - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); - if (!menu) - { - menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu"); - } - menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); - mPopupMenuHandle = menu->getHandle(); - - mViewModelItem->openItem(); -} - -// Destroys the object -LLFolderView::~LLFolderView( void ) -{ - closeRenamer(); - - // The release focus call can potentially call the - // scrollcontainer, which can potentially be called with a partly - // destroyed scollcontainer. Just null it out here, and no worries - // about calling into the invalid scroll container. - // Same with the renamer. - mScrollContainer = NULL; - mRenameItem = NULL; - mRenamer = NULL; - mStatusTextBox = NULL; - - mAutoOpenItems.removeAllNodes(); - - if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); - - mAutoOpenItems.removeAllNodes(); - clearSelection(); - mItems.clear(); - mFolders.clear(); - - delete mViewModel; - mViewModel = NULL; -} - -BOOL LLFolderView::canFocusChildren() const -{ - return FALSE; -} - -BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) -{ - LLFolderViewFolder::addFolder(folder); - - // TODO RN: enforce sort order of My Inventory followed by Library - //mFolders.remove(folder); - //if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) - //{ - // mFolders.push_back(folder); - //} - //else - //{ - // mFolders.insert(mFolders.begin(), folder); - //} - - return TRUE; -} - -void LLFolderView::closeAllFolders() -{ - // Close all the folders - setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); - arrangeAll(); -} - -void LLFolderView::openTopLevelFolders() -{ - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->setOpen(TRUE); - } -} - -// This view grows and shrinks to enclose all of its children items and folders. -// *width should be 0 -// conform show folder state works -S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) -{ - mMinWidth = 0; - S32 target_height; - - LLFolderViewFolder::arrange(&mMinWidth, &target_height); - - LLRect scroll_rect = mScrollContainer->getContentWindowRect(); - reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); - - LLRect new_scroll_rect = mScrollContainer->getContentWindowRect(); - if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) - { - reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); - } - - // move item renamer text field to item's new position - updateRenamerPosition(); - - return llround(mTargetHeight); -} - -static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View"); - -void LLFolderView::filter( LLFolderViewFilter& filter ) -{ - LLFastTimer t2(FTM_FILTER); - filter.setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); - - getViewModelItem()->filter(filter); -} - -void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) -{ - LLRect scroll_rect; - if (mScrollContainer) - { - LLView::reshape(width, height, called_from_parent); - scroll_rect = mScrollContainer->getContentWindowRect(); - } - width = llmax(mMinWidth, scroll_rect.getWidth()); - height = llmax(llround(mCurHeight), scroll_rect.getHeight()); - - // Restrict width within scroll container's width - if (mUseEllipses && mScrollContainer) - { - width = scroll_rect.getWidth(); - } - - LLView::reshape(width, height, called_from_parent); - mReshapeSignal(mSelectedItems, FALSE); -} - -void LLFolderView::addToSelectionList(LLFolderViewItem* item) -{ - if (item->isSelected()) - { - removeFromSelectionList(item); - } - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(FALSE); - } - item->setIsCurSelection(TRUE); - mSelectedItems.push_back(item); -} - -void LLFolderView::removeFromSelectionList(LLFolderViewItem* item) -{ - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(FALSE); - } - - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end();) - { - if (*item_iter == item) - { - item_iter = mSelectedItems.erase(item_iter); - } - else - { - ++item_iter; - } - } - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(TRUE); - } -} - -LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) -{ - if(mSelectedItems.size()) - { - LLFolderViewItem* itemp = mSelectedItems.back(); - llassert(itemp->getIsCurSelection()); - return itemp; - } - return NULL; -} - - -// Record the selected item and pass it down the hierachy. -BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus) -{ - mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; - - if( selection == this ) - { - return FALSE; - } - - if( selection && take_keyboard_focus) - { - mParentPanel->setFocus(TRUE); - } - - // clear selection down here because change of keyboard focus can potentially - // affect selection - clearSelection(); - - if(selection) - { - addToSelectionList(selection); - } - - BOOL rv = LLFolderViewFolder::setSelection(selection, openitem, take_keyboard_focus); - if(openitem && selection) - { - selection->getParentFolder()->requestArrange(); - } - - llassert(mSelectedItems.size() <= 1); - - return rv; -} - -BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) -{ - BOOL rv = FALSE; - - // can't select root folder - if(!selection || selection == this) - { - return FALSE; - } - - if (!mAllowMultiSelect) - { - clearSelection(); - } - - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) - { - if (*item_iter == selection) - { - break; - } - } - - BOOL on_list = (item_iter != mSelectedItems.end()); - - if(selected && !on_list) - { - addToSelectionList(selection); - } - if(!selected && on_list) - { - removeFromSelectionList(selection); - } - - rv = LLFolderViewFolder::changeSelection(selection, selected); - - mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; - - return rv; -} - -static LLFastTimer::DeclareTimer FTM_SANITIZE_SELECTION("Sanitize Selection"); -void LLFolderView::sanitizeSelection() -{ - LLFastTimer _(FTM_SANITIZE_SELECTION); - // store off current item in case it is automatically deselected - // and we want to preserve context - LLFolderViewItem* original_selected_item = getCurSelectedItem(); - - std::vector<LLFolderViewItem*> items_to_remove; - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) - { - LLFolderViewItem* item = *item_iter; - - // ensure that each ancestor is open and potentially passes filtering - BOOL visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item - // modify with parent open and filters states - LLFolderViewFolder* parent_folder = item->getParentFolder(); - // Move up through parent folders and see what's visible - while(parent_folder) - { - visible = visible && parent_folder->isOpen() && parent_folder->getViewModelItem()->potentiallyVisible(); - parent_folder = parent_folder->getParentFolder(); - } - - // deselect item if any ancestor is closed or didn't pass filter requirements. - if (!visible) - { - items_to_remove.push_back(item); - } - - // disallow nested selections (i.e. folder items plus one or more ancestors) - // could check cached mum selections count and only iterate if there are any - // but that may be a premature optimization. - selected_items_t::iterator other_item_iter; - for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) - { - LLFolderViewItem* other_item = *other_item_iter; - for( parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) - { - if (parent_folder == item) - { - // this is a descendent of the current folder, remove from list - items_to_remove.push_back(other_item); - break; - } - } - } - - // Don't allow invisible items (such as root folders) to be selected. - if (item == getRoot()) - { - items_to_remove.push_back(item); - } - } - - std::vector<LLFolderViewItem*>::iterator item_it; - for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) - { - changeSelection(*item_it, FALSE); // toggle selection (also removes from list) - } - - // if nothing selected after prior constraints... - if (mSelectedItems.empty()) - { - // ...select first available parent of original selection - LLFolderViewItem* new_selection = NULL; - if (original_selected_item) - { - for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder(); - parent_folder; - parent_folder = parent_folder->getParentFolder()) - { - if (parent_folder->getViewModelItem()->potentiallyVisible()) - { - // give initial selection to first ancestor folder that potentially passes the filter - if (!new_selection) - { - new_selection = parent_folder; - } - - // if any ancestor folder of original item is closed, move the selection up - // to the highest closed - if (!parent_folder->isOpen()) - { - new_selection = parent_folder; - } - } - } - } - else - { - new_selection = NULL; - } - - if (new_selection) - { - setSelection(new_selection, FALSE, FALSE); - } - } -} - -void LLFolderView::clearSelection() -{ - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); - item_it != mSelectedItems.end(); - ++item_it) - { - (*item_it)->setUnselected(); - } - - mSelectedItems.clear(); -} - -std::set<LLFolderViewItem*> LLFolderView::getSelectionList() const -{ - std::set<LLFolderViewItem*> selection; - std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin())); - return selection; -} - -BOOL LLFolderView::startDrag(LLToolDragAndDrop::ESource source) -{ - std::vector<EDragAndDropType> types; - uuid_vec_t cargo_ids; - selected_items_t::iterator item_it; - BOOL can_drag = TRUE; - if (!mSelectedItems.empty()) - { - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - EDragAndDropType type = DAD_NONE; - LLUUID id = LLUUID::null; - can_drag = can_drag && (*item_it)->getViewModelItem()->startDrag(&type, &id); - - types.push_back(type); - cargo_ids.push_back(id); - } - - LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, source, mSourceID); - } - return can_drag; -} - -void LLFolderView::commitRename( const LLSD& data ) -{ - finishRenamingItem(); -} - -void LLFolderView::draw() -{ - //LLFontGL* font = getLabelFontForStyle(mLabelStyle); - - // if cursor has moved off of me during drag and drop - // close all auto opened folders - if (!mDragAndDropThisFrame) - { - closeAutoOpenedFolders(); - } - - // while dragging, update selection rendering to reflect single/multi drag status - if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) - { - EAcceptance last_accept = LLToolDragAndDrop::getInstance()->getLastAccept(); - if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE) - { - setShowSingleSelection(TRUE); - } - else - { - setShowSingleSelection(FALSE); - } - } - else - { - setShowSingleSelection(FALSE); - } - - - if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout") || !mSearchString.size()) - { - mSearchString.clear(); - } - - if (hasVisibleChildren()) - { - mStatusTextBox->setVisible( FALSE ); - } - else if (mShowEmptyMessage) - { - mStatusTextBox->setValue(getFolderViewModel()->getStatusText()); - mStatusTextBox->setVisible( TRUE ); - - // firstly reshape message textbox with current size. This is necessary to - // LLTextBox::getTextPixelHeight works properly - const LLRect local_rect = getLocalRect(); - mStatusTextBox->setShape(local_rect); - - // get preferable text height... - S32 pixel_height = mStatusTextBox->getTextPixelHeight(); - bool height_changed = local_rect.getHeight() != pixel_height; - if (height_changed) - { - // ... if it does not match current height, lets rearrange current view. - // This will indirectly call ::arrange and reshape of the status textbox. - // We should call this method to also notify parent about required rect. - // See EXT-7564, EXT-7047. - S32 height = 0; - S32 width = 0; - S32 total_height = arrange( &width, &height ); - notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); - - LLUI::popMatrix(); - LLUI::pushMatrix(); - LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); - } - } - - // skip over LLFolderViewFolder::draw since we don't want the folder icon, label, - // and arrow for the root folder - LLView::draw(); - - mDragAndDropThisFrame = FALSE; -} - -void LLFolderView::finishRenamingItem( void ) -{ - if(!mRenamer) - { - return; - } - if( mRenameItem ) - { - mRenameItem->rename( mRenamer->getText() ); - } - - closeRenamer(); - - // List is re-sorted alphabetically, so scroll to make sure the selected item is visible. - scrollToShowSelection(); -} - -void LLFolderView::closeRenamer( void ) -{ - if (mRenamer && mRenamer->getVisible()) - { - // Triggers onRenamerLost() that actually closes the renamer. - LLUI::removePopup(mRenamer); - } -} - -bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector<LLFolderViewItem*>& selectedItems) -{ - LLFolderViewItem* item_parent = dynamic_cast<LLFolderViewItem*>(item->getParent()); - - if (item_parent) - { - for(std::vector<LLFolderViewItem*>::const_iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) - { - const LLFolderViewItem* const selected_item = (*it); - - LLFolderViewItem* parent = item_parent; - - while (parent) - { - if (selected_item == parent) - { - return true; - } - - parent = dynamic_cast<LLFolderViewItem*>(parent->getParent()); - } - } - } - - return false; -} - -void LLFolderView::removeSelectedItems() -{ - if(getVisible() && getEnabled()) - { - // just in case we're removing the renaming item. - mRenameItem = NULL; - - // create a temporary structure which we will use to remove - // items, since the removal will futz with internal data - // structures. - std::vector<LLFolderViewItem*> items; - S32 count = mSelectedItems.size(); - if(count == 0) return; - LLFolderViewItem* item = NULL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - item = *item_it; - if (item && item->isRemovable()) - { - items.push_back(item); - } - else - { - llinfos << "Cannot delete " << item->getName() << llendl; - return; - } - } - - // iterate through the new container. - count = items.size(); - LLUUID new_selection_id; - if(count == 1) - { - LLFolderViewItem* item_to_delete = items[0]; - LLFolderViewFolder* parent = item_to_delete->getParentFolder(); - LLFolderViewItem* new_selection = item_to_delete->getNextOpenNode(FALSE); - if (!new_selection) - { - new_selection = item_to_delete->getPreviousOpenNode(FALSE); - } - if(parent) - { - if (item_to_delete->remove()) - { - // change selection on successful delete - if (new_selection) - { - getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); - } - else - { - getRoot()->setSelection(NULL, mParentPanel->hasFocus()); - } - } - } - arrangeAll(); - } - else if (count > 1) - { - LLDynamicArray<LLFolderViewModelItem*> listeners; - LLFolderViewModelItem* listener; - LLFolderViewItem* last_item = items[count - 1]; - LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); - while(new_selection && new_selection->isSelected()) - { - new_selection = new_selection->getNextOpenNode(FALSE); - } - if (!new_selection) - { - new_selection = last_item->getPreviousOpenNode(FALSE); - while (new_selection && (new_selection->isSelected() || isDescendantOfASelectedItem(new_selection, items))) - { - new_selection = new_selection->getPreviousOpenNode(FALSE); - } - } - if (new_selection) - { - getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); - } - else - { - getRoot()->setSelection(NULL, mParentPanel->hasFocus()); - } - - for(S32 i = 0; i < count; ++i) - { - listener = items[i]->getViewModelItem(); - if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewModelItem*>::FAIL)) - { - listeners.put(listener); - } - } - listener = static_cast<LLFolderViewModelItem*>(listeners.get(0)); - if(listener) - { - listener->removeBatch(listeners); - } - } - arrangeAll(); - scrollToShowSelection(); - } -} - -// TODO RN: abstract -// open the selected item. -void LLFolderView::openSelectedItems( void ) -{ - //TODO RN: get working again - //if(getVisible() && getEnabled()) - //{ - // if (mSelectedItems.size() == 1) - // { - // mSelectedItems.front()->openItem(); - // } - // else - // { - // LLMultiPreview* multi_previewp = new LLMultiPreview(); - // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - // selected_items_t::iterator item_it; - // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - // { - // // IT_{OBJECT,ATTACHMENT} creates LLProperties - // // floaters; others create LLPreviews. Put - // // each one in the right type of container. - // LLFolderViewModelItemInventory* listener = static_cast<LLFolderViewModelItemInventory*>((*item_it)->getViewModelItem()); - // bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); - // if (is_prop) - // LLFloater::setFloaterHost(multi_propertiesp); - // else - // LLFloater::setFloaterHost(multi_previewp); - // listener->openItem(); - // } - - // LLFloater::setFloaterHost(NULL); - // // *NOTE: LLMulti* will safely auto-delete when open'd - // // without any children. - // multi_previewp->openFloater(LLSD()); - // multi_propertiesp->openFloater(LLSD()); - // } - //} -} - -void LLFolderView::propertiesSelectedItems( void ) -{ - //TODO RN: get working again - //if(getVisible() && getEnabled()) - //{ - // if (mSelectedItems.size() == 1) - // { - // LLFolderViewItem* folder_item = mSelectedItems.front(); - // if(!folder_item) return; - // folder_item->getViewModelItem()->showProperties(); - // } - // else - // { - // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - // LLFloater::setFloaterHost(multi_propertiesp); - - // selected_items_t::iterator item_it; - // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - // { - // (*item_it)->getViewModelItem()->showProperties(); - // } - - // LLFloater::setFloaterHost(NULL); - // multi_propertiesp->openFloater(LLSD()); - // } - //} -} - - -void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) -{ - if ((mAutoOpenItems.check() == item) || - (mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) || - item->isOpen()) - { - return; - } - - // close auto-opened folders - LLFolderViewFolder* close_item = mAutoOpenItems.check(); - while (close_item && close_item != item->getParentFolder()) - { - mAutoOpenItems.pop(); - close_item->setOpenArrangeRecursively(FALSE); - close_item = mAutoOpenItems.check(); - } - - item->requestArrange(); - - mAutoOpenItems.push(item); - - item->setOpen(TRUE); - LLRect content_rect = mScrollContainer->getContentWindowRect(); - LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0); - scrollToShowItem(item, constraint_rect); -} - -void LLFolderView::closeAutoOpenedFolders() -{ - while (mAutoOpenItems.check()) - { - LLFolderViewFolder* close_item = mAutoOpenItems.pop(); - close_item->setOpen(FALSE); - } - - if (mAutoOpenCandidate) - { - mAutoOpenCandidate->setAutoOpenCountdown(0.f); - } - mAutoOpenCandidate = NULL; - mAutoOpenTimer.stop(); -} - -BOOL LLFolderView::autoOpenTest(LLFolderViewFolder* folder) -{ - if (folder && mAutoOpenCandidate == folder) - { - if (mAutoOpenTimer.getStarted()) - { - if (!mAutoOpenCandidate->isOpen()) - { - mAutoOpenCandidate->setAutoOpenCountdown(clamp_rescale(mAutoOpenTimer.getElapsedTimeF32(), 0.f, sAutoOpenTime, 0.f, 1.f)); - } - if (mAutoOpenTimer.getElapsedTimeF32() > sAutoOpenTime) - { - autoOpenItem(folder); - mAutoOpenTimer.stop(); - return TRUE; - } - } - return FALSE; - } - - // otherwise new candidate, restart timer - if (mAutoOpenCandidate) - { - mAutoOpenCandidate->setAutoOpenCountdown(0.f); - } - mAutoOpenCandidate = folder; - mAutoOpenTimer.start(); - return FALSE; -} - -BOOL LLFolderView::canCopy() const -{ - if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) - { - return FALSE; - } - - for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - const LLFolderViewItem* item = *selected_it; - if (!item->getViewModelItem()->isItemCopyable()) - { - return FALSE; - } - } - return TRUE; -} - -// copy selected item -void LLFolderView::copy() -{ - // *NOTE: total hack to clear the inventory clipboard - LLClipboard::instance().reset(); - S32 count = mSelectedItems.size(); - if(getVisible() && getEnabled() && (count > 0)) - { - LLFolderViewModelItem* listener = NULL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - listener = (*item_it)->getViewModelItem(); - if(listener) - { - listener->copyToClipboard(); - } - } - } - mSearchString.clear(); -} - -BOOL LLFolderView::canCut() const -{ - if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) - { - return FALSE; - } - - for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - const LLFolderViewItem* item = *selected_it; - const LLFolderViewModelItem* listener = item->getViewModelItem(); - - if (!listener || !listener->isItemRemovable()) - { - return FALSE; - } - } - return TRUE; -} - -void LLFolderView::cut() -{ - // clear the inventory clipboard - LLClipboard::instance().reset(); - S32 count = mSelectedItems.size(); - if(getVisible() && getEnabled() && (count > 0)) - { - LLFolderViewModelItem* listener = NULL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - listener = (*item_it)->getViewModelItem(); - if(listener) - { - listener->cutToClipboard(); - listener->removeItem(); - } - } - } - mSearchString.clear(); -} - -BOOL LLFolderView::canPaste() const -{ - if (mSelectedItems.empty()) - { - return FALSE; - } - - if(getVisible() && getEnabled()) - { - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); - item_it != mSelectedItems.end(); ++item_it) - { - // *TODO: only check folders and parent folders of items - const LLFolderViewItem* item = (*item_it); - const LLFolderViewModelItem* listener = item->getViewModelItem(); - if(!listener || !listener->isClipboardPasteable()) - { - const LLFolderViewFolder* folderp = item->getParentFolder(); - listener = folderp->getViewModelItem(); - if (!listener || !listener->isClipboardPasteable()) - { - return FALSE; - } - } - } - return TRUE; - } - return FALSE; -} - -// paste selected item -void LLFolderView::paste() -{ - if(getVisible() && getEnabled()) - { - // find set of unique folders to paste into - std::set<LLFolderViewFolder*> folder_set; - - selected_items_t::iterator selected_it; - for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - LLFolderViewItem* item = *selected_it; - LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(item); - if (folder == NULL) - { - item = item->getParentFolder(); - } - folder_set.insert(folder); - } - - std::set<LLFolderViewFolder*>::iterator set_iter; - for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) - { - LLFolderViewModelItem* listener = (*set_iter)->getViewModelItem(); - if(listener && listener->isClipboardPasteable()) - { - listener->pasteFromClipboard(); - } - } - } - mSearchString.clear(); -} - -// public rename functionality - can only start the process -void LLFolderView::startRenamingSelectedItem( void ) -{ - // make sure selection is visible - scrollToShowSelection(); - - S32 count = mSelectedItems.size(); - LLFolderViewItem* item = NULL; - if(count > 0) - { - item = mSelectedItems.front(); - } - if(getVisible() && getEnabled() && (count == 1) && item && item->getViewModelItem() && - item->getViewModelItem()->isItemRenameable()) - { - mRenameItem = item; - - updateRenamerPosition(); - - - mRenamer->setText(item->getName()); - mRenamer->selectAll(); - mRenamer->setVisible( TRUE ); - // set focus will fail unless item is visible - mRenamer->setFocus( TRUE ); - mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); - LLUI::addPopup(mRenamer); - } -} - -BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) -{ - BOOL handled = FALSE; - - // SL-51858: Key presses are not being passed to the Popup menu. - // A proper fix is non-trivial so instead just close the menu. - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->isOpen()) - { - LLMenuGL::sMenuContainer->hideMenus(); - } - - LLView *item = NULL; - if (getChildCount() > 0) - { - item = *(getChildList()->begin()); - } - - switch( key ) - { - case KEY_F2: - mSearchString.clear(); - startRenamingSelectedItem(); - handled = TRUE; - break; - - case KEY_RETURN: - if (mask == MASK_NONE) - { - if( mRenameItem && mRenamer->getVisible() ) - { - finishRenamingItem(); - mSearchString.clear(); - handled = TRUE; - } - else - { - LLFolderView::openSelectedItems(); - handled = TRUE; - } - } - break; - - case KEY_ESCAPE: - if( mRenameItem && mRenamer->getVisible() ) - { - closeRenamer(); - handled = TRUE; - } - mSearchString.clear(); - break; - - case KEY_PAGE_UP: - mSearchString.clear(); - mScrollContainer->pageUp(30); - handled = TRUE; - break; - - case KEY_PAGE_DOWN: - mSearchString.clear(); - mScrollContainer->pageDown(30); - handled = TRUE; - break; - - case KEY_HOME: - mSearchString.clear(); - mScrollContainer->goToTop(); - handled = TRUE; - break; - - case KEY_END: - mSearchString.clear(); - mScrollContainer->goToBottom(); - break; - - case KEY_DOWN: - if((mSelectedItems.size() > 0) && mScrollContainer) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - - if (!mKeyboardSelection) - { - setSelection(last_selected, FALSE, TRUE); - mKeyboardSelection = TRUE; - } - - LLFolderViewItem* next = NULL; - if (mask & MASK_SHIFT) - { - // don't shift select down to children of folders (they are implicitly selected through parent) - next = last_selected->getNextOpenNode(FALSE); - if (next) - { - if (next->isSelected()) - { - // shrink selection - getRoot()->changeSelection(last_selected, FALSE); - } - else if (last_selected->getParentFolder() == next->getParentFolder()) - { - // grow selection - getRoot()->changeSelection(next, TRUE); - } - } - } - else - { - next = last_selected->getNextOpenNode(); - if( next ) - { - if (next == last_selected) - { - //special case for LLAccordionCtrl - if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed - { - clearSelection(); - return TRUE; - } - return FALSE; - } - setSelection( next, FALSE, TRUE ); - } - else - { - //special case for LLAccordionCtrl - if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed - { - clearSelection(); - return TRUE; - } - return FALSE; - } - } - scrollToShowSelection(); - mSearchString.clear(); - handled = TRUE; - } - break; - - case KEY_UP: - if((mSelectedItems.size() > 0) && mScrollContainer) - { - LLFolderViewItem* last_selected = mSelectedItems.back(); - - if (!mKeyboardSelection) - { - setSelection(last_selected, FALSE, TRUE); - mKeyboardSelection = TRUE; - } - - LLFolderViewItem* prev = NULL; - if (mask & MASK_SHIFT) - { - // don't shift select down to children of folders (they are implicitly selected through parent) - prev = last_selected->getPreviousOpenNode(FALSE); - if (prev) - { - if (prev->isSelected()) - { - // shrink selection - getRoot()->changeSelection(last_selected, FALSE); - } - else if (last_selected->getParentFolder() == prev->getParentFolder()) - { - // grow selection - getRoot()->changeSelection(prev, TRUE); - } - } - } - else - { - prev = last_selected->getPreviousOpenNode(); - if( prev ) - { - if (prev == this) - { - // If case we are in accordion tab notify parent to go to the previous accordion - if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed - { - clearSelection(); - return TRUE; - } - - return FALSE; - } - setSelection( prev, FALSE, TRUE ); - } - } - scrollToShowSelection(); - mSearchString.clear(); - - handled = TRUE; - } - break; - - case KEY_RIGHT: - if(mSelectedItems.size()) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - last_selected->setOpen( TRUE ); - mSearchString.clear(); - handled = TRUE; - } - break; - - case KEY_LEFT: - if(mSelectedItems.size()) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - LLFolderViewItem* parent_folder = last_selected->getParentFolder(); - if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder()) - { - setSelection(parent_folder, FALSE, TRUE); - } - else - { - last_selected->setOpen( FALSE ); - } - mSearchString.clear(); - scrollToShowSelection(); - handled = TRUE; - } - break; - } - - if (!handled && mParentPanel->hasFocus()) - { - if (key == KEY_BACKSPACE) - { - mSearchTimer.reset(); - if (mSearchString.size()) - { - mSearchString.erase(mSearchString.size() - 1, 1); - } - search(getCurSelectedItem(), mSearchString, FALSE); - handled = TRUE; - } - } - - return handled; -} - - -BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) -{ - if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL - { - return FALSE; - } - - if (uni_char > 0x7f) - { - llwarns << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << llendl; - return FALSE; - } - - BOOL handled = FALSE; - if (mParentPanel->hasFocus()) - { - // SL-51858: Key presses are not being passed to the Popup menu. - // A proper fix is non-trivial so instead just close the menu. - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->isOpen()) - { - LLMenuGL::sMenuContainer->hideMenus(); - } - - //do text search - if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout")) - { - mSearchString.clear(); - } - mSearchTimer.reset(); - if (mSearchString.size() < 128) - { - mSearchString += uni_char; - } - search(getCurSelectedItem(), mSearchString, FALSE); - - handled = TRUE; - } - - return handled; -} - - -BOOL LLFolderView::canDoDelete() const -{ - if (mSelectedItems.size() == 0) return FALSE; - - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - if (!(*item_it)->getViewModelItem()->isItemRemovable()) - { - return FALSE; - } - } - return TRUE; -} - -void LLFolderView::doDelete() -{ - if(mSelectedItems.size() > 0) - { - removeSelectedItems(); - } -} - - -BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - mKeyboardSelection = FALSE; - mSearchString.clear(); - - mParentPanel->setFocus(TRUE); - - LLEditMenuHandler::gEditMenuHandler = this; - - return LLView::handleMouseDown( x, y, mask ); -} - -BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward) -{ - // get first selected item - LLFolderViewItem* search_item = first_item; - - // make sure search string is upper case - std::string upper_case_string = search_string; - LLStringUtil::toUpper(upper_case_string); - - // if nothing selected, select first item in folder - if (!search_item) - { - // start from first item - search_item = getNextFromChild(NULL); - } - - // search over all open nodes for first substring match (with wrapping) - BOOL found = FALSE; - LLFolderViewItem* original_search_item = search_item; - do - { - // wrap at end - if (!search_item) - { - if (backward) - { - search_item = getPreviousFromChild(NULL); - } - else - { - search_item = getNextFromChild(NULL); - } - if (!search_item || search_item == original_search_item) - { - break; - } - } - - const std::string current_item_label(search_item->getViewModelItem()->getSearchableName()); - S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); - if (!current_item_label.compare(0, search_string_length, upper_case_string)) - { - found = TRUE; - break; - } - if (backward) - { - search_item = search_item->getPreviousOpenNode(); - } - else - { - search_item = search_item->getNextOpenNode(); - } - - } while(search_item != original_search_item); - - - if (found) - { - setSelection(search_item, FALSE, TRUE); - scrollToShowSelection(); - } - - return found; -} - -BOOL LLFolderView::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ - // skip LLFolderViewFolder::handleDoubleClick() - return LLView::handleDoubleClick( x, y, mask ); -} - -BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - // all user operations move keyboard focus to inventory - // this way, we know when to stop auto-updating a search - mParentPanel->setFocus(TRUE); - - BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL; - S32 count = mSelectedItems.size(); - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if ( handled - && ( count > 0 && (hasVisibleChildren()) ) // show menu only if selected items are visible - && menu ) - { - if (mCallbackRegistrar) - mCallbackRegistrar->pushScope(); - - updateMenuOptions(menu); - - menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, menu, x, y); - if (mCallbackRegistrar) - mCallbackRegistrar->popScope(); - } - else - { - if (menu && menu->getVisible()) - { - menu->setVisible(FALSE); - } - setSelection(NULL, FALSE, TRUE); - } - return handled; -} - -// Add "--no options--" if the menu is completely blank. -BOOL LLFolderView::addNoOptions(LLMenuGL* menu) const -{ - const std::string nooptions_str = "--no options--"; - LLView *nooptions_item = NULL; - - const LLView::child_list_t *list = menu->getChildList(); - for (LLView::child_list_t::const_iterator itor = list->begin(); - itor != list->end(); - ++itor) - { - LLView *menu_item = (*itor); - if (menu_item->getVisible()) - { - return FALSE; - } - std::string name = menu_item->getName(); - if (menu_item->getName() == nooptions_str) - { - nooptions_item = menu_item; - } - } - if (nooptions_item) - { - nooptions_item->setVisible(TRUE); - nooptions_item->setEnabled(FALSE); - return TRUE; - } - return FALSE; -} - -BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask ) -{ - return LLView::handleHover( x, y, mask ); -} - -BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - mDragAndDropThisFrame = TRUE; - // have children handle it first - BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, - accept, tooltip_msg); - - // when drop is not handled by child, it should be handled - // by the folder which is the hierarchy root. - if (!handled) - { - handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - } - - return handled; -} - -void LLFolderView::deleteAllChildren() -{ - closeRenamer(); - if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); - mPopupMenuHandle = LLHandle<LLView>(); - mScrollContainer = NULL; - mRenameItem = NULL; - mRenamer = NULL; - mStatusTextBox = NULL; - - clearSelection(); - LLView::deleteAllChildren(); -} - -void LLFolderView::scrollToShowSelection() -{ - if ( mSelectedItems.size() ) - { - mNeedsScroll = TRUE; - } -} - -// If the parent is scroll container, scroll it to make the selection -// is maximally visible. -void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect) -{ - if (!mScrollContainer) return; - - // don't scroll to items when mouse is being used to scroll/drag and drop - if (gFocusMgr.childHasMouseCapture(mScrollContainer)) - { - mNeedsScroll = FALSE; - return; - } - - // if item exists and is in visible portion of parent folder... - if(item) - { - LLRect local_rect = item->getLocalRect(); - LLRect item_scrolled_rect; // item position relative to display area of scroller - LLRect visible_doc_rect = mScrollContainer->getVisibleContentRect(); - - S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); - S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight(); - // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder - S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); - - // get portion of item that we want to see... - LLRect item_local_rect = LLRect(item->getIndentation(), - local_rect.getHeight(), - llmin(MIN_ITEM_WIDTH_VISIBLE, local_rect.getWidth()), - llmax(0, local_rect.getHeight() - max_height_to_show)); - - LLRect item_doc_rect; - - item->localRectToOtherView(item_local_rect, &item_doc_rect, this); - - mScrollContainer->scrollToShowRect( item_doc_rect, constraint_rect ); - - } -} - -LLRect LLFolderView::getVisibleRect() -{ - S32 visible_height = mScrollContainer->getRect().getHeight(); - S32 visible_width = mScrollContainer->getRect().getWidth(); - LLRect visible_rect; - visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height); - return visible_rect; -} - -BOOL LLFolderView::getShowSelectionContext() -{ - if (mShowSelectionContext) - { - return TRUE; - } - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->getVisible()) - { - return TRUE; - } - return FALSE; -} - -void LLFolderView::setShowSingleSelection(BOOL show) -{ - if (show != mShowSingleSelection) - { - mMultiSelectionFadeTimer.reset(); - mShowSingleSelection = show; - } -} - -static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select"); -static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory"); - -// Main idle routine -void LLFolderView::update() -{ - // If this is associated with the user's inventory, don't do anything - // until that inventory is loaded up. - LLFastTimer t2(FTM_INVENTORY); - - if (getFolderViewModel()->getFilter()->isModified() && getFolderViewModel()->getFilter()->isNotDefault()) - { - mNeedsAutoSelect = TRUE; - } - getFolderViewModel()->getFilter()->clearModified(); - - // filter to determine visibility before arranging - filter(*(getFolderViewModel()->getFilter())); - - // automatically show matching items, and select first one if we had a selection - if (mNeedsAutoSelect) - { - LLFastTimer t3(FTM_AUTO_SELECT); - // select new item only if a filtered item not currently selected - LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); - if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->getViewModelItem()->potentiallyVisible())) - { - // these are named variables to get around gcc not binding non-const references to rvalues - // and functor application is inherently non-const to allow for stateful functors - LLSelectFirstFilteredItem functor; - applyFunctorRecursively(functor); - } - - // Open filtered folders for folder views with mAutoSelectOverride=TRUE. - // Used by LLPlacesFolderView. - if (getFolderViewModel()->getFilter()->showAllResults()) - { - // these are named variables to get around gcc not binding non-const references to rvalues - // and functor application is inherently non-const to allow for stateful functors - LLOpenFilteredFolders functor; - applyFunctorRecursively(functor); - } - - scrollToShowSelection(); - } - - BOOL filter_finished = getViewModelItem()->passedFilter() - && mViewModel->contentsReady(); - if (filter_finished - || gFocusMgr.childHasKeyboardFocus(getParent()) // assume we are inside a scroll container - || gFocusMgr.childHasMouseCapture(getParent())) - { - // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process - mNeedsAutoSelect = FALSE; - } - - - // during filtering process, try to pin selected item's location on screen - // this will happen when searching your inventory and when new items arrive - if (!filter_finished) - { - // calculate rectangle to pin item to at start of animated rearrange - if (!mPinningSelectedItem && !mSelectedItems.empty()) - { - // lets pin it! - mPinningSelectedItem = TRUE; - - LLRect visible_content_rect = mScrollContainer->getVisibleContentRect(); - LLFolderViewItem* selected_item = mSelectedItems.back(); - - LLRect item_rect; - selected_item->localRectToOtherView(selected_item->getLocalRect(), &item_rect, this); - // if item is visible in scrolled region - if (visible_content_rect.overlaps(item_rect)) - { - // then attempt to keep it in same place on screen - mScrollConstraintRect = item_rect; - mScrollConstraintRect.translate(-visible_content_rect.mLeft, -visible_content_rect.mBottom); - } - else - { - // otherwise we just want it onscreen somewhere - LLRect content_rect = mScrollContainer->getContentWindowRect(); - mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); - } - } - } - else - { - // stop pinning selected item after folders stop rearranging - if (!needsArrange()) - { - mPinningSelectedItem = FALSE; - } - } - - LLRect constraint_rect; - if (mPinningSelectedItem) - { - // use last known constraint rect for pinned item - constraint_rect = mScrollConstraintRect; - } - else - { - // during normal use (page up/page down, etc), just try to fit item on screen - LLRect content_rect = mScrollContainer->getContentWindowRect(); - constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); - } - - BOOL is_visible = isInVisibleChain(); - - if ( is_visible ) - { - sanitizeSelection(); - if( needsArrange() ) - { - S32 height = 0; - S32 width = 0; - S32 total_height = arrange( &width, &height ); - notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); - } - } - - if (mSelectedItems.size() && mNeedsScroll) - { - scrollToShowItem(mSelectedItems.back(), constraint_rect); - // continue scrolling until animated layout change is done - if (filter_finished - && (!needsArrange() || !is_visible)) - { - mNeedsScroll = FALSE; - } - } - - if (mSignalSelectCallback) - { - //RN: we use keyboard focus as a proxy for user-explicit actions - BOOL take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS); - mSelectSignal(mSelectedItems, take_keyboard_focus); - } - mSignalSelectCallback = FALSE; -} - -void LLFolderView::dumpSelectionInformation() -{ - llinfos << "LLFolderView::dumpSelectionInformation()" << llendl; - llinfos << "****************************************" << llendl; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - llinfos << " " << (*item_it)->getName() << llendl; - } - llinfos << "****************************************" << llendl; -} - -void LLFolderView::updateRenamerPosition() -{ - if(mRenameItem) - { - // See also LLFolderViewItem::draw() - S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mRenameItem->getIndentation(); - S32 y = mRenameItem->getRect().getHeight() - mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; - mRenameItem->localPointToScreen( x, y, &x, &y ); - screenPointToLocal( x, y, &x, &y ); - mRenamer->setOrigin( x, y ); - - LLRect scroller_rect(0, 0, LLUI::getWindowSize().mV[VX], 0); - if (mScrollContainer) - { - scroller_rect = mScrollContainer->getContentWindowRect(); - } - - S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); - S32 height = mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; - mRenamer->reshape( width, height, TRUE ); - } -} - -// Update visibility and availability (i.e. enabled/disabled) of context menu items. -void LLFolderView::updateMenuOptions(LLMenuGL* menu) -{ - const LLView::child_list_t *list = menu->getChildList(); - - LLView::child_list_t::const_iterator menu_itor; - for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor) - { - (*menu_itor)->setVisible(FALSE); - (*menu_itor)->pushVisible(TRUE); - (*menu_itor)->setEnabled(TRUE); - } - - // Successively filter out invalid options - - U32 flags = FIRST_SELECTED_ITEM; - for (selected_items_t::iterator item_itor = mSelectedItems.begin(); - item_itor != mSelectedItems.end(); - ++item_itor) - { - LLFolderViewItem* selected_item = (*item_itor); - selected_item->buildContextMenu(*menu, flags); - flags = 0x0; - } - - addNoOptions(menu); -} - -// Refresh the context menu (that is already shown). -void LLFolderView::updateMenu() -{ - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->getVisible()) - { - updateMenuOptions(menu); - menu->needsArrange(); // update menu height if needed - } -} - -bool LLFolderView::selectFirstItem() -{ - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();++iter) - { - LLFolderViewFolder* folder = (*iter ); - if (folder->getVisible()) - { - LLFolderViewItem* itemp = folder->getNextFromChild(0,true); - if(itemp) - setSelection(itemp,FALSE,TRUE); - return true; - } - - } - for(items_t::iterator iit = mItems.begin(); - iit != mItems.end(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - if (itemp->getVisible()) - { - setSelection(itemp,FALSE,TRUE); - return true; - } - } - return false; -} -bool LLFolderView::selectLastItem() -{ - for(items_t::reverse_iterator iit = mItems.rbegin(); - iit != mItems.rend(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - if (itemp->getVisible()) - { - setSelection(itemp,FALSE,TRUE); - return true; - } - } - for (folders_t::reverse_iterator iter = mFolders.rbegin(); - iter != mFolders.rend();++iter) - { - LLFolderViewFolder* folder = (*iter); - if (folder->getVisible()) - { - LLFolderViewItem* itemp = folder->getPreviousFromChild(0,true); - if(itemp) - setSelection(itemp,FALSE,TRUE); - return true; - } - } - return false; -} - - -S32 LLFolderView::notify(const LLSD& info) -{ - if(info.has("action")) - { - std::string str_action = info["action"]; - if(str_action == "select_first") - { - setFocus(true); - selectFirstItem(); - scrollToShowSelection(); - return 1; - - } - else if(str_action == "select_last") - { - setFocus(true); - selectLastItem(); - scrollToShowSelection(); - return 1; - } - } - return 0; -} - - -///---------------------------------------------------------------------------- -/// Local function definitions -///---------------------------------------------------------------------------- - -void LLFolderView::onRenamerLost() -{ - if (mRenamer && mRenamer->getVisible()) - { - mRenamer->setVisible(FALSE); - - // will commit current name (which could be same as original name) - mRenamer->setFocus(FALSE); - } - - if( mRenameItem ) - { - setSelection( mRenameItem, TRUE ); - mRenameItem = NULL; - } -} - -S32 LLFolderView::getItemHeight() -{ - if(!hasVisibleChildren()) - { - //We need to display status textbox, let's reserve some place for it - return llmax(0, mStatusTextBox->getTextPixelHeight()); - } - return 0; -} diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h deleted file mode 100644 index 78f1d8aff2..0000000000 --- a/indra/newview/llfolderview.h +++ /dev/null @@ -1,393 +0,0 @@ -/** - * @file llfolderview.h - * @brief Definition of the folder view collection of classes. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -/** - * - * The folder view collection of classes provides an interface for - * making a 'folder view' similar to the way the a single pane file - * folder interface works. - * - */ - -#ifndef LL_LLFOLDERVIEW_H -#define LL_LLFOLDERVIEW_H - -#include "llfolderviewitem.h" // because LLFolderView is-a LLFolderViewFolder - -#include "lluictrl.h" -#include "v4color.h" -#include "stdenums.h" -#include "lldepthstack.h" -#include "lleditmenuhandler.h" -#include "llfontgl.h" -#include "llscrollcontainer.h" -#include "lltooldraganddrop.h" - -class LLFolderViewModelInterface; -class LLFolderViewFolder; -class LLFolderViewItem; -class LLFolderViewFilter; -class LLPanel; -class LLLineEditor; -class LLMenuGL; -class LLUICtrl; -class LLTextBox; - -/** - * Class LLFolderViewScrollContainer - * - * A scroll container which provides the information about the height - * of currently displayed folder view contents. - * Used for updating vertical scroll bar visibility in inventory panel. - * See LLScrollContainer::calcVisibleSize(). - */ -class LLFolderViewScrollContainer : public LLScrollContainer -{ -public: - /*virtual*/ ~LLFolderViewScrollContainer() {}; - /*virtual*/ const LLRect getScrolledViewRect() const; - -protected: - LLFolderViewScrollContainer(const LLScrollContainer::Params& p); - friend class LLUICtrlFactory; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderView -// -// The LLFolderView represents the root level folder view object. -// It manages the screen region of the folder view. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler -{ -public: - struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params> - { - Mandatory<LLPanel*> parent_panel; - Optional<LLUUID> task_id; - Optional<std::string> title; - Optional<bool> use_label_suffix, - allow_multiselect, - show_empty_message, - use_ellipses, - show_item_link_overlays; - Mandatory<LLFolderViewModelInterface*> view_model; - - Params(); - }; - - friend class LLFolderViewScrollContainer; - - LLFolderView(const Params&); - virtual ~LLFolderView( void ); - - virtual BOOL canFocusChildren() const; - - virtual const LLFolderView* getRoot() const { return this; } - virtual LLFolderView* getRoot() { return this; } - - LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } - const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; } - - void setFilterPermMask(PermissionMask filter_perm_mask); - - typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t; - void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } - void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } - - bool getAllowMultiSelect() { return mAllowMultiSelect; } - - // Close all folders in the view - void closeAllFolders(); - void openTopLevelFolders(); - - virtual BOOL addFolder( LLFolderViewFolder* folder); - - // Find width and height of this object and its children. Also - // makes sure that this view and its children are the right size. - virtual S32 arrange( S32* width, S32* height ); - virtual S32 getItemHeight(); - - void arrangeAll() { mArrangeGeneration++; } - S32 getArrangeGeneration() { return mArrangeGeneration; } - - // applies filters to control visibility of items - virtual void filter( LLFolderViewFilter& filter); - - // Get the last selected item - virtual LLFolderViewItem* getCurSelectedItem( void ); - - // Record the selected item and pass it down the hierarchy. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus = TRUE); - - // This method is used to toggle the selection of an item. Walks - // children, and keeps track of selected objects. - virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - - virtual std::set<LLFolderViewItem*> getSelectionList() const; - S32 getNumSelectedItems() { return mSelectedItems.size(); } - - // Make sure if ancestor is selected, descendants are not - void sanitizeSelection(); - virtual void clearSelection(); - void addToSelectionList(LLFolderViewItem* item); - void removeFromSelectionList(LLFolderViewItem* item); - - BOOL startDrag(LLToolDragAndDrop::ESource source); - void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; } - void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; } - LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; } - - // Deletion functionality - void removeSelectedItems(); - - // Open the selected item - void openSelectedItems( void ); - void propertiesSelectedItems( void ); - - void autoOpenItem(LLFolderViewFolder* item); - void closeAutoOpenedFolders(); - BOOL autoOpenTest(LLFolderViewFolder* item); - BOOL isOpen() const { return TRUE; } // root folder always open - - // Copy & paste - virtual void copy(); - virtual BOOL canCopy() const; - - virtual void cut(); - virtual BOOL canCut() const; - - virtual void paste(); - virtual BOOL canPaste() const; - - virtual void doDelete(); - virtual BOOL canDoDelete() const; - - // Public rename functionality - can only start the process - void startRenamingSelectedItem( void ); - - // LLView functionality - ///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent ); - /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); - /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char); - /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) { setShowSelectionContext(FALSE); } - virtual void draw(); - virtual void deleteAllChildren(); - - void scrollToShowSelection(); - void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect); - void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; } - LLRect getVisibleRect(); - - BOOL search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward); - void setShowSelectionContext(BOOL show) { mShowSelectionContext = show; } - BOOL getShowSelectionContext(); - void setShowSingleSelection(BOOL show); - BOOL getShowSingleSelection() { return mShowSingleSelection; } - F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } - bool getUseEllipses() { return mUseEllipses; } - - void update(); // needs to be called periodically (e.g. once per frame) - - BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; } - BOOL needsAutoRename() { return mNeedsAutoRename; } - void setNeedsAutoRename(BOOL val) { mNeedsAutoRename = val; } - void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; } - void setAutoSelectOverride(BOOL val) { mAutoSelectOverride = val; } - - bool showItemLinkOverlays() { return mShowItemLinkOverlays; } - - void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } - - LLPanel* getParentPanel() { return mParentPanel; } - // DEBUG only - void dumpSelectionInformation(); - - virtual S32 notify(const LLSD& info) ; - - bool useLabelSuffix() { return mUseLabelSuffix; } - void updateMenu(); - -private: - void updateMenuOptions(LLMenuGL* menu); - void updateRenamerPosition(); - -protected: - LLScrollContainer* mScrollContainer; // NULL if this is not a child of a scroll container. - - void commitRename( const LLSD& data ); - void onRenamerLost(); - - void finishRenamingItem( void ); - void closeRenamer( void ); - - bool selectFirstItem(); - bool selectLastItem(); - - BOOL addNoOptions(LLMenuGL* menu) const; - - -protected: - LLHandle<LLView> mPopupMenuHandle; - - typedef std::deque<LLFolderViewItem*> selected_items_t; - selected_items_t mSelectedItems; - BOOL mKeyboardSelection; - BOOL mAllowMultiSelect; - BOOL mShowEmptyMessage; - BOOL mShowFolderHierarchy; - LLUUID mSourceID; - - // Renaming variables and methods - LLFolderViewItem* mRenameItem; // The item currently being renamed - LLLineEditor* mRenamer; - - BOOL mNeedsScroll; - BOOL mPinningSelectedItem; - LLRect mScrollConstraintRect; - BOOL mNeedsAutoSelect; - BOOL mAutoSelectOverride; - BOOL mNeedsAutoRename; - bool mUseLabelSuffix; - bool mShowItemLinkOverlays; - - LLDepthStack<LLFolderViewFolder> mAutoOpenItems; - LLFolderViewFolder* mAutoOpenCandidate; - LLFrameTimer mAutoOpenTimer; - LLFrameTimer mSearchTimer; - std::string mSearchString; - BOOL mShowSelectionContext; - BOOL mShowSingleSelection; - LLFrameTimer mMultiSelectionFadeTimer; - S32 mArrangeGeneration; - - signal_t mSelectSignal; - signal_t mReshapeSignal; - S32 mSignalSelectCallback; - S32 mMinWidth; - BOOL mDragAndDropThisFrame; - - LLPanel* mParentPanel; - - LLFolderViewModelInterface* mViewModel; - - /** - * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. - * NOTE: For now it's used only to cut LLFolderViewItem::mLabel text for Landmarks in Places Panel. - */ - bool mUseEllipses; // See EXT-719 - - /** - * Contains item under mouse pointer while dragging - */ - LLFolderViewItem* mDraggingOverItem; // See EXT-719 - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar; - -public: - static F32 sAutoOpenTime; - LLTextBox* mStatusTextBox; - -}; - - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewFunctor -// -// Simple abstract base class for applying a functor to folders and -// items in a folder view hierarchy. This is suboptimal for algorithms -// that only work folders or only work on items, but I'll worry about -// that later when it's determined to be too slow. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLFolderViewFunctor -{ -public: - virtual ~LLFolderViewFunctor() {} - virtual void doFolder(LLFolderViewFolder* folder) = 0; - virtual void doItem(LLFolderViewItem* item) = 0; -}; - -class LLSelectFirstFilteredItem : public LLFolderViewFunctor -{ -public: - LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} - virtual ~LLSelectFirstFilteredItem() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - BOOL wasItemSelected() { return mItemSelected; } -protected: - BOOL mItemSelected; -}; - -class LLOpenFilteredFolders : public LLFolderViewFunctor -{ -public: - LLOpenFilteredFolders() {} - virtual ~LLOpenFilteredFolders() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); -}; - -class LLSaveFolderState : public LLFolderViewFunctor -{ -public: - LLSaveFolderState() : mApply(FALSE) {} - virtual ~LLSaveFolderState() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item) {} - void setApply(BOOL apply); - void clearOpenFolders() { mOpenFolders.clear(); } -protected: - std::set<LLUUID> mOpenFolders; - BOOL mApply; -}; - -class LLOpenFoldersWithSelection : public LLFolderViewFunctor -{ -public: - LLOpenFoldersWithSelection() {} - virtual ~LLOpenFoldersWithSelection() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); -}; - -// Flags for buildContextMenu() -const U32 SUPPRESS_OPEN_ITEM = 0x1; -const U32 FIRST_SELECTED_ITEM = 0x2; - -#endif // LL_LLFOLDERVIEW_H diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp deleted file mode 100644 index dee3fe7218..0000000000 --- a/indra/newview/llfolderviewitem.cpp +++ /dev/null @@ -1,2060 +0,0 @@ -/** -* @file llfolderviewitem.cpp -* @brief Items and folders that can appear in a hierarchical folder view -* -* $LicenseInfo:firstyear=2001&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ -#include "llviewerprecompiledheaders.h" - -#include "llfolderviewitem.h" - -// viewer includes -#include "llfolderview.h" -#include "llfolderviewmodel.h" -#include "llpanel.h" - -// linden library includes -#include "llclipboard.h" -#include "llfocusmgr.h" // gFocusMgr -#include "lltrans.h" - -///---------------------------------------------------------------------------- -/// Class LLFolderViewItem -///---------------------------------------------------------------------------- - -static LLDefaultChildRegistry::Register<LLFolderViewItem> r("folder_view_item"); - -// statics -std::map<U8, LLFontGL*> LLFolderViewItem::sFonts; // map of styles to fonts - -// only integers can be initialized in header -const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f; -const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f; - -const LLColor4U DEFAULT_WHITE(255, 255, 255); - - -//static -LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) -{ - LLFontGL* rtn = sFonts[style]; - if (!rtn) // grab label font with this style, lazily - { - LLFontDescriptor labelfontdesc("SansSerif", "Small", style); - rtn = LLFontGL::getFont(labelfontdesc); - if (!rtn) - { - rtn = LLFontGL::getFontDefault(); - } - sFonts[style] = rtn; - } - return rtn; -} - -//static -void LLFolderViewItem::initClass() -{ -} - -//static -void LLFolderViewItem::cleanupClass() -{ - sFonts.clear(); -} - - -// NOTE: Optimize this, we call it a *lot* when opening a large inventory -LLFolderViewItem::Params::Params() -: root(), - listener(), - folder_arrow_image("folder_arrow_image"), - folder_indentation("folder_indentation"), - selection_image("selection_image"), - item_height("item_height"), - item_top_pad("item_top_pad"), - creation_date() -{} - -// Default constructor -LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) -: LLView(p), - mLabelWidth(0), - mLabelWidthDirty(false), - mParentFolder( NULL ), - mIsSelected( FALSE ), - mIsCurSelection( FALSE ), - mSelectPending(FALSE), - mLabelStyle( LLFontGL::NORMAL ), - mHasVisibleChildren(FALSE), - mIndentation(0), - mItemHeight(p.item_height), - //TODO RN: create interface for string highlighting - //mStringMatchOffset(std::string::npos), - mControlLabelRotation(0.f), - mDragAndDropTarget(FALSE), - mLabel(p.name), - mRoot(p.root), - mViewModelItem(p.listener), - mIsMouseOverTitle(false) -{ - if (mViewModelItem) - { - mViewModelItem->setFolderViewItem(this); - } -} - -BOOL LLFolderViewItem::postBuild() -{ - refresh(); - return TRUE; -} - -// Destroys the object -LLFolderViewItem::~LLFolderViewItem( void ) -{ - delete mViewModelItem; - mViewModelItem = NULL; -} - -LLFolderView* LLFolderViewItem::getRoot() -{ - return mRoot; -} - -const LLFolderView* LLFolderViewItem::getRoot() const -{ - return mRoot; -} -// Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. -BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) -{ - LLFolderViewItem* root = this; - while( root->mParentFolder ) - { - if( root->mParentFolder == potential_ancestor ) - { - return TRUE; - } - root = root->mParentFolder; - } - return FALSE; -} - -LLFolderViewItem* LLFolderViewItem::getNextOpenNode(BOOL include_children) -{ - if (!mParentFolder) - { - return NULL; - } - - LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children ); - while(itemp && !itemp->getVisible()) - { - LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children ); - if (itemp == next_itemp) - { - // hit last item - return itemp->getVisible() ? itemp : this; - } - itemp = next_itemp; - } - - return itemp; -} - -LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) -{ - if (!mParentFolder) - { - return NULL; - } - - LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children ); - - // Skip over items that are invisible or are hidden from the UI. - while(itemp && !itemp->getVisible()) - { - LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children ); - if (itemp == next_itemp) - { - // hit first item - return itemp->getVisible() ? itemp : this; - } - itemp = next_itemp; - } - - return itemp; -} - -BOOL LLFolderViewItem::passedFilter(S32 filter_generation) -{ - return getViewModelItem()->passedFilter(filter_generation); -} - -void LLFolderViewItem::refresh() -{ - LLFolderViewModelItem& vmi = *getViewModelItem(); - - mLabel = vmi.getDisplayName(); - - setToolTip(mLabel); - mIcon = vmi.getIcon(); - mIconOpen = vmi.getIconOpen(); - mIconOverlay = vmi.getIconOverlay(); - - if (mRoot->useLabelSuffix()) - { - mLabelStyle = vmi.getLabelStyle(); - mLabelSuffix = vmi.getLabelSuffix(); - } - - //TODO RN: make sure this logic still fires - //std::string searchable_label(mLabel); - //searchable_label.append(mLabelSuffix); - //LLStringUtil::toUpper(searchable_label); - - //if (mSearchableLabel.compare(searchable_label)) - //{ - // mSearchableLabel.assign(searchable_label); - // vmi.dirtyFilter(); - // // some part of label has changed, so overall width has potentially changed, and sort order too - // if (mParentFolder) - // { - // mParentFolder->requestSort(); - // mParentFolder->requestArrange(); - // } - //} - - mLabelWidthDirty = true; - vmi.dirtyFilter(); -} - -// Utility function for LLFolderView -void LLFolderViewItem::arrangeAndSet(BOOL set_selection, - BOOL take_keyboard_focus) -{ - LLFolderView* root = getRoot(); - if (getParentFolder()) - { - getParentFolder()->requestArrange(); - } - if(set_selection) - { - getRoot()->setSelection(this, TRUE, take_keyboard_focus); - if(root) - { - root->scrollToShowSelection(); - } - } -} - - -std::set<LLFolderViewItem*> LLFolderViewItem::getSelectionList() const -{ - std::set<LLFolderViewItem*> selection; - return selection; -} - -// addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) -{ - return folder->addItem(this); -} - - -// Finds width and height of this object and its children. Also -// makes sure that this view and its children are the right size. -S32 LLFolderViewItem::arrange( S32* width, S32* height ) -{ - const Params& p = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); - S32 indentation = p.folder_indentation(); - // Only indent deeper items in hierarchy - mIndentation = (getParentFolder()) - ? getParentFolder()->getIndentation() + indentation - : 0; - if (mLabelWidthDirty) - { - mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + TEXT_PAD_RIGHT; - mLabelWidthDirty = false; - } - - *width = llmax(*width, mLabelWidth + mIndentation); - - // determine if we need to use ellipses to avoid horizontal scroll. EXT-719 - bool use_ellipses = getRoot()->getUseEllipses(); - if (use_ellipses) - { - // limit to set rect to avoid horizontal scrollbar - *width = llmin(*width, getRoot()->getRect().getWidth()); - } - *height = getItemHeight(); - return *height; -} - -S32 LLFolderViewItem::getItemHeight() -{ - return mItemHeight; -} - -// *TODO: This can be optimized a lot by simply recording that it is -// selected in the appropriate places, and assuming that set selection -// means 'deselect' for a leaf item. Do this optimization after -// multiple selection is implemented to make sure it all plays nice -// together. -BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus) -{ - if (selection == this && !mIsSelected) - { - selectItem(); - } - else if (mIsSelected) // Deselect everything else. - { - deselectItem(); - } - return mIsSelected; -} - -BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected) -{ - if (selection == this) - { - if (mIsSelected) - { - deselectItem(); - } - else - { - selectItem(); - } - return TRUE; - } - return FALSE; -} - -void LLFolderViewItem::deselectItem(void) -{ - mIsSelected = FALSE; -} - -void LLFolderViewItem::selectItem(void) -{ - if (mIsSelected == FALSE) - { - getViewModelItem()->selectItem(); - mIsSelected = TRUE; - } -} - -BOOL LLFolderViewItem::isMovable() -{ - return getViewModelItem()->isItemMovable(); -} - -BOOL LLFolderViewItem::isRemovable() -{ - return getViewModelItem()->isItemRemovable(); -} - -void LLFolderViewItem::destroyView() -{ - getRoot()->removeFromSelectionList(this); - - if (mParentFolder) - { - // removeView deletes me - mParentFolder->extractItem(this); - } - delete this; -} - -// Call through to the viewed object and return true if it can be -// removed. -//BOOL LLFolderViewItem::removeRecursively(BOOL single_item) -BOOL LLFolderViewItem::remove() -{ - if(!isRemovable()) - { - return FALSE; - } - return getViewModelItem()->removeItem(); -} - -// Build an appropriate context menu for the item. -void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - getViewModelItem()->buildContextMenu(menu, flags); -} - -void LLFolderViewItem::openItem( void ) -{ - getViewModelItem()->openItem(); -} - -void LLFolderViewItem::rename(const std::string& new_name) -{ - if( !new_name.empty() ) - { - getViewModelItem()->renameItem(new_name); - - if(mParentFolder) - { - mParentFolder->requestSort(); - } - } - } - -const std::string& LLFolderViewItem::getName( void ) const -{ - return getViewModelItem()->getName(); -} - -// LLView functionality -BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - if(!mIsSelected) - { - getRoot()->setSelection(this, FALSE); - } - make_ui_sound("UISndClick"); - return TRUE; -} - -BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - if (LLView::childrenHandleMouseDown(x, y, mask)) - { - return TRUE; - } - - // No handler needed for focus lost since this class has no - // state that depends on it. - gFocusMgr.setMouseCapture( this ); - - if (!mIsSelected) - { - if(mask & MASK_CONTROL) - { - getRoot()->changeSelection(this, !mIsSelected); - } - else if (mask & MASK_SHIFT) - { - getParentFolder()->extendSelectionTo(this); - } - else - { - getRoot()->setSelection(this, FALSE); - } - make_ui_sound("UISndClick"); - } - else - { - mSelectPending = TRUE; - } - - if( isMovable() ) - { - S32 screen_x; - S32 screen_y; - localPointToScreen(x, y, &screen_x, &screen_y ); - LLToolDragAndDrop::getInstance()->setDragStart( screen_x, screen_y ); - } - return TRUE; -} - -BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) -{ - mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); - - if( hasMouseCapture() && isMovable() ) - { - S32 screen_x; - S32 screen_y; - localPointToScreen(x, y, &screen_x, &screen_y ); - BOOL can_drag = TRUE; - if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) ) - { - LLFolderView* root = getRoot(); - - if(root->getCurSelectedItem()) - { - LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_WORLD; - - // *TODO: push this into listener and remove - // dependency on llagent - src = getViewModelItem()->getDragSource(); - - can_drag = root->startDrag(src); - if (can_drag) - { - // if (getViewModelItem()) getViewModelItem()->startDrag(); - // RN: when starting drag and drop, clear out last auto-open - root->autoOpenTest(NULL); - root->setShowSelectionContext(TRUE); - - // Release keyboard focus, so that if stuff is dropped into the - // world, pressing the delete key won't blow away the inventory - // item. - gFocusMgr.setKeyboardFocus(NULL); - - return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask ); - } - } - } - - if (can_drag) - { - getWindow()->setCursor(UI_CURSOR_ARROW); - } - else - { - getWindow()->setCursor(UI_CURSOR_NOLOCKED); - } - return TRUE; - } - else - { - if (getRoot()) - { - getRoot()->setShowSelectionContext(FALSE); - } - getWindow()->setCursor(UI_CURSOR_ARROW); - // let parent handle this then... - return FALSE; - } -} - - -BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ - getViewModelItem()->openItem(); - return TRUE; -} - -BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) -{ - if (LLView::childrenHandleMouseUp(x, y, mask)) - { - return TRUE; - } - - // if mouse hasn't moved since mouse down... - if ( pointInView(x, y) && mSelectPending ) - { - //...then select - if(mask & MASK_CONTROL) - { - getRoot()->changeSelection(this, !mIsSelected); - } - else if (mask & MASK_SHIFT) - { - getParentFolder()->extendSelectionTo(this); - } - else - { - getRoot()->setSelection(this, FALSE); - } - } - - mSelectPending = FALSE; - - if( hasMouseCapture() ) - { - if (getRoot()) - { - getRoot()->setShowSelectionContext(FALSE); - } - gFocusMgr.setMouseCapture( NULL ); - } - return TRUE; -} - -void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask) -{ - mIsMouseOverTitle = false; -} - -BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - BOOL handled = FALSE; - BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); - handled = accepted; - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - if(mParentFolder && !handled) - { - // store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event. - mRoot->setDraggingOverItem(this); - handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); - mRoot->setDraggingOverItem(NULL); - } - if (handled) - { - lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewItem" << llendl; - } - - return handled; -} - -void LLFolderViewItem::draw() -{ - static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); - static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); - static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); - static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); - static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); - static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); - static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); - static LLUIColor sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); - static LLUIColor sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); - static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); - static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); - - const Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); - const S32 TOP_PAD = default_params.item_top_pad; - const S32 FOCUS_LEFT = 1; - const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - - getViewModelItem()->update(); - - //--------------------------------------------------------------------------------// - // Draw open folder arrow - // - if (hasVisibleChildren() || getViewModelItem()->hasChildren()) - { - LLUIImage* arrow_image = default_params.folder_arrow_image; - gl_draw_scaled_rotated_image( - mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD - TOP_PAD, - ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, arrow_image->getImage(), sFgColor); - } - - - //--------------------------------------------------------------------------------// - // Draw highlight for selected items - // - const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); - const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled - const S32 focus_top = getRect().getHeight(); - const S32 focus_bottom = getRect().getHeight() - mItemHeight; - const bool folder_open = (getRect().getHeight() > mItemHeight + 4); - if (mIsSelected) // always render "current" item. Only render other selected items if mShowSingleSelection is FALSE - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLColor4 bg_color = sHighlightBgColor; - if (!mIsCurSelection) - { - // do time-based fade of extra objects - F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); - if (getRoot() && getRoot()->getShowSingleSelection()) - { - // fading out - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); - } - else - { - // fading in - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); - } - } - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - bg_color, filled); - if (mIsCurSelection) - { - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sFocusOutlineColor, FALSE); - } - if (folder_open) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, // overlap with bottom edge of above rect - getRect().getWidth() - 2, - 0, - sFocusOutlineColor, FALSE); - if (show_context) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, - getRect().getWidth() - 2, - 0, - sHighlightBgColor, TRUE); - } - } - } - else if (mIsMouseOverTitle) - { - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sMouseOverColor, FALSE); - } - - //--------------------------------------------------------------------------------// - // Draw DragNDrop highlight - // - if (mDragAndDropTarget) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sHighlightBgColor, FALSE); - if (folder_open) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, // overlap with bottom edge of above rect - getRect().getWidth() - 2, - 0, - sHighlightBgColor, FALSE); - } - mDragAndDropTarget = FALSE; - } - - //--------------------------------------------------------------------------------// - // Draw open icon - // - const S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; - if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders - { - mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); - } - else if (mIcon) - { - mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - } - - if (mIconOverlay && getRoot()->showItemLinkOverlays()) - { - mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - } - - //--------------------------------------------------------------------------------// - // Exit if no label to draw - // - if (mLabel.empty()) - { - return; - } - - LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; - //TODO RN: implement this in terms of getColor() - //if (highlight_link) color = sLinkColor; - //if (gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; - - F32 right_x = 0; - F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; - F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); - - //--------------------------------------------------------------------------------// - // Draw the actual label text - // - font->renderUTF8(mLabel, 0, text_left, y, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); - - //--------------------------------------------------------------------------------// - // Draw label suffix - // - if (!mLabelSuffix.empty()) - { - font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x, FALSE ); - } - - //--------------------------------------------------------------------------------// - // Highlight string match - // - //TODO RN: expose interface for highlighting - //if (mStringMatchOffset != std::string::npos) - //{ - // // don't draw backgrounds for zero-length strings - // S32 filter_string_length = getRoot()->getFilterSubString().size(); - // if (filter_string_length > 0) - // { - // std::string combined_string = mLabel + mLabelSuffix; - // S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; - // S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; - // S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); - // S32 top = getRect().getHeight() - TOP_PAD; - // - // LLUIImage* box_image = default_params.selection_image; - // LLRect box_rect(left, top, right, bottom); - // box_image->draw(box_rect, sFilterBGColor); - // F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); - // F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; - // font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, - // sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - // filter_string_length, S32_MAX, &right_x, FALSE ); - // } - //} -} - -const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const - { - return getRoot()->getFolderViewModel(); -} - -LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) - { - return getRoot()->getFolderViewModel(); -} - - -///---------------------------------------------------------------------------- -/// Class LLFolderViewFolder -///---------------------------------------------------------------------------- - -LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): - LLFolderViewItem( p ), - mIsOpen(FALSE), - mExpanderHighlighted(FALSE), - mCurHeight(0.f), - mTargetHeight(0.f), - mAutoOpenCountdown(0.f), - mLastArrangeGeneration( -1 ), - mLastCalculatedWidth(0) -{ -} - -// Destroys the object -LLFolderViewFolder::~LLFolderViewFolder( void ) -{ - // The LLView base class takes care of object destruction. make sure that we - // don't have mouse or keyboard focus - gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() -} - -// addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) -{ - return folder->addFolder(this); -} - -static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); - -// Finds width and height of this object and its children. Also -// makes sure that this view and its children are the right size. -S32 LLFolderViewFolder::arrange( S32* width, S32* height ) -{ - // sort before laying out contents - getRoot()->getFolderViewModel()->sort(this); - - LLFastTimer t2(FTM_ARRANGE); - - // evaluate mHasVisibleChildren - mHasVisibleChildren = false; - if (getViewModelItem()->descendantsPassedFilter()) - { - // We have to verify that there's at least one child that's not filtered out - bool found = false; - // Try the items first - for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - found = itemp->passedFilter(); - if (found) - break; - } - if (!found) - { - // If no item found, try the folders - for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) - { - LLFolderViewFolder* folderp = (*fit); - found = folderp->passedFilter(); - if (found) - break; - } - } - - mHasVisibleChildren = found; - } - - // calculate height as a single item (without any children), and reshapes rectangle to match - LLFolderViewItem::arrange( width, height ); - - // clamp existing animated height so as to never get smaller than a single item - mCurHeight = llmax((F32)*height, mCurHeight); - - // initialize running height value as height of single item in case we have no children - F32 running_height = (F32)*height; - F32 target_height = (F32)*height; - - // are my children visible? - if (needsArrange()) - { - // set last arrange generation first, in case children are animating - // and need to be arranged again - mLastArrangeGeneration = getRoot()->getArrangeGeneration(); - if (isOpen()) - { - // Add sizes of children - S32 parent_item_height = getRect().getHeight(); - - for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) - { - LLFolderViewFolder* folderp = (*fit); - folderp->setVisible(folderp->passedFilter()); // passed filter or has descendants that passed filter - - if (folderp->getVisible()) - { - S32 child_width = *width; - S32 child_height = 0; - S32 child_top = parent_item_height - llround(running_height); - - target_height += folderp->arrange( &child_width, &child_height ); - - running_height += (F32)child_height; - *width = llmax(*width, child_width); - folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() ); - } - } - for(items_t::iterator iit = mItems.begin(); - iit != mItems.end(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - itemp->setVisible(itemp->passedFilter()); - - if (itemp->getVisible()) - { - S32 child_width = *width; - S32 child_height = 0; - S32 child_top = parent_item_height - llround(running_height); - - target_height += itemp->arrange( &child_width, &child_height ); - // don't change width, as this item is as wide as its parent folder by construction - itemp->reshape( itemp->getRect().getWidth(), child_height); - - running_height += (F32)child_height; - *width = llmax(*width, child_width); - itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() ); - } - } - } - - mTargetHeight = target_height; - // cache this width so next time we can just return it - mLastCalculatedWidth = *width; - } - else - { - // just use existing width - *width = mLastCalculatedWidth; - } - - // animate current height towards target height - if (llabs(mCurHeight - mTargetHeight) > 1.f) - { - mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); - - requestArrange(); - - // hide child elements that fall out of current animated height - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - // number of pixels that bottom of folder label is from top of parent folder - if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight() - > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) - { - // hide if beyond current folder height - (*fit)->setVisible(FALSE); - } - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - // number of pixels that bottom of item label is from top of parent folder - if (getRect().getHeight() - (*iit)->getRect().mBottom - > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) - { - (*iit)->setVisible(FALSE); - } - } - } - else - { - mCurHeight = mTargetHeight; - } - - // don't change width as this item is already as wide as its parent folder - reshape(getRect().getWidth(),llround(mCurHeight)); - - // pass current height value back to parent - *height = llround(mCurHeight); - - return llround(mTargetHeight); -} - -BOOL LLFolderViewFolder::needsArrange() -{ - return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); -} - -void LLFolderViewFolder::requestSort() -{ - getViewModelItem()->requestSort(); -} - -//TODO RN: get height resetting working -//void LLFolderViewFolder::setPassedFilter(BOOL passed, BOOL passed_folder, S32 filter_generation) -//{ -// // if this folder is now filtered, but wasn't before -// // (it just passed) -// if (passed && !passedFilter(filter_generation)) -// { -// // reset current height, because last time we drew it -// // it might have had more visible items than now -// mCurHeight = 0.f; -// } -// -// LLFolderViewItem::setPassedFilter(passed, passed_folder, filter_generation); -//} - - -// Passes selection information on to children and record selection -// information if necessary. -BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus) -{ - BOOL rv = FALSE; - if (selection == this) - { - if (!isSelected()) - { - selectItem(); - } - rv = TRUE; - } - else - { - if (isSelected()) - { - deselectItem(); - } - rv = FALSE; - } - BOOL child_selected = FALSE; - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if((*fit)->setSelection(selection, openitem, take_keyboard_focus)) - { - rv = TRUE; - child_selected = TRUE; - } - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if((*iit)->setSelection(selection, openitem, take_keyboard_focus)) - { - rv = TRUE; - child_selected = TRUE; - } - } - if(openitem && child_selected) - { - setOpenArrangeRecursively(TRUE); - } - return rv; -} - -// This method is used to change the selection of an item. -// Recursively traverse all children; if 'selection' is 'this' then change -// the select status if necessary. -// Returns TRUE if the selection state of this folder, or of a child, was changed. -BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selected) -{ - BOOL rv = FALSE; - if(selection == this) - { - if (isSelected() != selected) - { - rv = TRUE; - if (selected) - { - selectItem(); - } - else - { - deselectItem(); - } - } - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if((*fit)->changeSelection(selection, selected)) - { - rv = TRUE; - } - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if((*iit)->changeSelection(selection, selected)) - { - rv = TRUE; - } - } - return rv; -} - -LLFolderViewFolder* LLFolderViewFolder::getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse) -{ - if (!item_a->getParentFolder() || !item_b->getParentFolder()) return NULL; - - std::deque<LLFolderViewFolder*> item_a_ancestors; - - LLFolderViewFolder* parent = item_a->getParentFolder(); - while(parent) - { - item_a_ancestors.push_back(parent); - parent = parent->getParentFolder(); - } - - std::deque<LLFolderViewFolder*> item_b_ancestors; - - parent = item_b->getParentFolder(); - while(parent) - { - item_b_ancestors.push_back(parent); - parent = parent->getParentFolder(); - } - - LLFolderViewFolder* common_ancestor = item_a->getRoot(); - - while(item_a_ancestors.size() > item_b_ancestors.size()) - { - item_a = item_a_ancestors.front(); - item_a_ancestors.pop_front(); - } - - while(item_b_ancestors.size() > item_a_ancestors.size()) - { - item_b = item_b_ancestors.front(); - item_b_ancestors.pop_front(); - } - - while(item_a_ancestors.size()) - { - common_ancestor = item_a_ancestors.front(); - - if (item_a_ancestors.front() == item_b_ancestors.front()) - { - // which came first, sibling a or sibling b? - for (folders_t::iterator it = common_ancestor->mFolders.begin(), end_it = common_ancestor->mFolders.end(); - it != end_it; - ++it) - { - LLFolderViewItem* item = *it; - - if (item == item_a) - { - reverse = false; - return common_ancestor; - } - if (item == item_b) - { - reverse = true; - return common_ancestor; - } - } - - for (items_t::iterator it = common_ancestor->mItems.begin(), end_it = common_ancestor->mItems.end(); - it != end_it; - ++it) - { - LLFolderViewItem* item = *it; - - if (item == item_a) - { - reverse = false; - return common_ancestor; - } - if (item == item_b) - { - reverse = true; - return common_ancestor; - } - } - break; - } - - item_a = item_a_ancestors.front(); - item_a_ancestors.pop_front(); - item_b = item_b_ancestors.front(); - item_b_ancestors.pop_front(); - } - - return NULL; -} - -void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items) -{ - bool selecting = start == NULL; - if (reverse) - { - for (items_t::reverse_iterator it = mItems.rbegin(), end_it = mItems.rend(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - if (selecting) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - for (folders_t::reverse_iterator it = mFolders.rbegin(), end_it = mFolders.rend(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - - if (selecting) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - } - else - { - for (folders_t::iterator it = mFolders.begin(), end_it = mFolders.end(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - - if (selecting) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - for (items_t::iterator it = mItems.begin(), end_it = mItems.end(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - - if (selecting) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - } -} - -void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) -{ - if (getRoot()->getAllowMultiSelect() == FALSE) return; - - LLFolderViewItem* cur_selected_item = getRoot()->getCurSelectedItem(); - if (cur_selected_item == NULL) - { - cur_selected_item = new_selection; - } - - - bool reverse = false; - LLFolderViewFolder* common_ancestor = getCommonAncestor(cur_selected_item, new_selection, reverse); - if (!common_ancestor) return; - - LLFolderViewItem* last_selected_item_from_cur = cur_selected_item; - LLFolderViewFolder* cur_folder = cur_selected_item->getParentFolder(); - - std::vector<LLFolderViewItem*> items_to_select_forward; - - while(cur_folder != common_ancestor) - { - cur_folder->gatherChildRangeExclusive(last_selected_item_from_cur, NULL, reverse, items_to_select_forward); - - last_selected_item_from_cur = cur_folder; - cur_folder = cur_folder->getParentFolder(); - } - - std::vector<LLFolderViewItem*> items_to_select_reverse; - - LLFolderViewItem* last_selected_item_from_new = new_selection; - cur_folder = new_selection->getParentFolder(); - while(cur_folder != common_ancestor) - { - cur_folder->gatherChildRangeExclusive(last_selected_item_from_new, NULL, !reverse, items_to_select_reverse); - - last_selected_item_from_new = cur_folder; - cur_folder = cur_folder->getParentFolder(); - } - - common_ancestor->gatherChildRangeExclusive(last_selected_item_from_cur, last_selected_item_from_new, reverse, items_to_select_forward); - - for (std::vector<LLFolderViewItem*>::reverse_iterator it = items_to_select_reverse.rbegin(), end_it = items_to_select_reverse.rend(); - it != end_it; - ++it) - { - items_to_select_forward.push_back(*it); - } - - LLFolderView* root = getRoot(); - - for (std::vector<LLFolderViewItem*>::iterator it = items_to_select_forward.begin(), end_it = items_to_select_forward.end(); - it != end_it; - ++it) - { - LLFolderViewItem* item = *it; - if (item->isSelected()) - { - root->removeFromSelectionList(item); - } - else - { - item->selectItem(); - } - root->addToSelectionList(item); - } - - if (new_selection->isSelected()) - { - root->removeFromSelectionList(new_selection); - } - else - { - new_selection->selectItem(); - } - root->addToSelectionList(new_selection); -} - - -void LLFolderViewFolder::destroyView() -{ - std::for_each(mItems.begin(), mItems.end(), DeletePointer()); - mItems.clear(); - - while (!mFolders.empty()) - { - LLFolderViewFolder *folderp = mFolders.back(); - folderp->destroyView(); // removes entry from mFolders - } - - LLFolderViewItem::destroyView(); -} - -// extractItem() removes the specified item from the folder, but -// doesn't delete it. -void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) -{ - items_t::iterator it = std::find(mItems.begin(), mItems.end(), item); - if(it == mItems.end()) - { - // This is an evil downcast. However, it's only doing - // pointer comparison to find if (which it should be ) the - // item is in the container, so it's pretty safe. - LLFolderViewFolder* f = static_cast<LLFolderViewFolder*>(item); - folders_t::iterator ft; - ft = std::find(mFolders.begin(), mFolders.end(), f); - if (ft != mFolders.end()) - { - mFolders.erase(ft); - } - } - else - { - mItems.erase(it); - } - //item has been removed, need to update filter - getViewModelItem()->removeChild(item->getViewModelItem()); - getViewModelItem()->dirtyFilter(); - //because an item is going away regardless of filter status, force rearrange - requestArrange(); - removeChild(item); -} - -BOOL LLFolderViewFolder::isMovable() -{ - if( !(getViewModelItem()->isItemMovable()) ) - { - return FALSE; - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if(!(*iit)->isMovable()) - { - return FALSE; - } - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if(!(*fit)->isMovable()) - { - return FALSE; - } - } - return TRUE; -} - - -BOOL LLFolderViewFolder::isRemovable() -{ - if( !(getViewModelItem()->isItemRemovable()) ) - { - return FALSE; - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if(!(*iit)->isRemovable()) - { - return FALSE; - } - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if(!(*fit)->isRemovable()) - { - return FALSE; - } - } - return TRUE; -} - -// this is an internal method used for adding items to folders. -BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) -{ - if (item->getParentFolder()) - { - item->getParentFolder()->extractItem(item); - } - item->setParentFolder(this); - - mItems.push_back(item); - - item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); - item->setVisible(FALSE); - - addChild(item); - - item->getViewModelItem()->dirtyFilter(); - - // Handle sorting - requestArrange(); - requestSort(); - - getViewModelItem()->addChild(item->getViewModelItem()); - - //TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria - //// Traverse parent folders and update creation date and resort, if necessary - //LLFolderViewFolder* parentp = this; - //while (parentp) - //{ - // if (parentp->mSortFunction.isByDate()) - // { - // // parent folder doesn't have a time stamp yet, so get it from us - // parentp->requestSort(); - // } - - // parentp = parentp->getParentFolder(); - //} - - return TRUE; -} - -// this is an internal method used for adding items to folders. -BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) -{ - if (folder->mParentFolder) - { - folder->mParentFolder->extractItem(folder); - } - folder->mParentFolder = this; - mFolders.push_back(folder); - folder->setOrigin(0, 0); - folder->reshape(getRect().getWidth(), 0); - folder->setVisible(FALSE); - addChild( folder ); - folder->getViewModelItem()->dirtyFilter(); - // rearrange all descendants too, as our indentation level might have changed - folder->requestArrange(); - requestSort(); - - getViewModelItem()->addChild(folder->getViewModelItem()); - - return TRUE; -} - -void LLFolderViewFolder::requestArrange() -{ - mLastArrangeGeneration = -1; - // flag all items up to root - if (mParentFolder) - { - mParentFolder->requestArrange(); - } -} - -void LLFolderViewFolder::toggleOpen() -{ - setOpen(!isOpen()); -} - -// Force a folder open or closed -void LLFolderViewFolder::setOpen(BOOL openitem) -{ - setOpenArrangeRecursively(openitem); -} - -void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) -{ - BOOL was_open = isOpen(); - mIsOpen = openitem; - if(!was_open && openitem) - { - getViewModelItem()->openItem(); - } - else if(was_open && !openitem) - { - getViewModelItem()->closeItem(); - } - - if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) - { - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */ - } - } - if (mParentFolder - && (recurse == RECURSE_UP - || recurse == RECURSE_UP_DOWN)) - { - mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP); - } - - if (was_open != isOpen()) - { - requestArrange(); - } -} - -BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, - BOOL drop, - EDragAndDropType c_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - BOOL accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - - // drag and drop to child item, so clear pending auto-opens - getRoot()->autoOpenTest(NULL); - - return TRUE; -} - -void LLFolderViewFolder::openItem( void ) -{ - toggleOpen(); -} - -void LLFolderViewFolder::applyFunctorToChildren(LLFolderViewFunctor& functor) -{ - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - functor.doItem((*fit)); - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - functor.doItem((*iit)); - } -} - -void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) -{ - functor.doFolder(this); - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->applyFunctorRecursively(functor); - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - functor.doItem((*iit)); - } -} - -// LLView functionality -BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - BOOL handled = FALSE; - - if (isOpen()) - { - handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL); - } - - if (!handled) - { - handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - - lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl; - } - - return TRUE; -} - -BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); - - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - - if (!drop && accepted) - { - getRoot()->autoOpenTest(this); - } - - return TRUE; -} - - -BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - BOOL handled = FALSE; - - if( isOpen() ) - { - handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; - } - if (!handled) - { - handled = LLFolderViewItem::handleRightMouseDown( x, y, mask ); - } - return handled; -} - - -BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) -{ - mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); - - BOOL handled = LLView::handleHover(x, y, mask); - - if (!handled) - { - // this doesn't do child processing - handled = LLFolderViewItem::handleHover(x, y, mask); - } - - return handled; -} - -BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - BOOL handled = FALSE; - if( isOpen() ) - { - handled = childrenHandleMouseDown(x,y,mask) != NULL; - } - if( !handled ) - { - if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD) - { - toggleOpen(); - handled = TRUE; - } - else - { - // do normal selection logic - handled = LLFolderViewItem::handleMouseDown(x, y, mask); - } - } - - return handled; -} - -BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ - BOOL handled = FALSE; - if( isOpen() ) - { - handled = childrenHandleDoubleClick( x, y, mask ) != NULL; - } - if( !handled ) - { - if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD) - { - // don't select when user double-clicks plus sign - // so as not to contradict single-click behavior - toggleOpen(); - } - else - { - getRoot()->setSelection(this, FALSE); - toggleOpen(); - } - handled = TRUE; - } - return handled; -} - -void LLFolderViewFolder::draw() -{ - if (mAutoOpenCountdown != 0.f) - { - mControlLabelRotation = mAutoOpenCountdown * -90.f; - } - else if (isOpen()) - { - mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); - } - else - { - mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); - } - - LLFolderViewItem::draw(); - - // draw children if root folder, or any other folder that is open or animating to closed state - if( getRoot() == this || (isOpen() || mCurHeight != mTargetHeight )) - { - LLView::draw(); - } - - mExpanderHighlighted = FALSE; -} - -// this does prefix traversal, as folders are listed above their contents -LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children ) -{ - BOOL found_item = FALSE; - - LLFolderViewItem* result = NULL; - // when not starting from a given item, start at beginning - if(item == NULL) - { - found_item = TRUE; - } - - // find current item among children - folders_t::iterator fit = mFolders.begin(); - folders_t::iterator fend = mFolders.end(); - - items_t::iterator iit = mItems.begin(); - items_t::iterator iend = mItems.end(); - - // if not trivially starting at the beginning, we have to find the current item - if (!found_item) - { - // first, look among folders, since they are always above items - for(; fit != fend; ++fit) - { - if(item == (*fit)) - { - found_item = TRUE; - // if we are on downwards traversal - if (include_children && (*fit)->isOpen()) - { - // look for first descendant - return (*fit)->getNextFromChild(NULL, TRUE); - } - // otherwise advance to next folder - ++fit; - include_children = TRUE; - break; - } - } - - // didn't find in folders? Check items... - if (!found_item) - { - for(; iit != iend; ++iit) - { - if(item == (*iit)) - { - found_item = TRUE; - // point to next item - ++iit; - break; - } - } - } - } - - if (!found_item) - { - // you should never call this method with an item that isn't a child - // so we should always find something - llassert(FALSE); - return NULL; - } - - // at this point, either iit or fit point to a candidate "next" item - // if both are out of range, we need to punt up to our parent - - // now, starting from found folder, continue through folders - // searching for next visible folder - while(fit != fend && !(*fit)->getVisible()) - { - // turn on downwards traversal for next folder - ++fit; - } - - if (fit != fend) - { - result = (*fit); - } - else - { - // otherwise, scan for next visible item - while(iit != iend && !(*iit)->getVisible()) - { - ++iit; - } - - // check to see if we have a valid item - if (iit != iend) - { - result = (*iit); - } - } - - if( !result && mParentFolder ) - { - // If there are no siblings or children to go to, recurse up one level in the tree - // and skip children for this folder, as we've already discounted them - result = mParentFolder->getNextFromChild(this, FALSE); - } - - return result; -} - -// this does postfix traversal, as folders are listed above their contents -LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, BOOL include_children ) -{ - BOOL found_item = FALSE; - - LLFolderViewItem* result = NULL; - // when not starting from a given item, start at end - if(item == NULL) - { - found_item = TRUE; - } - - // find current item among children - folders_t::reverse_iterator fit = mFolders.rbegin(); - folders_t::reverse_iterator fend = mFolders.rend(); - - items_t::reverse_iterator iit = mItems.rbegin(); - items_t::reverse_iterator iend = mItems.rend(); - - // if not trivially starting at the end, we have to find the current item - if (!found_item) - { - // first, look among items, since they are always below the folders - for(; iit != iend; ++iit) - { - if(item == (*iit)) - { - found_item = TRUE; - // point to next item - ++iit; - break; - } - } - - // didn't find in items? Check folders... - if (!found_item) - { - for(; fit != fend; ++fit) - { - if(item == (*fit)) - { - found_item = TRUE; - // point to next folder - ++fit; - break; - } - } - } - } - - if (!found_item) - { - // you should never call this method with an item that isn't a child - // so we should always find something - llassert(FALSE); - return NULL; - } - - // at this point, either iit or fit point to a candidate "next" item - // if both are out of range, we need to punt up to our parent - - // now, starting from found item, continue through items - // searching for next visible item - while(iit != iend && !(*iit)->getVisible()) - { - ++iit; - } - - if (iit != iend) - { - // we found an appropriate item - result = (*iit); - } - else - { - // otherwise, scan for next visible folder - while(fit != fend && !(*fit)->getVisible()) - { - ++fit; - } - - // check to see if we have a valid folder - if (fit != fend) - { - // try selecting child element of this folder - if ((*fit)->isOpen()) - { - result = (*fit)->getPreviousFromChild(NULL); - } - else - { - result = (*fit); - } - } - } - - if( !result ) - { - // If there are no siblings or children to go to, recurse up one level in the tree - // which gets back to this folder, which will only be visited if it is a valid, visible item - result = this; - } - - return result; -} - diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h deleted file mode 100644 index 92923e82da..0000000000 --- a/indra/newview/llfolderviewitem.h +++ /dev/null @@ -1,418 +0,0 @@ -/** -* @file llfolderviewitem.h -* @brief Items and folders that can appear in a hierarchical folder view -* -* $LicenseInfo:firstyear=2001&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ -#ifndef LLFOLDERVIEWITEM_H -#define LLFOLDERVIEWITEM_H - -#include "llview.h" -#include "lluiimage.h" - -class LLFolderView; -class LLFolderViewModelItem; -class LLFolderViewFolder; -class LLFolderViewFunctor; -class LLFolderViewFilter; -class LLFolderViewModelInterface; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewItem -// -// An instance of this class represents a single item in a folder view -// such as an inventory item or a file. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderViewItem : public LLView -{ -public: - static void initClass(); - static void cleanupClass(); - - struct Params : public LLInitParam::Block<Params, LLView::Params> - { - Optional<LLUIImage*> folder_arrow_image, - selection_image; - Optional<LLFolderView*> root; - Mandatory<LLFolderViewModelItem*> listener; - - Optional<S32> folder_indentation, // pixels - item_height, - item_top_pad; - - Optional<time_t> creation_date; - - Params(); - }; - - // layout constants - static const S32 LEFT_PAD = 5; - // LEFT_INDENTATION is set via folder_indentation above - static const S32 ICON_PAD = 2; - static const S32 ICON_WIDTH = 16; - static const S32 TEXT_PAD = 1; - static const S32 TEXT_PAD_RIGHT = 4; - static const S32 ARROW_SIZE = 12; - static const S32 MAX_FOLDER_ITEM_OVERLAP = 2; - // animation parameters - static const F32 FOLDER_CLOSE_TIME_CONSTANT; - static const F32 FOLDER_OPEN_TIME_CONSTANT; - -private: - BOOL mIsSelected; - -protected: - friend class LLUICtrlFactory; - friend class LLFolderViewModelItem; - - LLFolderViewItem(const Params& p); - - std::string mLabel; - S32 mLabelWidth; - bool mLabelWidthDirty; - LLFolderViewFolder* mParentFolder; - LLFolderViewModelItem* mViewModelItem; - BOOL mIsCurSelection; - BOOL mSelectPending; - LLFontGL::StyleFlags mLabelStyle; - std::string mLabelSuffix; - LLUIImagePtr mIcon; - LLUIImagePtr mIconOpen; - LLUIImagePtr mIconOverlay; - BOOL mHasVisibleChildren; - S32 mIndentation; - S32 mItemHeight; - - //TODO RN: create interface for string highlighting - //std::string::size_type mStringMatchOffset; - F32 mControlLabelRotation; - LLFolderView* mRoot; - BOOL mDragAndDropTarget; - bool mIsMouseOverTitle; - - // this is an internal method used for adding items to folders. A - // no-op at this level, but reimplemented in derived classes. - virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } - virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; } - - static LLFontGL* getLabelFontForStyle(U8 style); - -public: - BOOL postBuild(); - - virtual void openItem( void ); - - void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus); - - virtual ~LLFolderViewItem( void ); - - // addToFolder() returns TRUE if it succeeds. FALSE otherwise - virtual BOOL addToFolder(LLFolderViewFolder* folder); - - // Finds width and height of this object and it's children. Also - // makes sure that this view and it's children are the right size. - virtual S32 arrange( S32* width, S32* height ); - virtual S32 getItemHeight(); - - // If 'selection' is 'this' then note that otherwise ignore. - // Returns TRUE if this item ends up being selected. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); - - // This method is used to set the selection state of an item. - // If 'selection' is 'this' then note selection. - // Returns TRUE if the selection state of this item was changed. - virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - - // this method is used to deselect this element - void deselectItem(); - - // this method is used to select this element - virtual void selectItem(); - - // gets multiple-element selection - virtual std::set<LLFolderViewItem*> getSelectionList() const; - - // Returns true is this object and all of its children can be removed (deleted by user) - virtual BOOL isRemovable(); - - // Returns true is this object and all of its children can be moved - virtual BOOL isMovable(); - - // destroys this item recursively - virtual void destroyView(); - - BOOL isSelected() const { return mIsSelected; } - - void setUnselected() { mIsSelected = FALSE; } - - void setIsCurSelection(BOOL select) { mIsCurSelection = select; } - - BOOL getIsCurSelection() { return mIsCurSelection; } - - BOOL hasVisibleChildren() { return mHasVisibleChildren; } - - // Call through to the viewed object and return true if it can be - // removed. Returns true if it's removed. - //virtual BOOL removeRecursively(BOOL single_item); - BOOL remove(); - - // Build an appropriate context menu for the item. Flags unused. - void buildContextMenu(class LLMenuGL& menu, U32 flags); - - // This method returns the actual name of the thing being - // viewed. This method will ask the viewed object itself. - const std::string& getName( void ) const; - - // This method returns the label displayed on the view. This - // method was primarily added to allow sorting on the folder - // contents possible before the entire view has been constructed. - const std::string& getLabel() const { return mLabel; } - - - LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } - const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } - - void setParentFolder(LLFolderViewFolder* parent) { mParentFolder = parent; } - - LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); - LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); - - const LLFolderViewModelItem* getViewModelItem( void ) const { return mViewModelItem; } - LLFolderViewModelItem* getViewModelItem( void ) { return mViewModelItem; } - - const LLFolderViewModelInterface* getFolderViewModel( void ) const; - LLFolderViewModelInterface* getFolderViewModel( void ); - - // just rename the object. - void rename(const std::string& new_name); - - - // Show children (unfortunate that this is called "open") - virtual void setOpen(BOOL open = TRUE) {}; - virtual BOOL isOpen() const { return FALSE; } - - virtual LLFolderView* getRoot(); - virtual const LLFolderView* getRoot() const; - BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); - S32 getIndentation() { return mIndentation; } - - virtual BOOL passedFilter(S32 filter_generation = -1); - - // refresh information from the object being viewed. - virtual void refresh(); - - // LLView functionality - virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleHover( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); - virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - - virtual void onMouseLeave(S32 x, S32 y, MASK mask); - - virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return NULL; } - - // virtual void handleDropped(); - virtual void draw(); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - -private: - static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewFolder -// -// An instance of an LLFolderViewFolder represents a collection of -// more folders and items. This is used to build the hierarchy of -// items found in the folder view. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderViewFolder : public LLFolderViewItem -{ -protected: - LLFolderViewFolder( const LLFolderViewItem::Params& ); - friend class LLUICtrlFactory; - -public: - - typedef std::list<LLFolderViewItem*> items_t; - typedef std::list<LLFolderViewFolder*> folders_t; - -protected: - items_t mItems; - folders_t mFolders; - - BOOL mIsOpen; - BOOL mExpanderHighlighted; - F32 mCurHeight; - F32 mTargetHeight; - F32 mAutoOpenCountdown; - S32 mLastArrangeGeneration; - S32 mLastCalculatedWidth; - S32 mMostFilteredDescendantGeneration; - bool mNeedsSort; - -public: - typedef enum e_recurse_type - { - RECURSE_NO, - RECURSE_UP, - RECURSE_DOWN, - RECURSE_UP_DOWN - } ERecurseType; - - - virtual ~LLFolderViewFolder( void ); - - LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); - LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); - - // addToFolder() returns TRUE if it succeeds. FALSE otherwise - virtual BOOL addToFolder(LLFolderViewFolder* folder); - - // Finds width and height of this object and it's children. Also - // makes sure that this view and it's children are the right size. - virtual S32 arrange( S32* width, S32* height ); - - BOOL needsArrange(); - - bool descendantsPassedFilter(S32 filter_generation = -1); - - // Passes selection information on to children and record - // selection information if necessary. - // Returns TRUE if this object (or a child) ends up being selected. - // If 'openitem' is TRUE then folders are opened up along the way to the selection. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus = TRUE); - - // This method is used to change the selection of an item. - // Recursively traverse all children; if 'selection' is 'this' then change - // the select status if necessary. - // Returns TRUE if the selection state of this folder, or of a child, was changed. - virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - - // this method is used to group select items - void extendSelectionTo(LLFolderViewItem* selection); - - // Returns true is this object and all of its children can be removed. - virtual BOOL isRemovable(); - - // Returns true is this object and all of its children can be moved - virtual BOOL isMovable(); - - // destroys this folder, and all children - virtual void destroyView(); - - // If this folder can be removed, remove all children that can be - // removed, return TRUE if this is empty after the operation and - // it's viewed folder object can be removed. - //virtual BOOL removeRecursively(BOOL single_item); - //virtual BOOL remove(); - - // extractItem() removes the specified item from the folder, but - // doesn't delete it. - virtual void extractItem( LLFolderViewItem* item ); - - // This function is called by a child that needs to be resorted. - void resort(LLFolderViewItem* item); - - void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; } - - // folders can be opened. This will usually be called by internal - // methods. - virtual void toggleOpen(); - - // Force a folder open or closed - virtual void setOpen(BOOL openitem = TRUE); - - // Called when a child is refreshed. - virtual void requestArrange(); - - virtual void requestSort(); - - // internal method which doesn't update the entire view. This - // method was written because the list iterators destroy the state - // of other iterations, thus, we can't arrange while iterating - // through the children (such as when setting which is selected. - virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO); - - // Get the current state of the folder. - virtual BOOL isOpen() const { return mIsOpen; } - - // special case if an object is dropped on the child. - BOOL handleDragAndDropFromChild(MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - - void applyFunctorRecursively(LLFolderViewFunctor& functor); - - // Just apply this functor to the folder's immediate children. - void applyFunctorToChildren(LLFolderViewFunctor& functor); - - virtual void openItem( void ); - virtual BOOL addItem(LLFolderViewItem* item); - virtual BOOL addFolder( LLFolderViewFolder* folder); - - // LLView functionality - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - BOOL handleDragAndDropToThisFolder(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - virtual void draw(); - - folders_t::iterator getFoldersBegin() { return mFolders.begin(); } - folders_t::iterator getFoldersEnd() { return mFolders.end(); } - folders_t::size_type getFoldersCount() const { return mFolders.size(); } - - items_t::const_iterator getItemsBegin() const { return mItems.begin(); } - items_t::const_iterator getItemsEnd() const { return mItems.end(); } - items_t::size_type getItemsCount() const { return mItems.size(); } - - LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); - void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items); - -public: - //WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead - template<typename SORT_FUNC> void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); } - template<typename SORT_FUNC> void sortItems(const SORT_FUNC& func) { mItems.sort(func); } -}; - - -#endif // LLFOLDERVIEWITEM_H diff --git a/indra/newview/llfolderviewmodel.cpp b/indra/newview/llfolderviewmodel.cpp deleted file mode 100644 index ca6225aca7..0000000000 --- a/indra/newview/llfolderviewmodel.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file llfolderviewmodel.cpp - * @brief Implementation of the view model collection of classes. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfolderviewmodel.h" -#include "lltrans.h" - -bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) -{ - return item->getSortVersion() < mTargetSortVersion; -} - -std::string LLFolderViewModelCommon::getStatusText() -{ - if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter()->getCurrentGeneration()) - { - return LLTrans::getString("Searching"); - } - else - { - return getFilter()->getEmptyLookupMessage(); - } -} - -void LLFolderViewModelCommon::filter() -{ - getFilter()->setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); - mFolderView->getViewModelItem()->filter(*getFilter()); -} diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h deleted file mode 100644 index 079409c2a4..0000000000 --- a/indra/newview/llfolderviewmodel.h +++ /dev/null @@ -1,357 +0,0 @@ -/** - * @file llfolderviewmodel.h - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ -#ifndef LLFOLDERVIEWMODEL_H -#define LLFOLDERVIEWMODEL_H - -#include "llfontgl.h" // just for StyleFlags enum -#include "llfolderview.h" - -// These are grouping of inventory types. -// Order matters when sorting system folders to the top. -enum EInventorySortGroup -{ - SG_SYSTEM_FOLDER, - SG_TRASH_FOLDER, - SG_NORMAL_FOLDER, - SG_ITEM -}; - -class LLFontGL; -class LLInventoryModel; -class LLMenuGL; -class LLUIImage; -class LLUUID; -class LLFolderViewItem; -class LLFolderViewFolder; - -class LLFolderViewFilter -{ -public: - enum EFilterModified - { - FILTER_NONE, // nothing to do, already filtered - FILTER_RESTART, // restart filtering from scratch - FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter - FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one - }; - -public: - - LLFolderViewFilter() {} - virtual ~LLFolderViewFilter() {} - - // +-------------------------------------------------------------------+ - // + Execution And Results - // +-------------------------------------------------------------------+ - virtual bool check(const LLFolderViewModelItem* item) = 0; - virtual bool check(const LLInventoryItem* item) = 0; - virtual bool checkFolder(const LLFolderViewModelItem* folder) const = 0; - virtual bool checkFolder(const LLUUID& folder_id) const = 0; - - virtual void setEmptyLookupMessage(const std::string& message) = 0; - virtual std::string getEmptyLookupMessage() const = 0; - - virtual bool showAllResults() const = 0; - - // +-------------------------------------------------------------------+ - // + Status - // +-------------------------------------------------------------------+ - virtual bool isActive() const = 0; - virtual bool isModified() const = 0; - virtual void clearModified() = 0; - virtual const std::string& getName() const = 0; - virtual const std::string& getFilterText() = 0; - //RN: this is public to allow system to externally force a global refilter - virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0; - - // +-------------------------------------------------------------------+ - // + Count - // +-------------------------------------------------------------------+ - virtual void setFilterCount(S32 count) = 0; - virtual S32 getFilterCount() const = 0; - virtual void decrementFilterCount() = 0; - - // +-------------------------------------------------------------------+ - // + Default - // +-------------------------------------------------------------------+ - virtual bool isDefault() const = 0; - virtual bool isNotDefault() const = 0; - virtual void markDefault() = 0; - virtual void resetDefault() = 0; - - // +-------------------------------------------------------------------+ - // + Generation - // +-------------------------------------------------------------------+ - virtual S32 getCurrentGeneration() const = 0; - virtual S32 getFirstSuccessGeneration() const = 0; - virtual S32 getFirstRequiredGeneration() const = 0; -}; - -class LLFolderViewModelInterface -{ -public: - virtual void requestSortAll() = 0; - - virtual void sort(class LLFolderViewFolder*) = 0; - virtual void filter() = 0; - - virtual bool contentsReady() = 0; - virtual void setFolderView(LLFolderView* folder_view) = 0; - virtual LLFolderViewFilter* getFilter() = 0; - virtual const LLFolderViewFilter* getFilter() const = 0; - virtual std::string getStatusText() = 0; -}; - -class LLFolderViewModelCommon : public LLFolderViewModelInterface -{ -public: - LLFolderViewModelCommon() - : mTargetSortVersion(0), - mFolderView(NULL) - {} - - virtual void requestSortAll() - { - // sort everything - mTargetSortVersion++; - } - virtual std::string getStatusText(); - virtual void filter(); - - void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} - -protected: - bool needsSort(class LLFolderViewModelItem* item); - - S32 mTargetSortVersion; - LLFolderView* mFolderView; - -}; - -template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE> -class LLFolderViewModel : public LLFolderViewModelCommon -{ -public: - LLFolderViewModel(){} - virtual ~LLFolderViewModel() {} - - typedef SORT_TYPE SortType; - typedef ITEM_TYPE ItemType; - typedef FOLDER_TYPE FolderType; - typedef FILTER_TYPE FilterType; - - virtual SortType& getSorter() { return mSorter; } - virtual const SortType& getSorter() const { return mSorter; } - virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } - - virtual FilterType* getFilter() { return &mFilter; } - virtual const FilterType* getFilter() const { return &mFilter; } - virtual void setFilter(const FilterType& filter) { mFilter = filter; } - - // TODO RN: remove this and put all filtering logic in view model - // add getStatusText and isFiltering() - virtual bool contentsReady() { return true; } - - - struct ViewModelCompare - { - ViewModelCompare(const SortType& sorter) - : mSorter(sorter) - {} - - bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const - { - return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); - } - - bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const - { - return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); - } - - const SortType& mSorter; - }; - - void sort(LLFolderViewFolder* folder) - { - if (needsSort(folder->getViewModelItem())) - { - folder->sortFolders(ViewModelCompare(getSorter())); - folder->sortItems(ViewModelCompare(getSorter())); - folder->getViewModelItem()->setSortVersion(mTargetSortVersion); - folder->requestArrange(); - } - } - -protected: - SortType mSorter; - FilterType mFilter; -}; - -// This is am abstract base class that users of the folderview classes -// would use to bridge the folder view with the underlying data -class LLFolderViewModelItem -{ -public: - virtual ~LLFolderViewModelItem( void ) {}; - - virtual void update() {} //called when drawing - virtual const std::string& getName() const = 0; - virtual const std::string& getDisplayName() const = 0; - virtual const std::string& getSearchableName() const = 0; - - virtual LLPointer<LLUIImage> getIcon() const = 0; - virtual LLPointer<LLUIImage> getIconOpen() const { return getIcon(); } - virtual LLPointer<LLUIImage> getIconOverlay() const { return NULL; } - - virtual LLFontGL::StyleFlags getLabelStyle() const = 0; - virtual std::string getLabelSuffix() const = 0; - - virtual void openItem( void ) = 0; - virtual void closeItem( void ) = 0; - virtual void selectItem(void) = 0; - - virtual BOOL isItemRenameable() const = 0; - virtual BOOL renameItem(const std::string& new_name) = 0; - - virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder - virtual void move( LLFolderViewModelItem* parent_listener ) = 0; - - virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed - virtual BOOL removeItem() = 0; - virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0; - - virtual BOOL isItemCopyable() const = 0; - virtual BOOL copyToClipboard() const = 0; - virtual BOOL cutToClipboard() const = 0; - - virtual BOOL isClipboardPasteable() const = 0; - virtual void pasteFromClipboard() = 0; - virtual void pasteLinkFromClipboard() = 0; - - virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; - - virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? - - virtual bool filter( LLFolderViewFilter& filter) = 0; - virtual bool passedFilter(S32 filter_generation = -1) = 0; - virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; - virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) = 0; - virtual void dirtyFilter() = 0; - - virtual S32 getLastFilterGeneration() const = 0; - - // This method should be called when a drag begins. returns TRUE - // if the drag can begin, otherwise FALSE. - virtual LLToolDragAndDrop::ESource getDragSource() const = 0; - virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; - - virtual bool hasChildren() const = 0; - virtual void addChild(LLFolderViewModelItem* child) = 0; - virtual void removeChild(LLFolderViewModelItem* child) = 0; - - // This method will be called to determine if a drop can be - // performed, and will set drop to TRUE if a drop is - // requested. Returns TRUE if a drop is possible/happened, - // otherwise FALSE. - virtual BOOL dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - std::string& tooltip_msg) = 0; - - virtual void requestSort() = 0; - virtual S32 getSortVersion() = 0; - virtual void setSortVersion(S32 version) = 0; - virtual void setParent(LLFolderViewModelItem* parent) = 0; - -protected: - - friend class LLFolderViewItem; - virtual void setFolderViewItem(LLFolderViewItem* folder_view_item) = 0; - -}; - -class LLFolderViewModelItemCommon : public LLFolderViewModelItem -{ -public: - LLFolderViewModelItemCommon() - : mSortVersion(-1), - mPassedFilter(true), - mPassedFolderFilter(true), - mFolderViewItem(NULL), - mLastFilterGeneration(-1), - mMostFilteredDescendantGeneration(-1), - mParent(NULL) - { - std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); - } - - void requestSort() { mSortVersion = -1; } - S32 getSortVersion() { return mSortVersion; } - void setSortVersion(S32 version) { mSortVersion = version;} - - S32 getLastFilterGeneration() const { return mLastFilterGeneration; } - void dirtyFilter() - { - mLastFilterGeneration = -1; - - // bubble up dirty flag all the way to root - if (mParent) - { - mParent->dirtyFilter(); - } - } - virtual void addChild(LLFolderViewModelItem* child) - { - mChildren.push_back(child); - child->setParent(this); - } - virtual void removeChild(LLFolderViewModelItem* child) - { - mChildren.remove(child); - child->setParent(NULL); - } - -protected: - virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } - - S32 mSortVersion; - bool mPassedFilter; - bool mPassedFolderFilter; - - S32 mLastFilterGeneration; - S32 mMostFilteredDescendantGeneration; - - - typedef std::list<LLFolderViewModelItem*> child_list_t; - child_list_t mChildren; - LLFolderViewModelItem* mParent; - - void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} - LLFolderViewItem* mFolderViewItem; -}; - - -#endif // LLFOLDERVIEWMODEL_H diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 99831c61bf..d23b4af8cb 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -28,12 +28,38 @@ #include "llfolderviewmodelinventory.h" #include "llinventorymodelbackgroundfetch.h" #include "llinventorypanel.h" +#include "lltooldraganddrop.h" // // class LLFolderViewModelInventory // static LLFastTimer::DeclareTimer FTM_INVENTORY_SORT("Sort"); +bool LLFolderViewModelInventory::startDrag(std::vector<LLFolderViewModelItem*>& items) +{ + std::vector<EDragAndDropType> types; + uuid_vec_t cargo_ids; + std::vector<LLFolderViewModelItem*>::iterator item_it; + bool can_drag = true; + if (!items.empty()) + { + for (item_it = items.begin(); item_it != items.end(); ++item_it) + { + EDragAndDropType type = DAD_NONE; + LLUUID id = LLUUID::null; + can_drag = can_drag && static_cast<LLFolderViewModelItemInventory*>(*item_it)->startDrag(&type, &id); + + types.push_back(type); + cargo_ids.push_back(id); + } + + LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, + static_cast<LLFolderViewModelItemInventory*>(items.front())->getDragSource(), mTaskID); + } + return can_drag; +} + + void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) { LLFastTimer _(FTM_INVENTORY_SORT); diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index a8fe3f57ea..12a977b28b 100644 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -29,6 +29,9 @@ #define LL_LLFOLDERVIEWMODELINVENTORY_H #include "llinventoryfilter.h" +#include "llinventory.h" +#include "llwearabletype.h" +#include "lltooldraganddrop.h" class LLFolderViewModelItemInventory : public LLFolderViewModelItemCommon @@ -62,6 +65,10 @@ public: virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); virtual bool filter( LLFolderViewFilter& filter); virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); + + virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; + virtual LLToolDragAndDrop::ESource getDragSource() const = 0; + protected: class LLFolderViewModelInventory* mRootViewModel; }; @@ -97,11 +104,13 @@ class LLFolderViewModelInventory public: typedef LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> base_t; - virtual ~LLFolderViewModelInventory() {} + void setTaskID(const LLUUID& id) {mTaskID = id;} void sort(LLFolderViewFolder* folder); - bool contentsReady(); + bool startDrag(std::vector<LLFolderViewModelItem*>& items); +private: + LLUUID mTaskID; }; #endif // LL_LLFOLDERVIEWMODELINVENTORY_H diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 9615f3f44d..f68cf07d8c 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -65,8 +65,6 @@ public: virtual const std::string& getSearchableName() const { return mName; } virtual const LLUUID& getUUID() const { return mUUID; } virtual time_t getCreationDate() const { return 0; } - virtual PermissionMask getPermissionMask() const { return PERM_ALL; } - virtual LLFolderType::EType getPreferredType() const { return LLFolderType::FT_NONE; } virtual LLPointer<LLUIImage> getIcon() const { return NULL; } virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } @@ -88,8 +86,6 @@ public: virtual void buildContextMenu(LLMenuGL& menu, U32 flags) { } virtual BOOL isUpToDate() const { return TRUE; } virtual bool hasChildren() const { return FALSE; } - virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; } - virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } virtual bool potentiallyVisible() { return true; } virtual bool filter( LLFolderViewFilter& filter) { return true; } @@ -107,11 +103,6 @@ public: void setVisibleIfDetached(BOOL visible); - // This method should be called when a drag begins. - // Returns TRUE if the drag can begin, FALSE otherwise. - virtual LLToolDragAndDrop::ESource getDragSource() const { return LLToolDragAndDrop::SOURCE_PEOPLE; } - virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const { return FALSE; } - // This method will be called to determine if a drop can be // performed, and will set drop to TRUE if a drop is // requested. diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index e235d9cf5f..b4a91ca0f7 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -35,6 +35,7 @@ #include "llinventorypanel.h" #include "llviewercontrol.h" #include "llwearable.h" +#include "lltooldraganddrop.h" class LLInventoryFilter; class LLInventoryPanel; @@ -119,7 +120,7 @@ public: void getClipboardEntries(bool show_asset_id, menuentry_vec_t &items, menuentry_vec_t &disabled_items, U32 flags); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); - virtual LLToolDragAndDrop::ESource getDragSource() const; + virtual LLToolDragAndDrop::ESource getDragSource() const; virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index fed9893158..0aa67cddca 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -571,7 +571,24 @@ void LLInventoryPanel::onIdle(void *userdata) void LLInventoryPanel::idle(void* user_data) { LLInventoryPanel* panel = (LLInventoryPanel*)user_data; - panel->mFolderRoot->doIdle(); + panel->mFolderRoot->update(); + // while dragging, update selection rendering to reflect single/multi drag status + if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) + { + EAcceptance last_accept = LLToolDragAndDrop::getInstance()->getLastAccept(); + if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE) + { + panel->mFolderRoot->setShowSingleSelection(TRUE); + } + else + { + panel->mFolderRoot->setShowSingleSelection(FALSE); + } + } + else + { + panel->mFolderRoot->setShowSingleSelection(FALSE); + } } diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 002c0c1113..ca20051a51 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1557,7 +1557,6 @@ void LLPanelObjectInventory::reset() LLFolderView::Params p; p.name = "task inventory"; p.title = "task inventory"; - p.task_id = getTaskUUID(); p.parent_panel = this; p.tool_tip= LLTrans::getString("PanelContentsTooltip"); p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL); @@ -1823,6 +1822,7 @@ void LLPanelObjectInventory::refresh() removeVOInventoryListener(); clearContents(); } + mInventoryViewModel.setTaskID(mTaskUUID); //llinfos << "LLPanelObjectInventory::refresh() " << mTaskUUID << llendl; } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 4a9e106687..cb59f704a5 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -58,6 +58,7 @@ #include "lltoolmgr.h" #include "lltoolpipette.h" #include "llfiltereditor.h" +#include "llwindow.h" #include "lltool.h" #include "llviewerwindow.h" -- cgit v1.2.3 From d3edb1c466f42e2c46c77e43b26d700c6298b8d6 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 4 Jul 2012 00:30:00 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose partial fix for crash on startup --- indra/llui/llfolderview.cpp | 4 ++-- indra/llui/llfolderviewitem.h | 2 +- indra/newview/llimfloatercontainer.cpp | 17 ++++++++++++++--- indra/newview/llimfloatercontainer.h | 1 + 4 files changed, 18 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 0d3bc44ae4..990b79a30b 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1798,8 +1798,8 @@ void LLFolderView::update() BOOL filter_finished = getViewModelItem()->passedFilter() && mViewModel->contentsReady(); if (filter_finished - || gFocusMgr.childHasKeyboardFocus(getParent()) // assume we are inside a scroll container - || gFocusMgr.childHasMouseCapture(getParent())) + || gFocusMgr.childHasKeyboardFocus(mParentPanel) + || gFocusMgr.childHasMouseCapture(mParentPanel)) { // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process mNeedsAutoSelect = FALSE; diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 9cb885066a..50d3e0580e 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -53,7 +53,7 @@ public: { Optional<LLUIImage*> folder_arrow_image, selection_image; - Optional<LLFolderView*> root; + Mandatory<LLFolderView*> root; Mandatory<LLFolderViewModelItem*> listener; Optional<S32> folder_indentation, // pixels diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 261b5f33a2..2b943df48f 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -47,8 +47,9 @@ // LLIMFloaterContainer // LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) -: LLMultiFloater(seed) - ,mExpandCollapseBtn(NULL) +: LLMultiFloater(seed), + mExpandCollapseBtn(NULL), + mFolders(NULL) { // Firstly add our self to IMSession observers, so we catch session events LLIMMgr::getInstance()->addSessionObserver(this); @@ -90,6 +91,16 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsListPanel = getChild<LLPanel>("conversations_list_panel"); + LLFolderView::Params p; + //TODO RN: define view model for conversations + //p.view_model = ?; + p.parent_panel = mConversationsListPanel; + p.rect = mConversationsListPanel->getLocalRect(); + p.follows.flags = FOLLOWS_ALL; + + mFolders = LLUICtrlFactory::create<LLFolderView>(p); + mConversationsListPanel->addChild(mFolders); + mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this)); @@ -512,7 +523,7 @@ LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversat //params.icon = bridge->getIcon(); //params.icon_open = bridge->getOpenIcon(); //params.creation_date = bridge->getCreationDate(); - //params.root = mFolderRoot; + params.root = mFolders; params.listener = item; params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index f68cf07d8c..890a115a04 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -194,6 +194,7 @@ private: LLPanel* mConversationsListPanel; // This is the widget we add items to (i.e. clickable title for each conversation) conversations_items_map mConversationsItems; conversations_widgets_map mConversationsWidgets; + LLFolderView* mFolders; }; #endif // LL_LLIMFLOATERCONTAINER_H -- cgit v1.2.3 From 22f8301b1dea787e0adda80b2625a8d7d9ddbda4 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Wed, 4 Jul 2012 17:18:48 +0300 Subject: CHUI-172 CHUI-183 FIX Disabled applying stored rect dimensions when Nearby chat is hosted in Conversations floater. --- indra/newview/llimconversation.cpp | 4 ---- indra/newview/llnearbychat.cpp | 32 +++++++++++++++++++------------- 2 files changed, 19 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index acdd7ba46a..c855a844cf 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -254,9 +254,7 @@ void LLIMConversation::updateHeaderAndToolbar() if (mDragHandle) { mDragHandle->setTitleVisible(!is_hosted); - setCanDrag(!is_hosted); } - setCanResize(!is_hosted); // The button (>>) should be disabled for torn off P2P conversations. mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat); @@ -349,8 +347,6 @@ void LLIMConversation::onOpen(const LLSD& key) host_floater->collapseMessagesPane(false); } - setCanResize(TRUE); - updateHeaderAndToolbar(); } diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a81d6b4025..13e9eeee66 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -364,20 +364,18 @@ void LLNearbyChat::onOpen(const LLSD& key) bool LLNearbyChat::applyRectControl() { - bool rect_controlled = LLFloater::applyRectControl(); + bool is_torn_off = getHost() == NULL; -/* if (!mNearbyChat->getVisible()) + // Resize is limited to torn off floaters. + // A hosted floater is not resizable. + if (is_torn_off) { - reshape(getRect().getWidth(), getMinHeight()); - enableResizeCtrls(true, true, false); - } - else - {*/ enableResizeCtrls(true); - setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); -// } + } - return rect_controlled; + setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); + + return LLFloater::applyRectControl(); } void LLNearbyChat::onChatFontChange(LLFontGL* fontp) @@ -408,9 +406,17 @@ void LLNearbyChat::showHistory() { openFloater(); setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); - reshape(getRect().getWidth(), mExpandedHeight); - enableResizeCtrls(true); - storeRectControl(); + + bool is_torn_off = getHost() == NULL; + + // Reshape and enable resize controls only if it's a torn off floater. + // Otherwise all the size changes should be handled by LLIMFloaterContainer. + if (is_torn_off) + { + reshape(getRect().getWidth(), mExpandedHeight); + enableResizeCtrls(true); + storeRectControl(); + } } std::string LLNearbyChat::getCurrentChat() -- cgit v1.2.3 From e0eeed2680a2c6ba1055ac2a9f6465cb8004b7d6 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Wed, 4 Jul 2012 20:53:47 +0300 Subject: CHUI-189 FIXED (Blocked objects by name are not sorted correctly) - Fixed sort criteria. It's needed to take into account that objects in mute list are represented by two types: LLMute::BY_NAME and LLMute::OBJECT --- indra/newview/llblocklist.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llblocklist.cpp b/indra/newview/llblocklist.cpp index cb68f677eb..0165a9c4e8 100644 --- a/indra/newview/llblocklist.cpp +++ b/indra/newview/llblocklist.cpp @@ -267,9 +267,15 @@ bool LLBlockListNameTypeComparator::doCompare(const LLBlockedListItem* blocked_i LLMute::EType type1 = blocked_item1->getType(); LLMute::EType type2 = blocked_item2->getType(); - if (type1 != type2) + // if mute type is LLMute::BY_NAME or LLMute::OBJECT it means that this mute is an object + bool both_mutes_are_objects = (LLMute::OBJECT == type1 || LLMute::BY_NAME == type1) && (LLMute::OBJECT == type2 || LLMute::BY_NAME == type2); + + // mute types may be different, but since both LLMute::BY_NAME and LLMute::OBJECT types represent objects + // it's needed to perform additional checking of both_mutes_are_objects variable + if (type1 != type2 && !both_mutes_are_objects) { - return type1 > type2; + // objects in block list go first, so return true if mute type is not an avatar + return LLMute::AGENT != type1; } return NAME_COMPARATOR.compare(blocked_item1, blocked_item2); -- cgit v1.2.3 From 1fa326ccdbb9b99fedac0b4cdab232ec1fbe8d74 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Wed, 4 Jul 2012 21:13:25 +0300 Subject: CHUI-136 ADDITIONAL FIX (Implement new design for blocked list on the people floater) - Disabled object profile functionality according to the spec --- indra/newview/llblocklist.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llblocklist.cpp b/indra/newview/llblocklist.cpp index 0165a9c4e8..066cb71677 100644 --- a/indra/newview/llblocklist.cpp +++ b/indra/newview/llblocklist.cpp @@ -195,7 +195,13 @@ bool LLBlockList::isActionEnabled(const LLSD& userdata) const std::string command_name = userdata.asString(); - if ("unblock_item" == command_name || "profile_item" == command_name) + if ("profile_item" == command_name) + { + LLBlockedListItem* item = getBlockedItem(); + action_enabled = item && (LLMute::AGENT == item->getType()); + } + + if ("unblock_item" == command_name) { action_enabled = getSelectedItem() != NULL; } @@ -227,10 +233,6 @@ void LLBlockList::onCustomAction(const LLSD& userdata) LLAvatarActions::showProfile(item->getUUID()); break; - case LLMute::OBJECT: - LLFloaterSidePanelContainer::showPanel("inventory", LLSD().with("id", item->getUUID())); - break; - default: break; } -- cgit v1.2.3 From ff448aed525b8c1d2f05b6a5816ba6855707e4b8 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 5 Jul 2012 19:23:34 +0300 Subject: CHUI-200 FIXED Show correct and localized name of the nearby chat In the conversations list --- indra/newview/llimfloatercontainer.cpp | 4 ---- indra/newview/llnearbychat.cpp | 5 ++++- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 08ace601a3..134623722c 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -534,10 +534,6 @@ LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLF mFloater(floaterp), mContainer(containerp) { - // Hack: the nearby chat has no name so we catch that case and impose one - // Of course, we won't be doing this in the final code - if (name == "") - mName = "Nearby Chat"; } // Virtual action callbacks diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 13e9eeee66..644304aff3 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -158,6 +158,10 @@ BOOL LLNearbyChat::postBuild() enableResizeCtrls(true, true, false); + // title must be defined BEFORE call addToHost() because + // it is used for show the item's name in the conversations list + setTitle(getString("NearbyChatTitle")); + addToHost(); //for menu @@ -182,7 +186,6 @@ BOOL LLNearbyChat::postBuild() loadHistory(); } - setTitle(getString("NearbyChatTitle")); return LLIMConversation::postBuild(); } -- cgit v1.2.3 From 89d8a49f28dac5d99ec05a5201203ec57f72be02 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 5 Jul 2012 14:14:35 +0300 Subject: CHUI-197 FIXED Conversation names updating when checked corresponding preference --- indra/newview/llimfloatercontainer.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 134623722c..30a77bef98 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -104,6 +104,8 @@ BOOL LLIMFloaterContainer::postBuild() collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); + LLAvatarNameCache::addUseDisplayNamesCallback( + boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); return TRUE; } -- cgit v1.2.3 From c76c73770bf1a4095100cdb79021826ebebbd2f0 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 4 Jul 2012 17:57:46 +0300 Subject: CHUI-195 FIXED Starting ad-hoc conference call does not open Conversations floater --- indra/newview/llimview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 79018ec366..cdbb7c7cca 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2583,7 +2583,6 @@ LLUUID LLIMMgr::addSession( LLDynamicArray<LLUUID> ids; ids.put(other_participant_id); LLUUID session_id = addSession(name, dialog, other_participant_id, ids, voice); - notifyObserverSessionVoiceOrIMStarted(session_id); return session_id; } @@ -2653,6 +2652,8 @@ LLUUID LLIMMgr::addSession( noteMutedUsers(session_id, ids); } + notifyObserverSessionVoiceOrIMStarted(session_id); + return session_id; } -- cgit v1.2.3 From 73ad740443e615467f7e14fe4fb3f04d8abe2f9c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 4 Jul 2012 16:45:02 +0300 Subject: CHUI-170 FIXED Save Torn off state of Nearby Chat between sessions --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llimconversation.cpp | 8 +------- indra/newview/llimconversation.h | 2 +- indra/newview/llimfloatercontainer.cpp | 5 ++--- indra/newview/llnearbychat.cpp | 27 ++++++++++++++++++++++++--- indra/newview/llnearbychat.h | 2 ++ 6 files changed, 41 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4a586b02af..da3ff2d1ee 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1639,6 +1639,17 @@ <key>Value</key> <string /> </map> + <key>NearbyChatIsNotTornOff</key> + <map> + <key>Comment</key> + <string>saving torn-off state of the nearby chat between sessions</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>CloseChatOnReturn</key> <map> <key>Comment</key> diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index c855a844cf..3c6c5c3898 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -55,12 +55,6 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id) { mCommitCallbackRegistrar.add("IMSession.Menu.Action", boost::bind(&LLIMConversation::onIMSessionMenuItemClicked, this, _2)); -// mCommitCallbackRegistrar.add("IMSession.ExpCollapseBtn.Click", -// boost::bind(&LLIMConversation::onSlide, this)); -// mCommitCallbackRegistrar.add("IMSession.CloseBtn.Click", -// boost::bind(&LLFloater::onClickClose, this)); - mCommitCallbackRegistrar.add("IMSession.TearOffBtn.Click", - boost::bind(&LLIMConversation::onTearOffClicked, this)); mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", boost::bind(&LLIMConversation::onIMCompactExpandedMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.CheckItem", @@ -366,7 +360,7 @@ void LLIMConversation::onClose(bool app_quitting) void LLIMConversation::onTearOffClicked() { - onClickTearOff(this); + LLFloater::onClickTearOff(this); updateHeaderAndToolbar(); } diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 50663137ac..682779a44b 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -78,7 +78,7 @@ protected: bool onIMShowModesMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemEnable(const LLSD& userdata); static void onSlide(LLIMConversation *self); - void onTearOffClicked(); + virtual void onTearOffClicked(); // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 30a77bef98..546eccbd04 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -302,9 +302,8 @@ void LLIMFloaterContainer::setVisible(BOOL visible) if (visible) { // Make sure we have the Nearby Chat present when showing the conversation container - LLUUID nearbychat_uuid = LLUUID::null; // Hacky but true: the session id for nearby chat is always null - LLFloater* floaterp = findConversationItem(nearbychat_uuid); - if (floaterp == NULL) + LLFloater* nearby_chat = LLFloaterReg::findInstance("chat_bar"); + if (nearby_chat == NULL) { // If not found, force the creation of the nearby chat conversation panel // *TODO: find a way to move this to XML as a default panel or something like that diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 644304aff3..384762549a 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -345,15 +345,36 @@ void LLNearbyChat::enableDisableCallBtn() getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/); } +void LLNearbyChat::onTearOffClicked() +{ + LLIMConversation::onTearOffClicked(); + + LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + + // see CHUI-170: Save torn-off state of the nearby chat between sessions + BOOL in_the_multifloater = (getHost() == im_box); + gSavedSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater); +} + void LLNearbyChat::addToHost() { - if (LLIMConversation::isChatMultiTab()) + if ( LLIMConversation::isChatMultiTab()) { LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); - if (im_box) { - im_box->addFloater(this, FALSE, LLTabContainer::END); + if (gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) + { + im_box->addFloater(this, TRUE, LLTabContainer::END); + } + else + { + // setting of the "potential" host: this sequence sets + // LLFloater::mHostHandle = NULL (a current host), but + // LLFloater::mLastHostHandle = im_box (a "future" host) + setHost(im_box); + setHost(NULL); + } } } } diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 61404df942..90feb71488 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -101,6 +101,8 @@ protected: void onToggleNearbyChatPanel(); + /*virtual*/ void onTearOffClicked(); + static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); EChatType processChatTypeTriggers(EChatType type, std::string &str); -- cgit v1.2.3 From ec15ff6350c0997421cf2884e40aa9feaa070d4d Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 5 Jul 2012 16:42:20 -0700 Subject: CHUI-98 : WIP, use the refactored folder view for conversation view list --- indra/llui/llfolderview.cpp | 36 ++++++++++----- indra/newview/llimfloatercontainer.cpp | 23 +++++++++- indra/newview/llimfloatercontainer.h | 83 ++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 990b79a30b..92e3b7a8e9 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -320,10 +320,10 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) LLFolderViewFolder::arrange(&mMinWidth, &target_height); - LLRect scroll_rect = mScrollContainer->getContentWindowRect(); + LLRect scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); - LLRect new_scroll_rect = mScrollContainer->getContentWindowRect(); + LLRect new_scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) { reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); @@ -945,7 +945,7 @@ void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) mAutoOpenItems.push(item); item->setOpen(TRUE); - LLRect content_rect = mScrollContainer->getContentWindowRect(); + LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0); scrollToShowItem(item, constraint_rect); } @@ -1225,25 +1225,37 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) case KEY_PAGE_UP: mSearchString.clear(); - mScrollContainer->pageUp(30); + if (mScrollContainer) + { + mScrollContainer->pageUp(30); + } handled = TRUE; break; case KEY_PAGE_DOWN: mSearchString.clear(); - mScrollContainer->pageDown(30); + if (mScrollContainer) + { + mScrollContainer->pageDown(30); + } handled = TRUE; break; case KEY_HOME: mSearchString.clear(); - mScrollContainer->goToTop(); + if (mScrollContainer) + { + mScrollContainer->goToTop(); + } handled = TRUE; break; case KEY_END: mSearchString.clear(); - mScrollContainer->goToBottom(); + if (mScrollContainer) + { + mScrollContainer->goToBottom(); + } break; case KEY_DOWN: @@ -1719,8 +1731,8 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr LLRect LLFolderView::getVisibleRect() { - S32 visible_height = mScrollContainer->getRect().getHeight(); - S32 visible_width = mScrollContainer->getRect().getWidth(); + S32 visible_height = (mScrollContainer ? mScrollContainer->getRect().getHeight() : 0); + S32 visible_width = (mScrollContainer ? mScrollContainer->getRect().getWidth() : 0); LLRect visible_rect; visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height); return visible_rect; @@ -1816,7 +1828,7 @@ void LLFolderView::update() // lets pin it! mPinningSelectedItem = TRUE; - LLRect visible_content_rect = mScrollContainer->getVisibleContentRect(); + LLRect visible_content_rect = (mScrollContainer ? mScrollContainer->getVisibleContentRect() : LLRect()); LLFolderViewItem* selected_item = mSelectedItems.back(); LLRect item_rect; @@ -1831,7 +1843,7 @@ void LLFolderView::update() else { // otherwise we just want it onscreen somewhere - LLRect content_rect = mScrollContainer->getContentWindowRect(); + LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); } } @@ -1854,7 +1866,7 @@ void LLFolderView::update() else { // during normal use (page up/page down, etc), just try to fit item on screen - LLRect content_rect = mScrollContainer->getContentWindowRect(); + LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 2b943df48f..be38eddbaf 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -91,12 +91,14 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsListPanel = getChild<LLPanel>("conversations_list_panel"); + mRoot = new LLConversationItem(); LLFolderView::Params p; - //TODO RN: define view model for conversations - //p.view_model = ?; + // CHUI-98 : View Model for conversations + p.view_model = &mConversationViewModel; p.parent_panel = mConversationsListPanel; p.rect = mConversationsListPanel->getLocalRect(); p.follows.flags = FOLLOWS_ALL; + p.listener = mRoot; mFolders = LLUICtrlFactory::create<LLFolderView>(p); mConversationsListPanel->addChild(mFolders); @@ -544,6 +546,15 @@ LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLF mName = "Nearby Chat"; } +LLConversationItem::LLConversationItem() : + mName(""), + mUUID(), + mFloater(NULL), + mContainer(NULL) +{ +} + + // Virtual action callbacks void LLConversationItem::selectItem(void) { @@ -589,4 +600,12 @@ void LLConversationItem::showProperties(void) { } +bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const +{ + // We compare only by name for the moment + // *TODO : Implement the sorting by date + S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); + return (compare < 0); +} + // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 890a115a04..f146e65897 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -57,6 +57,7 @@ class LLConversationItem : public LLFolderViewModelItemCommon { public: LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp); + LLConversationItem(); virtual ~LLConversationItem() {} // Stub those things we won't really be using in this conversation context @@ -120,6 +121,86 @@ private: LLFloater* mFloater; LLIMFloaterContainer* mContainer; }; + +// We don't want to ever filter conversations but we need to declare that class to create a conversation view model. +// We just stubb everything for the moment. +class LLConversationFilter : public LLFolderViewFilter +{ +public: + + enum ESortOrderType + { + SO_NAME = 0, // Sort inventory by name + SO_DATE = 0x1, // Sort inventory by date + }; + + LLConversationFilter() { mEmpty = ""; } + ~LLConversationFilter() {} + + bool check(const LLFolderViewModelItem* item) { return true; } + bool checkFolder(const LLFolderViewModelItem* folder) const { return true; } + void setEmptyLookupMessage(const std::string& message) { } + std::string getEmptyLookupMessage() const { return mEmpty; } + bool showAllResults() const { return true; } + + bool isActive() const { return false; } + bool isModified() const { return false; } + void clearModified() { } + const std::string& getName() const { return mEmpty; } + const std::string& getFilterText() { return mEmpty; } + void setModified(EFilterModified behavior = FILTER_RESTART) { } + + void setFilterCount(S32 count) { } + S32 getFilterCount() const { return 0; } + void decrementFilterCount() { } + + bool isDefault() const { return true; } + bool isNotDefault() const { return false; } + void markDefault() { } + void resetDefault() { } + + S32 getCurrentGeneration() const { return 0; } + S32 getFirstSuccessGeneration() const { return 0; } + S32 getFirstRequiredGeneration() const { return 0; } +private: + std::string mEmpty; +}; + +class LLConversationSort +{ +public: + LLConversationSort(U32 order = 0) + : mSortOrder(order), + mByDate(false), + mByName(false) + { + mByDate = (order & LLConversationFilter::SO_DATE); + mByName = (order & LLConversationFilter::SO_NAME); + } + + bool isByDate() const { return mByDate; } + U32 getSortOrder() const { return mSortOrder; } + + bool operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const; +private: + U32 mSortOrder; + bool mByDate; + bool mByName; +}; + +class LLConversationViewModel +: public LLFolderViewModel<LLConversationSort, LLConversationItem, LLConversationItem, LLConversationFilter> +{ +public: + typedef LLFolderViewModel<LLConversationSort, LLConversationItem, LLConversationItem, LLConversationFilter> base_t; + + void sort(LLFolderViewFolder* folder) { } // *TODO : implement conversation sort + bool contentsReady() { return true; } // *TODO : we need to check that participants names are available somewhat + bool startDrag(std::vector<LLFolderViewModelItem*>& items) { return false; } // We do not allow drag of conversation items + +private: +}; + // CHUI-137 : End class LLIMFloaterContainer @@ -189,6 +270,8 @@ public: void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp); LLFloater* findConversationItem(LLUUID& uuid); private: + LLConversationViewModel mConversationViewModel; + LLConversationItem* mRoot; LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); // Conversation list data LLPanel* mConversationsListPanel; // This is the widget we add items to (i.e. clickable title for each conversation) -- cgit v1.2.3 From c3e048a2f14b08ec4428ea9f5a10f17de154e1fc Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 6 Jul 2012 13:30:05 +0300 Subject: build fix --- indra/newview/llimfloatercontainer.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 546eccbd04..f3b97776fc 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -37,6 +37,7 @@ #include "llagent.h" #include "llavataractions.h" #include "llavatariconctrl.h" +#include "llavatarnamecache.h" #include "llgroupiconctrl.h" #include "llfloateravatarpicker.h" #include "llimview.h" -- cgit v1.2.3 From 9ab042dd1d003da15dd579f366db04d4aae3ff6b Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 6 Jul 2012 17:49:02 +0300 Subject: CHUI-196 FIXED (Chat text entry area gets resized unexpectedly with certain user display names) - Fixed label length calculating --- indra/llui/lltextbase.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 3b3bc64c5b..a7bc6bbb77 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -510,7 +510,7 @@ void LLTextBase::drawText() } else if (text_len <= 0 && !mLabel.empty() && !hasFocus()) { - text_len = mLabel.length(); + text_len = mLabel.getWString().length(); } S32 selection_left = -1; @@ -1816,7 +1816,7 @@ void LLTextBase::resetLabel() style->setColor(mTentativeFgColor); LLStyleConstSP sp(style); - LLTextSegmentPtr label = new LLLabelTextSegment(sp, 0, getLabel().length() + 1, *this); + LLTextSegmentPtr label = new LLLabelTextSegment(sp, 0, mLabel.getWString().length() + 1, *this); insertSegment(label); } } @@ -2988,7 +2988,7 @@ const LLWString& LLLabelTextSegment::getWText() const /*virtual*/ const S32 LLLabelTextSegment::getLength() const { - return mEditor.getLabel().length(); + return mEditor.getWlabel().length(); } // -- cgit v1.2.3 From 0b8a57cab8628ba064a14250a140ca9615669d2c Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Sat, 7 Jul 2012 00:50:31 +0300 Subject: Linux build fix. LLFolderViewModelItem placed before the call to a method of this class in LLFolderViewModel::sort(). --- indra/llui/llfolderviewmodel.h | 207 ++++++++++++++++++++--------------------- 1 file changed, 103 insertions(+), 104 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 0f5f9a1f50..268ae8eea8 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -107,110 +107,6 @@ public: virtual S32 getFirstRequiredGeneration() const = 0; }; -class LLFolderViewModelInterface -{ -public: - virtual ~LLFolderViewModelInterface() {} - virtual void requestSortAll() = 0; - - virtual void sort(class LLFolderViewFolder*) = 0; - virtual void filter() = 0; - - virtual bool contentsReady() = 0; - virtual void setFolderView(LLFolderView* folder_view) = 0; - virtual LLFolderViewFilter* getFilter() = 0; - virtual const LLFolderViewFilter* getFilter() const = 0; - virtual std::string getStatusText() = 0; - - virtual bool startDrag(std::vector<LLFolderViewModelItem*>& items) = 0; -}; - -class LLFolderViewModelCommon : public LLFolderViewModelInterface -{ -public: - LLFolderViewModelCommon() - : mTargetSortVersion(0), - mFolderView(NULL) - {} - - virtual void requestSortAll() - { - // sort everything - mTargetSortVersion++; - } - virtual std::string getStatusText(); - virtual void filter(); - - void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} - -protected: - bool needsSort(class LLFolderViewModelItem* item); - - S32 mTargetSortVersion; - LLFolderView* mFolderView; - -}; - -template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE> -class LLFolderViewModel : public LLFolderViewModelCommon -{ -public: - LLFolderViewModel(){} - virtual ~LLFolderViewModel() {} - - typedef SORT_TYPE SortType; - typedef ITEM_TYPE ItemType; - typedef FOLDER_TYPE FolderType; - typedef FILTER_TYPE FilterType; - - virtual SortType& getSorter() { return mSorter; } - virtual const SortType& getSorter() const { return mSorter; } - virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } - - virtual FilterType* getFilter() { return &mFilter; } - virtual const FilterType* getFilter() const { return &mFilter; } - virtual void setFilter(const FilterType& filter) { mFilter = filter; } - - // TODO RN: remove this and put all filtering logic in view model - // add getStatusText and isFiltering() - virtual bool contentsReady() { return true; } - - - struct ViewModelCompare - { - ViewModelCompare(const SortType& sorter) - : mSorter(sorter) - {} - - bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const - { - return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); - } - - bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const - { - return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); - } - - const SortType& mSorter; - }; - - void sort(LLFolderViewFolder* folder) - { - if (needsSort(folder->getViewModelItem())) - { - folder->sortFolders(ViewModelCompare(getSorter())); - folder->sortItems(ViewModelCompare(getSorter())); - folder->getViewModelItem()->setSortVersion(mTargetSortVersion); - folder->requestArrange(); - } - } - -protected: - SortType mSorter; - FilterType mFilter; -}; - // This is am abstract base class that users of the folderview classes // would use to bridge the folder view with the underlying data class LLFolderViewModelItem @@ -349,5 +245,108 @@ protected: LLFolderViewItem* mFolderViewItem; }; +class LLFolderViewModelInterface +{ +public: + virtual ~LLFolderViewModelInterface() {} + virtual void requestSortAll() = 0; + + virtual void sort(class LLFolderViewFolder*) = 0; + virtual void filter() = 0; + + virtual bool contentsReady() = 0; + virtual void setFolderView(LLFolderView* folder_view) = 0; + virtual LLFolderViewFilter* getFilter() = 0; + virtual const LLFolderViewFilter* getFilter() const = 0; + virtual std::string getStatusText() = 0; + + virtual bool startDrag(std::vector<LLFolderViewModelItem*>& items) = 0; +}; + +class LLFolderViewModelCommon : public LLFolderViewModelInterface +{ +public: + LLFolderViewModelCommon() + : mTargetSortVersion(0), + mFolderView(NULL) + {} + + virtual void requestSortAll() + { + // sort everything + mTargetSortVersion++; + } + virtual std::string getStatusText(); + virtual void filter(); + + void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} + +protected: + bool needsSort(class LLFolderViewModelItem* item); + + S32 mTargetSortVersion; + LLFolderView* mFolderView; + +}; + +template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE> +class LLFolderViewModel : public LLFolderViewModelCommon +{ +public: + LLFolderViewModel(){} + virtual ~LLFolderViewModel() {} + + typedef SORT_TYPE SortType; + typedef ITEM_TYPE ItemType; + typedef FOLDER_TYPE FolderType; + typedef FILTER_TYPE FilterType; + + virtual SortType& getSorter() { return mSorter; } + virtual const SortType& getSorter() const { return mSorter; } + virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } + + virtual FilterType* getFilter() { return &mFilter; } + virtual const FilterType* getFilter() const { return &mFilter; } + virtual void setFilter(const FilterType& filter) { mFilter = filter; } + + // TODO RN: remove this and put all filtering logic in view model + // add getStatusText and isFiltering() + virtual bool contentsReady() { return true; } + + + struct ViewModelCompare + { + ViewModelCompare(const SortType& sorter) + : mSorter(sorter) + {} + + bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const + { + return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); + } + + bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const + { + return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); + } + + const SortType& mSorter; + }; + + void sort(LLFolderViewFolder* folder) + { + if (needsSort(folder->getViewModelItem())) + { + folder->sortFolders(ViewModelCompare(getSorter())); + folder->sortItems(ViewModelCompare(getSorter())); + folder->getViewModelItem()->setSortVersion(mTargetSortVersion); + folder->requestArrange(); + } + } + +protected: + SortType mSorter; + FilterType mFilter; +}; #endif // LLFOLDERVIEWMODEL_H -- cgit v1.2.3 From c9e11635488720626601b7b4a7926f09031a6908 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Sat, 7 Jul 2012 01:10:30 +0300 Subject: Another Linux build fix. --- indra/llui/llfolderview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 92e3b7a8e9..8ade17b763 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1927,7 +1927,7 @@ void LLFolderView::updateRenamerPosition() screenPointToLocal( x, y, &x, &y ); mRenamer->setOrigin( x, y ); - LLRect scroller_rect(0, 0, LLUI::getWindowSize().mV[VX], 0); + LLRect scroller_rect(0, 0, (S32)LLUI::getWindowSize().mV[VX], 0); if (mScrollContainer) { scroller_rect = mScrollContainer->getContentWindowRect(); -- cgit v1.2.3 From b490266226ac79cc7570ff7ee921506e941cce16 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 9 Jul 2012 11:49:43 -0700 Subject: CHUI-98 : WIP. Clean up conversation list data structure and comments --- indra/newview/llimfloatercontainer.cpp | 14 +++++++------- indra/newview/llimfloatercontainer.h | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index be38eddbaf..d343c8be24 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -49,7 +49,7 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) : LLMultiFloater(seed), mExpandCollapseBtn(NULL), - mFolders(NULL) + mConversationsRoot(NULL) { // Firstly add our self to IMSession observers, so we catch session events LLIMMgr::getInstance()->addSessionObserver(this); @@ -91,17 +91,17 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsListPanel = getChild<LLPanel>("conversations_list_panel"); - mRoot = new LLConversationItem(); - LLFolderView::Params p; // CHUI-98 : View Model for conversations + LLConversationItem* base_item = new LLConversationItem(); + LLFolderView::Params p; p.view_model = &mConversationViewModel; p.parent_panel = mConversationsListPanel; p.rect = mConversationsListPanel->getLocalRect(); p.follows.flags = FOLLOWS_ALL; - p.listener = mRoot; + p.listener = base_item; - mFolders = LLUICtrlFactory::create<LLFolderView>(p); - mConversationsListPanel->addChild(mFolders); + mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); + mConversationsListPanel->addChild(mConversationsRoot); mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this)); @@ -525,7 +525,7 @@ LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversat //params.icon = bridge->getIcon(); //params.icon_open = bridge->getOpenIcon(); //params.creation_date = bridge->getCreationDate(); - params.root = mFolders; + params.root = mConversationsRoot; params.listener = item; params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index f146e65897..8f0ec27905 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -264,20 +264,20 @@ private: LLLayoutPanel* mConversationsPane; LLLayoutStack* mConversationsStack; - // CHUI-137 : Temporary implementation of conversations list + // Conversation list implementation public: void removeConversationListItem(LLFloater* floaterp, bool change_focus = true); void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp); LLFloater* findConversationItem(LLUUID& uuid); private: - LLConversationViewModel mConversationViewModel; - LLConversationItem* mRoot; LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); + // Conversation list data - LLPanel* mConversationsListPanel; // This is the widget we add items to (i.e. clickable title for each conversation) + LLPanel* mConversationsListPanel; // This is the main widget we add conversation widget to conversations_items_map mConversationsItems; conversations_widgets_map mConversationsWidgets; - LLFolderView* mFolders; + LLConversationViewModel mConversationViewModel; + LLFolderView* mConversationsRoot; }; #endif // LL_LLIMFLOATERCONTAINER_H -- cgit v1.2.3 From b203fe12f8ea19ee80d9de1ac6ff4ebbc3bdb493 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Tue, 10 Jul 2012 16:49:49 +0300 Subject: CHUI-201 FIX for crash when leaving a voice call via the end call prompt. Fixed the problem with confirmLeaveCallCallback() firing after the chat floater is destroyed. --- indra/newview/llimfloater.cpp | 57 +++++++++++++++++++++++-------------------- indra/newview/llimfloater.h | 2 ++ 2 files changed, 33 insertions(+), 26 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index a506f0f9f3..23c97c5345 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -118,6 +118,35 @@ void LLIMFloater::refresh() } } +// virtual +void LLIMFloater::onClickCloseBtn() +{ + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( + mSessionID); + + if (session == NULL) + { + llwarns << "Empty session." << llendl; + return; + } + + bool is_call_with_chat = session->isGroupSessionType() + || session->isAdHocSessionType() || session->isP2PSessionType(); + + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + + if (is_call_with_chat && voice_channel != NULL + && voice_channel->isActive()) + { + LLSD payload; + payload["session_id"] = mSessionID; + LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); + return; + } + + LLIMConversation::onClickCloseBtn(); +} + /* static */ void LLIMFloater::newIMCallback(const LLSD& data) { @@ -407,8 +436,7 @@ void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) bool is_voice_call = voice_channel != NULL && voice_channel->isActive(); // then we can close the current session - gIMMgr->leaveSession(mSessionID); - LLIMConversation::onClose(false); + onClose(false); // Start a new ad hoc voice call if we invite new participants to a P2P call, // or start a text chat otherwise. @@ -667,29 +695,6 @@ LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) void LLIMFloater::onClose(bool app_quitting) { - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - mSessionID); - - if (session == NULL) - { - llwarns << "Empty session." << llendl; - return; - } - - bool is_call_with_chat = session->isGroupSessionType() - || session->isAdHocSessionType() || session->isP2PSessionType(); - - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - - if (is_call_with_chat && voice_channel != NULL - && voice_channel->isActive()) - { - LLSD payload; - payload["session_id"] = mSessionID; - LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); - return; - } - setTyping(false); // The source of much argument and design thrashing @@ -1278,7 +1283,7 @@ void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD& const LLSD& payload = notification["payload"]; LLUUID session_id = payload["session_id"]; - LLFloater* im_floater = LLFloaterReg::findInstance("impanel", session_id); + LLFloater* im_floater = findInstance(session_id); if (option == 0 && im_floater != NULL) { im_floater->closeFloater(); diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 2e8fc84746..2ac11ded20 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -132,6 +132,8 @@ private: /*virtual*/ void refresh(); + /*virtual*/ void onClickCloseBtn(); + // Update the window title, input field help text, etc. void updateSessionName(const std::string& ui_title, const std::string& ui_label); -- cgit v1.2.3 From aafbf0d21301ccaf2e447a556d08e6686f519d4d Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Wed, 11 Jul 2012 17:19:22 +0300 Subject: CHUI-203 FIXED Conversations floater resizing when it is opened with FUI Chat button. --- indra/newview/llimfloatercontainer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index e9144a4969..f54b3672e5 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -393,7 +393,9 @@ void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) { LLRect floater_rect = getRect(); floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); - setShape(floater_rect); + + // Set by_user = true so that reshaped rect is saved in user_settings. + setShape(floater_rect, true); updateResizeLimits(); -- cgit v1.2.3 From 6dff1477d5898c54ea0a08aa72bd099b628433e7 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 12 Jul 2012 16:36:01 +0300 Subject: CHUI-199 FIXED Save positioning of conversations between sessions --- indra/newview/llimconversation.cpp | 33 ++++++++++++++++++---- indra/newview/llimconversation.h | 1 + indra/newview/llimfloatercontainer.cpp | 19 ------------- indra/newview/llimfloatercontainer.h | 1 - .../skins/default/xui/en/floater_im_session.xml | 1 + 5 files changed, 30 insertions(+), 25 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 3c6c5c3898..4774cc2d5a 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -219,16 +219,39 @@ void LLIMConversation::updateHeaderAndToolbar() { bool is_hosted = getHost() != NULL; - if (is_hosted) + if (mWasHosted != is_hosted) { - for (S32 i = 0; i < BUTTON_COUNT; i++) + mWasHosted = is_hosted; + LLView* floater_contents = getChild<LLView>("contents_view"); + LLRect contents_rect = floater_contents->getRect(); + + if (is_hosted) { - if (mButtons[i]) + for (S32 i = 0; i < BUTTON_COUNT; i++) { - // Hide the standard header buttons in a docked IM floater. - mButtons[i]->setVisible(false); + if (mButtons[i]) + { + // Hide the standard header buttons in a docked IM floater. + mButtons[i]->setVisible(false); + } } + + // we don't show the header when the floater is hosted, so reshape floater contents + // to occupy the header space. + LLRect floater_rect = getRect(); + contents_rect.setOriginAndSize( + contents_rect.mLeft, + contents_rect.mBottom, + floater_rect.getWidth(), + floater_rect.getHeight()); } + else + { + // reduce the floater contents height by header height + contents_rect.mTop -= getHeaderHeight(); + } + + floater_contents->setShape(contents_rect); } // Participant list should be visible only in torn off floaters. diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 682779a44b..19d1e523f0 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -91,6 +91,7 @@ protected: bool mIsNearbyChat; bool mIsP2PChat; + bool mWasHosted; LLLayoutPanel* mParticipantListPanel; LLParticipantList* mParticipantList; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index f54b3672e5..bf0fc2f6c0 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -154,12 +154,6 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, // Add a conversation list item in the left pane addConversationListItem(floaterp->getTitle(), session_id, floaterp); - LLView* floater_contents = floaterp->getChild<LLView>("contents_view"); - - // we don't show the header when the floater is hosted, - // so reshape floater contents to occupy the header space - floater_contents->setShape(floaterp->getRect()); - LLIconCtrl* icon = 0; if(gAgent.isInGroup(session_id, TRUE)) @@ -185,19 +179,6 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, mTabContainer->setTabImage(floaterp, icon); } -// virtual -void LLIMFloaterContainer::removeFloater(LLFloater* floaterp) -{ - LLMultiFloater::removeFloater(floaterp); - - LLRect contents_rect = floaterp->getRect(); - - // reduce the floater contents height by header height - contents_rect.mTop -= floaterp->getHeaderHeight(); - - LLView* floater_contents = floaterp->getChild<LLView>("contents_view"); - floater_contents->setShape(contents_rect); -} void LLIMFloaterContainer::onCloseFloater(LLUUID& id) { diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 0d988b5b73..b624b7558a 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -220,7 +220,6 @@ public: /*virtual*/ void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); - /*virtual*/ void removeFloater(LLFloater* floaterp); /*virtual*/ void tabClose(); diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 32eb4ebdae..95f6708e96 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -9,6 +9,7 @@ can_dock="false" can_minimize="true" can_close="true" + save_rect="true" visible="false" width="394" can_resize="true" -- cgit v1.2.3 From af7de5dd9373a5a15c4d5ea107782e50eb3ce62c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 12 Jul 2012 19:06:29 +0300 Subject: CHUI-170 Workaround for the permanently showing of the nearbychat's name in a conversations list when that floater is torn-off --- indra/newview/llnearbychat.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra') diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 384762549a..1c81cdc4bc 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -363,6 +363,9 @@ void LLNearbyChat::addToHost() LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); if (im_box) { + // Make sure the Nearby Chat is present in the conversations list + im_box->addConversationListItem(getTitle(), getKey(), this); + if (gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) { im_box->addFloater(this, TRUE, LLTabContainer::END); -- cgit v1.2.3 From 7f7a9b7cbae153b00b8a77d3d662257bf6152912 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Fri, 13 Jul 2012 20:06:35 +0300 Subject: CHUI-205 FIXED conversations selection in the conversations list. Each conversation item is added to the folder view which lists all conversations. --- indra/newview/llimfloatercontainer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index bf0fc2f6c0..4f626cb5d2 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -438,6 +438,9 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI LLFolderViewItem* widget = createConversationItemWidget(item); mConversationsWidgets[floaterp] = widget; + // Add a new conversation widget to the root folder of a folder view. + mConversationsRoot->addItem(widget); + // Add it to the UI widget->setVisible(TRUE); mConversationsListPanel->addChild(widget); @@ -460,7 +463,7 @@ void LLIMFloaterContainer::removeConversationListItem(LLFloater* floaterp, bool if (widget_it != mConversationsWidgets.end()) { LLFolderViewItem* widget = widget_it->second; - delete widget; + widget->destroyView(); } // Suppress the conversation items and widgets from their respective maps -- cgit v1.2.3 From 56277fa43c6f6491d356c6fb8a0a0275d4cd00fc Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 13 Jul 2012 20:24:44 +0300 Subject: CHUI-206 FIXED Viewer crash when selecting to cut inventory item, then selecting to cut another inventory item --- indra/newview/llfolderviewmodelinventory.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index d23b4af8cb..dff1e1be90 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -158,22 +158,20 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite if (item->getLastFilterGeneration() < filter_generation) { + // recursive application of the filter for child items + item->filter( filter ); + if (item->getLastFilterGeneration() >= must_pass_generation && !item->passedFilter(must_pass_generation)) { // failed to pass an earlier filter that was a subset of the current one // go ahead and flag this item as done - item->filter(filter); if (item->passedFilter()) { llerrs << "Invalid shortcut in inventory filtering!" << llendl; } item->setPassedFilter(false, false, filter_generation); } - else - { - item->filter( filter ); - } } // track latest generation to pass any child items, for each folder up to root -- cgit v1.2.3 From 8fd35a0a084303073bc40580d69c797c073fb4dc Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 13 Jul 2012 16:30:33 +0300 Subject: CHUI-207 FIXED cancellation of removal of the object that has already been removed --- indra/newview/llinventorypanel.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 0aa67cddca..ed370e9add 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -533,7 +533,6 @@ void LLInventoryPanel::modelChanged(U32 mask) // Remove the item's UI. removeItemID(viewmodel_item->getUUID()); view_item->destroyView(); - removeItemID(viewmodel_item->getUUID()); } } } -- cgit v1.2.3 From b3ca0b09dcbe6189d6b1f6d0439b0d9d6f575007 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 17 Jul 2012 16:43:48 +0300 Subject: Fixed positioning of conversations into container --- indra/newview/llimconversation.cpp | 51 ++++++++++++++++++++++++-------------- indra/newview/llimconversation.h | 3 +++ 2 files changed, 36 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 4774cc2d5a..ec7e0ee6cb 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -43,6 +43,7 @@ const F32 REFRESH_INTERVAL = 0.2f; LLIMConversation::LLIMConversation(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id) , mIsP2PChat(false) + , mWasHosted(false) , mExpandCollapseBtn(NULL) , mTearOffBtn(NULL) , mCloseBtn(NULL) @@ -80,6 +81,8 @@ LLIMConversation::~LLIMConversation() BOOL LLIMConversation::postBuild() { + BOOL result; + mCloseBtn = getChild<LLButton>("close_btn"); mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); @@ -103,6 +106,7 @@ BOOL LLIMConversation::postBuild() } buildParticipantList(); + updateHeaderAndToolbar(); if (isChatMultiTab()) @@ -111,13 +115,14 @@ BOOL LLIMConversation::postBuild() { setCanClose(FALSE); } - return LLFloater::postBuild(); + result = LLFloater::postBuild(); } else { - return LLDockableFloater::postBuild(); + result = LLDockableFloater::postBuild(); } + return result; } void LLIMConversation::draw() @@ -215,7 +220,7 @@ bool LLIMConversation::onIMShowModesMenuItemEnable(const LLSD& userdata) return (plain_text && (is_not_names || mIsP2PChat)); } -void LLIMConversation::updateHeaderAndToolbar() +void LLIMConversation::hideOrShowTitle() { bool is_hosted = getHost() != NULL; @@ -227,23 +232,9 @@ void LLIMConversation::updateHeaderAndToolbar() if (is_hosted) { - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - if (mButtons[i]) - { - // Hide the standard header buttons in a docked IM floater. - mButtons[i]->setVisible(false); - } - } - // we don't show the header when the floater is hosted, so reshape floater contents // to occupy the header space. - LLRect floater_rect = getRect(); - contents_rect.setOriginAndSize( - contents_rect.mLeft, - contents_rect.mBottom, - floater_rect.getWidth(), - floater_rect.getHeight()); + contents_rect.mTop += getHeaderHeight(); } else { @@ -253,6 +244,30 @@ void LLIMConversation::updateHeaderAndToolbar() floater_contents->setShape(contents_rect); } +} + +void LLIMConversation::hideAllStandardButtons() +{ + for (S32 i = 0; i < BUTTON_COUNT; i++) + { + if (mButtons[i]) + { + // Hide the standard header buttons in a docked IM floater. + mButtons[i]->setVisible(false); + } + } +} + +void LLIMConversation::updateHeaderAndToolbar() +{ + bool is_hosted = getHost() != NULL; + + if (is_hosted) + { + hideAllStandardButtons(); + } + + hideOrShowTitle(); // Participant list should be visible only in torn off floaters. bool is_participant_list_visible = diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 19d1e523f0..e6b4f534cc 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -89,6 +89,9 @@ protected: void buildParticipantList(); void onSortMenuItemClicked(const LLSD& userdata); + void hideOrShowTitle(); + void hideAllStandardButtons(); + bool mIsNearbyChat; bool mIsP2PChat; bool mWasHosted; -- cgit v1.2.3 From ec4d1a2450807afcff5c0f0ebf651c9e67f1b310 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 17 Jul 2012 12:07:25 -0700 Subject: CHUI-234 : Fix crashers in landmarks panel --- indra/newview/llpanellandmarks.cpp | 2 +- indra/newview/llplacesinventorypanel.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index faef923338..4bbab52e5a 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -651,7 +651,7 @@ void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesI // Start background fetch, mostly for My Inventory and Library if (expanded) { - const LLUUID &cat_id = mCurrentSelectedList->getRootFolderID(); + const LLUUID &cat_id = inventory_list->getRootFolderID(); // Just because the category itself has been fetched, doesn't mean its child folders have. /* if (!gInventory.isCategoryComplete(cat_id)) diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index d95d5eac19..65d9691902 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -93,6 +93,7 @@ void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& par p.parent_panel = this; p.allow_multiselect = mAllowMultiSelect; p.use_ellipses = true; // truncate inventory item text so remove horizontal scroller + p.view_model = &mInventoryViewModel; mFolderRoot = LLUICtrlFactory::create<LLPlacesFolderView>(p); } -- cgit v1.2.3 From 15f6f877f923ecc85489c0159ca62deb02de1201 Mon Sep 17 00:00:00 2001 From: merov_linden <none@none> Date: Thu, 19 Jul 2012 03:57:24 +0100 Subject: CHUI-236 : WIP : Modify the handling of FT_ROOT_INVENTORY which was creating havoc in LLInventoryModel instantiation. Still, some of those hack will have to come back on. --- indra/newview/llinventorymodel.cpp | 37 ++++++++++++++++---------------- indra/newview/llplacesinventorypanel.cpp | 37 +------------------------------- 2 files changed, 20 insertions(+), 54 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 9b0d12b353..3250d60179 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -210,7 +210,7 @@ const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(cons if (!cat) break; const LLFolderType::EType folder_type = cat->getPreferredType(); if (folder_type != LLFolderType::FT_NONE && - folder_type != LLFolderType::FT_ROOT_INVENTORY && +// folder_type != LLFolderType::FT_ROOT_INVENTORY && !LLFolderType::lookupIsEnsembleType(folder_type)) { return cat; @@ -380,11 +380,12 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe LLUUID rv = LLUUID::null; const LLUUID &root_id = (find_in_library) ? gInventory.getLibraryRootFolderID() : gInventory.getRootFolderID(); - if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) - { - rv = root_id; - } - else if (root_id.notNull()) +// if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) +// { +// rv = root_id; +// } +// else if (root_id.notNull()) + if (root_id.notNull()) { cat_array_t* cats = NULL; cats = get_ptr_in_map(mParentChildCategoryTree, root_id); @@ -2026,11 +2027,11 @@ void LLInventoryModel::buildParentChildMap() { cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); } - else if(LLFolderType::FT_ROOT_INVENTORY == pref) - { +// else if(LLFolderType::FT_ROOT_INVENTORY == pref) +// { // it's the root - cat->setParent(LLUUID::null); - } +// cat->setParent(LLUUID::null); +// } else { // it's a protected folder. @@ -2160,14 +2161,14 @@ void LLInventoryModel::buildParentChildMap() if(category && category->getPreferredType() != LLFolderType::FT_ROOT_INVENTORY) continue; - if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) ) - { - if(category->getUUID()!=mRootFolderID) - { - LLUUID& new_inv_root_folder_id = const_cast<LLUUID&>(mRootFolderID); - new_inv_root_folder_id = category->getUUID(); - } - } +// if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) ) +// { +// if(category->getUUID()!=mRootFolderID) +// { +// LLUUID& new_inv_root_folder_id = const_cast<LLUUID&>(mRootFolderID); +// new_inv_root_folder_id = category->getUUID(); +// } +// } } } diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index 65d9691902..c46681f556 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -60,44 +60,9 @@ LLPlacesInventoryPanel::~LLPlacesInventoryPanel() void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) { - // Determine the root folder in case specified, and - // build the views starting with that folder. - const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(params.start_folder); - - LLUUID root_id; - - if ("LIBRARY" == params.start_folder()) - { - root_id = gInventory.getLibraryRootFolderID(); - } - else - { - root_id = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null); - } - - LLRect folder_rect(0, - 0, - getRect().getWidth(), - 0); - LLPlacesFolderView::Params p; - p.name = getName(); - p.title = getLabel(); - p.rect = folder_rect; - p.listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, - LLAssetType::AT_CATEGORY, - LLInventoryType::IT_CATEGORY, - this, - &mInventoryViewModel, - NULL, - root_id); - p.parent_panel = this; - p.allow_multiselect = mAllowMultiSelect; - p.use_ellipses = true; // truncate inventory item text so remove horizontal scroller - p.view_model = &mInventoryViewModel; - mFolderRoot = LLUICtrlFactory::create<LLPlacesFolderView>(p); + LLInventoryPanel::buildFolderView(params); } - // save current folder open state void LLPlacesInventoryPanel::saveFolderState() { -- cgit v1.2.3 From efa73d4975afda19ee5255d5cca33fa96fc21eb4 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 19 Jul 2012 20:38:07 -0700 Subject: CHUI-236 : WIP : Places panel works for My Inventory but still empty lists for Favorites Bar, My Landmarks and Library. --- indra/newview/llinventorymodel.cpp | 37 ++++++++++++++++++------------------- indra/newview/llinventorypanel.cpp | 25 +++++++++++-------------- indra/newview/llinventorypanel.h | 1 - 3 files changed, 29 insertions(+), 34 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 3250d60179..9b0d12b353 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -210,7 +210,7 @@ const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(cons if (!cat) break; const LLFolderType::EType folder_type = cat->getPreferredType(); if (folder_type != LLFolderType::FT_NONE && -// folder_type != LLFolderType::FT_ROOT_INVENTORY && + folder_type != LLFolderType::FT_ROOT_INVENTORY && !LLFolderType::lookupIsEnsembleType(folder_type)) { return cat; @@ -380,12 +380,11 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe LLUUID rv = LLUUID::null; const LLUUID &root_id = (find_in_library) ? gInventory.getLibraryRootFolderID() : gInventory.getRootFolderID(); -// if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) -// { -// rv = root_id; -// } -// else if (root_id.notNull()) - if (root_id.notNull()) + if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) + { + rv = root_id; + } + else if (root_id.notNull()) { cat_array_t* cats = NULL; cats = get_ptr_in_map(mParentChildCategoryTree, root_id); @@ -2027,11 +2026,11 @@ void LLInventoryModel::buildParentChildMap() { cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); } -// else if(LLFolderType::FT_ROOT_INVENTORY == pref) -// { + else if(LLFolderType::FT_ROOT_INVENTORY == pref) + { // it's the root -// cat->setParent(LLUUID::null); -// } + cat->setParent(LLUUID::null); + } else { // it's a protected folder. @@ -2161,14 +2160,14 @@ void LLInventoryModel::buildParentChildMap() if(category && category->getPreferredType() != LLFolderType::FT_ROOT_INVENTORY) continue; -// if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) ) -// { -// if(category->getUUID()!=mRootFolderID) -// { -// LLUUID& new_inv_root_folder_id = const_cast<LLUUID&>(mRootFolderID); -// new_inv_root_folder_id = category->getUUID(); -// } -// } + if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) ) + { + if(category->getUUID()!=mRootFolderID) + { + LLUUID& new_inv_root_folder_id = const_cast<LLUUID&>(mRootFolderID); + new_inv_root_folder_id = category->getUUID(); + } + } } } diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index ed370e9add..340f851ed8 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -193,6 +193,15 @@ void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) { + // Clear up the root view + // Note: This needs to be done *before* we build the new folder view + LLFolderViewItem* root_view = getItemByID(gInventory.getRootFolderID()); + if (root_view) + { + removeItemID(static_cast<LLFolderViewModelItemInventory*>(root_view->getViewModelItem())->getUUID()); + root_view->destroyView(); + } + LLMemType mt(LLMemType::MTYPE_INVENTORY_POST_BUILD); mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves @@ -228,6 +237,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) { initializeViews(); } + gIdleCallbacks.addFunction(onIdle, (void*)this); if (mSortOrderSetting != INHERIT_SORT_ORDER) @@ -595,7 +605,7 @@ void LLInventoryPanel::initializeViews() { if (!gInventory.isInventoryUsable()) return; - rebuildViewsFor(gInventory.getRootFolderID()); + buildNewViews(gInventory.getRootFolderID()); gIdleCallbacks.addFunction(idle, this); @@ -622,19 +632,6 @@ void LLInventoryPanel::initializeViews() } } -LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id) -{ - // Destroy the old view for this ID so we can rebuild it. - LLFolderViewItem* old_view = getItemByID(id); - if (old_view) - { - old_view->destroyView(); - removeItemID(static_cast<LLFolderViewModelItemInventory*>(old_view->getViewModelItem())->getUUID()); - } - - return buildNewViews(id); -} - LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix) { LLRect folder_rect(0, diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 465ccdd582..4fcc93b0c4 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -237,7 +237,6 @@ public: protected: // Builds the UI. Call this once the inventory is usable. void initializeViews(); - LLFolderViewItem* rebuildViewsFor(const LLUUID& id); // Given the id and the parent, build all of the folder views. virtual void buildFolderView(const LLInventoryPanel::Params& params); LLFolderViewItem* buildNewViews(const LLUUID& id); -- cgit v1.2.3 From 6227a5c273efbe732c8068400d7e4b5486981bba Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 19 Jul 2012 19:16:36 +0300 Subject: CHUI-231, CHUI-233 [FIXED] - Modified and simplified algorithm of reshaping floater's body (content) and showing/hiding of the title for prevent of present and future issues with floater's repositioning --- indra/newview/llimconversation.cpp | 32 ++++++++-------------- indra/newview/llimconversation.h | 3 +- .../skins/default/xui/en/floater_im_session.xml | 2 +- 3 files changed, 13 insertions(+), 24 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index ec7e0ee6cb..ec534b903d 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -43,7 +43,6 @@ const F32 REFRESH_INTERVAL = 0.2f; LLIMConversation::LLIMConversation(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id) , mIsP2PChat(false) - , mWasHosted(false) , mExpandCollapseBtn(NULL) , mTearOffBtn(NULL) , mCloseBtn(NULL) @@ -224,26 +223,17 @@ void LLIMConversation::hideOrShowTitle() { bool is_hosted = getHost() != NULL; - if (mWasHosted != is_hosted) - { - mWasHosted = is_hosted; - LLView* floater_contents = getChild<LLView>("contents_view"); - LLRect contents_rect = floater_contents->getRect(); - - if (is_hosted) - { - // we don't show the header when the floater is hosted, so reshape floater contents - // to occupy the header space. - contents_rect.mTop += getHeaderHeight(); - } - else - { - // reduce the floater contents height by header height - contents_rect.mTop -= getHeaderHeight(); - } - - floater_contents->setShape(contents_rect); - } + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; + LLView* floater_contents = getChild<LLView>("contents_view"); + + LLRect floater_rect = getLocalRect(); + S32 top_border_of_contents = floater_rect.mTop - (is_hosted? 0 : floater_header_size); + LLRect handle_rect (0, floater_rect.mTop, floater_rect.mRight, top_border_of_contents); + LLRect contents_rect (0, top_border_of_contents, floater_rect.mRight, floater_rect.mBottom); + mDragHandle->setShape(handle_rect); + mDragHandle->setVisible(! is_hosted); + floater_contents->setShape(contents_rect); } void LLIMConversation::hideAllStandardButtons() diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index e6b4f534cc..c3dff96d5d 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -89,12 +89,11 @@ protected: void buildParticipantList(); void onSortMenuItemClicked(const LLSD& userdata); - void hideOrShowTitle(); + void hideOrShowTitle(); // toggle the floater's drag handle void hideAllStandardButtons(); bool mIsNearbyChat; bool mIsP2PChat; - bool mWasHosted; LLLayoutPanel* mParticipantListPanel; LLParticipantList* mParticipantList; diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 95f6708e96..560e1be213 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -9,7 +9,7 @@ can_dock="false" can_minimize="true" can_close="true" - save_rect="true" + save_rect="false" visible="false" width="394" can_resize="true" -- cgit v1.2.3 From 7c9be0e3de6821478c71e4646f07fb112e0e572c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 19 Jul 2012 15:11:56 +0300 Subject: CHUI-229 [FIXED] Nearby chat conversation does not appear initially in conversation list if no other conversations are present --- indra/newview/llimfloater.cpp | 8 +++--- indra/newview/llimfloatercontainer.cpp | 48 ++++++++++++++++++---------------- indra/newview/llimfloatercontainer.h | 1 + indra/newview/llnearbychat.cpp | 8 +++--- 4 files changed, 34 insertions(+), 31 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 23c97c5345..22ce3cd42b 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -346,6 +346,10 @@ BOOL LLIMFloater::postBuild() initIMFloater(); + // Add a conversation list item in the left pane + LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + im_box->addConversationListItem(getTitle(), getKey(), this); + return TRUE; } @@ -641,10 +645,6 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) } } - // Add a conversation list item in the left pane: nothing will be done if already in there - // but relevant clean up will be done to ensure consistency of the conversation list - floater_container->addConversationListItem(floater->getTitle(), session_id, floater); - floater->openFloater(floater->getKey()); } else diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 4f626cb5d2..005794444b 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -150,9 +150,6 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); LLUUID session_id = floaterp->getKey(); - - // Add a conversation list item in the left pane - addConversationListItem(floaterp->getTitle(), session_id, floaterp); LLIconCtrl* icon = 0; @@ -280,6 +277,8 @@ void LLIMFloaterContainer::draw() collapseMessagesPane(true); } LLFloater::draw(); + + repositioningWidgets(); } void LLIMFloaterContainer::tabClose() @@ -306,7 +305,7 @@ void LLIMFloaterContainer::setVisible(BOOL visible) LLFloaterReg::toggleInstanceOrBringToFront(name); } } - + // We need to show/hide all the associated conversations that have been torn off // (and therefore, are not longer managed by the multifloater), // so that they show/hide with the conversations manager. @@ -409,6 +408,23 @@ void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) } } +void LLIMFloaterContainer::repositioningWidgets() +{ + LLRect panel_rect = mConversationsListPanel->getRect(); + S32 item_height = 16; + int index = 0; + for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + widget_it != mConversationsWidgets.end(); + widget_it++, ++index) + { + LLFolderViewItem* widget = widget_it->second; + widget->setRect(LLRect(0, + panel_rect.getHeight() - item_height*index, + panel_rect.getWidth(), + panel_rect.getHeight() - item_height*(index+1))); + } +} + // CHUI-137 : Temporary implementation of conversations list void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp) { @@ -443,14 +459,11 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI // Add it to the UI widget->setVisible(TRUE); + + repositioningWidgets(); + mConversationsListPanel->addChild(widget); - LLRect panel_rect = mConversationsListPanel->getRect(); - S32 item_height = 16; - S32 index = mConversationsWidgets.size() - 1; - widget->setRect(LLRect(0, - panel_rect.getHeight() - item_height*index, - panel_rect.getWidth(), - panel_rect.getHeight() - item_height*(index+1))); + return; } @@ -470,18 +483,7 @@ void LLIMFloaterContainer::removeConversationListItem(LLFloater* floaterp, bool mConversationsItems.erase(floaterp); mConversationsWidgets.erase(floaterp); - // Reposition the leftover conversation items - LLRect panel_rect = mConversationsListPanel->getRect(); - S32 item_height = 16; - int index = 0; - for (widget_it = mConversationsWidgets.begin(); widget_it != mConversationsWidgets.end(); ++widget_it, ++index) - { - LLFolderViewItem* widget = widget_it->second; - widget->setRect(LLRect(0, - panel_rect.getHeight() - item_height*index, - panel_rect.getWidth(), - panel_rect.getHeight() - item_height*(index+1))); - } + repositioningWidgets(); // Don't let the focus fall IW, select and refocus on the first conversation in the list if (change_focus) diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index b624b7558a..a25ea0ab46 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -254,6 +254,7 @@ private: void collapseConversationsPane(bool collapse); void updateState(bool collapse, S32 delta_width); + void repositioningWidgets(); void onAddButtonClicked(); void onAvatarPicked(const uuid_vec_t& ids); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 1c81cdc4bc..a21690bed8 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -158,7 +158,7 @@ BOOL LLNearbyChat::postBuild() enableResizeCtrls(true, true, false); - // title must be defined BEFORE call addToHost() because + // title must be defined BEFORE call addConversationListItem() because // it is used for show the item's name in the conversations list setTitle(getString("NearbyChatTitle")); @@ -186,6 +186,9 @@ BOOL LLNearbyChat::postBuild() loadHistory(); } + // added row in the conversations list when nearby chat is tear-off + LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + im_box->addConversationListItem(getTitle(), LLSD(), this); return LLIMConversation::postBuild(); } @@ -363,9 +366,6 @@ void LLNearbyChat::addToHost() LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); if (im_box) { - // Make sure the Nearby Chat is present in the conversations list - im_box->addConversationListItem(getTitle(), getKey(), this); - if (gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) { im_box->addFloater(this, TRUE, LLTabContainer::END); -- cgit v1.2.3 From 3ae21b429e67faf4ee32c9387c63a552b883a472 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 20 Jul 2012 17:16:22 +0300 Subject: CHUI-207 FIXED Emptying Lost and Found and Trash in inventory crashes viewer --- indra/newview/llinventorymodel.cpp | 23 +++++++++++++++++++++-- indra/newview/llinventorypanel.cpp | 13 ++++++++++--- 2 files changed, 31 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 9b0d12b353..fe65b87afd 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1240,14 +1240,33 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) items, INCLUDE_TRASH); S32 count = items.count(); + + item_map_t::iterator item_map_end = mItemMap.end(); + cat_map_t::iterator cat_map_end = mCategoryMap.end(); + LLUUID uu_id; + for(S32 i = 0; i < count; ++i) { - deleteObject(items.get(i)->getUUID()); + uu_id = items.get(i)->getUUID(); + + // This check prevents the deletion of a previously deleted item. + // This is necessary because deletion is not done in a hierarchical + // order. The current item may have been already deleted as a child + // of its deleted parent. + if (mItemMap.find(uu_id) != item_map_end) + { + deleteObject(uu_id); + } } + count = categories.count(); for(S32 i = 0; i < count; ++i) { - deleteObject(categories.get(i)->getUUID()); + uu_id = categories.get(i)->getUUID(); + if (mCategoryMap.find(uu_id) != cat_map_end) + { + deleteObject(uu_id); + } } } } diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 340f851ed8..6a7ee3b6a0 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -421,7 +421,14 @@ void LLInventoryPanel::modelChanged(U32 mask) // LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item // to folder is the fast way to get a folder without searching through folders tree. - LLFolderViewFolder* view_folder = dynamic_cast<LLFolderViewFolder*>(view_item); + LLFolderViewFolder* view_folder = NULL; + + // Check requires as this item might have already been deleted + // as a child of its deleted parent. + if (model_item && view_item) + { + view_folder = dynamic_cast<LLFolderViewFolder*>(view_item); + } ////////////////////////////// // LABEL Operation @@ -448,7 +455,7 @@ void LLInventoryPanel::modelChanged(U32 mask) if (mask & LLInventoryObserver::REBUILD) { handled = true; - if (model_item && view_item) + if (model_item && view_item && viewmodel_item) { view_item->destroyView(); removeItemID(viewmodel_item->getUUID()); @@ -538,7 +545,7 @@ void LLInventoryPanel::modelChanged(U32 mask) ////////////////////////////// // REMOVE Operation // This item has been removed from memory, but its associated UI element still exists. - else if (!model_item && view_item) + else if (!model_item && view_item && viewmodel_item) { // Remove the item's UI. removeItemID(viewmodel_item->getUUID()); -- cgit v1.2.3 From 176b7d82be3b48344e2a54f81402352273719108 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Mon, 23 Jul 2012 19:33:39 -0700 Subject: CHUI-227 FIX Teleport offers sent are not received cleaned up serialization of LLSD to param block so that it can round-trip also, optimized LLXMLNode and fixed an assert --- indra/llui/llnotifications.cpp | 10 +---- indra/llui/llsdparam.cpp | 33 +++++----------- indra/llxml/llxmlnode.cpp | 87 +++++++++--------------------------------- indra/llxml/llxmlnode.h | 5 +-- indra/llxuixml/llinitparam.cpp | 5 --- indra/llxuixml/llinitparam.h | 31 ++++++++++++--- indra/llxuixml/llxuiparser.cpp | 12 +++++- 7 files changed, 66 insertions(+), 117 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 48128e0b40..7e1e2c3c9b 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -223,14 +223,6 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica LLParamSDParser parser; parser.writeSD(mFormData, p.form_elements); - if (!mFormData.isArray() && !mFormData.isUndefined()) - { - // change existing contents to a one element array - LLSD new_llsd_array = LLSD::emptyArray(); - new_llsd_array.append(mFormData); - mFormData = new_llsd_array; - } - for (LLSD::array_iterator it = mFormData.beginArray(), end_it = mFormData.endArray(); it != end_it; ++it) @@ -516,7 +508,7 @@ LLSD LLNotification::asLLSD() p.id = mId; p.name = mTemplatep->mName; p.form_elements = getForm()->asLLSD(); - + p.substitutions = mSubstitutions; p.payload = mPayload; p.time_stamp = mTimestamp; diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index 811e20e810..5a0d688f4f 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -223,10 +223,14 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser: { bool new_traversal = it->second; - LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first]; - - if (child_sd->isArray()) + LLSD* child_sd; + if (it->first.empty()) { + child_sd = sd_to_write; + if (child_sd->isUndefined()) + { + *child_sd = LLSD::emptyArray(); + } if (new_traversal) { // write to new element at end @@ -240,22 +244,7 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser: } else { - if (new_traversal - && child_sd->isDefined() - && !child_sd->isArray()) - { - // copy child contents into first element of an array - LLSD new_array = LLSD::emptyArray(); - new_array.append(*child_sd); - // assign array to slot that previously held the single value - *child_sd = new_array; - // return next element in that array - sd_to_write = &((*child_sd)[1]); - } - else - { - sd_to_write = child_sd; - } + sd_to_write = &(*sd_to_write)[it->first]; } it->second = false; } @@ -283,11 +272,9 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLI it != sd.endArray(); ++it) { - if (!stack.empty()) - { - stack.back().second = true; - } + stack.push_back(make_pair(std::string(), true)); readSDValues(cb, *it, stack); + stack.pop_back(); } } else if (sd.isUndefined()) diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 2ffb0d8503..45839595a0 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -259,7 +259,7 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child) return FALSE; } -void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child) +void LLXMLNode::addChild(LLXMLNodePtr& new_child) { if (new_child->mParent != NULL) { @@ -273,6 +273,11 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child) new_child->mParent = this; if (new_child->mIsAttribute) { + LLXMLAttribList::iterator found_it = mAttributes.find(new_child->mName); + if (found_it != mAttributes.end()) + { + removeChild(found_it->second); + } mAttributes.insert(std::make_pair(new_child->mName, new_child)); } else @@ -285,49 +290,11 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child) } mChildren->map.insert(std::make_pair(new_child->mName, new_child)); - // if after_child is specified, it damn well better be in the list of children - // for this node. I'm not going to assert that, because it would be expensive, - // but don't specify that parameter if you didn't get the value for it from the - // list of children of this node! - if (after_child.isNull()) - { - if (mChildren->tail != new_child) - { - mChildren->tail->mNext = new_child; - new_child->mPrev = mChildren->tail; - mChildren->tail = new_child; - } - } - // if after_child == parent, then put new_child at beginning - else if (after_child == this) - { - // add to front of list - new_child->mNext = mChildren->head; - if (mChildren->head) - { - mChildren->head->mPrev = new_child; - mChildren->head = new_child; - } - else // no children - { - mChildren->head = new_child; - mChildren->tail = new_child; - } - } - else + if (mChildren->tail != new_child) { - if (after_child->mNext.notNull()) - { - // if after_child was not the last item, fix up some pointers - after_child->mNext->mPrev = new_child; - new_child->mNext = after_child->mNext; - } - new_child->mPrev = after_child; - after_child->mNext = new_child; - if (mChildren->tail == after_child) - { - mChildren->tail = new_child; - } + mChildren->tail->mNext = new_child; + new_child->mPrev = mChildren->tail; + mChildren->tail = new_child; } } @@ -343,8 +310,9 @@ LLXMLNodePtr LLXMLNode::createChild(const char* name, BOOL is_attribute) // virtual LLXMLNodePtr LLXMLNode::createChild(LLStringTableEntry* name, BOOL is_attribute) { - LLXMLNode* ret = new LLXMLNode(name, is_attribute); + LLXMLNodePtr ret(new LLXMLNode(name, is_attribute)); ret->mID.clear(); + addChild(ret); return ret; } @@ -358,11 +326,12 @@ BOOL LLXMLNode::deleteChild(LLXMLNode *child) return FALSE; } -void LLXMLNode::setParent(LLXMLNodePtr new_parent) +void LLXMLNode::setParent(LLXMLNodePtr& new_parent) { if (new_parent.notNull()) { - new_parent->addChild(this); + LLXMLNodePtr this_ptr(this); + new_parent->addChild(this_ptr); } else { @@ -681,27 +650,6 @@ bool LLXMLNode::updateNode( return TRUE; } - -// static -LLXMLNodePtr LLXMLNode::replaceNode(LLXMLNodePtr node, LLXMLNodePtr update_node) -{ - if (!node || !update_node) - { - llwarns << "Node invalid" << llendl; - return node; - } - - LLXMLNodePtr cloned_node = update_node->deepCopy(); - node->mParent->addChild(cloned_node, node); // add after node - LLXMLNodePtr parent = node->mParent; - parent->removeChild(node); - parent->updateDefault(); - - return cloned_node; -} - - - // static bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXMLNode* defaults_tree) { @@ -1198,7 +1146,7 @@ void LLXMLNode::scrubToTree(LLXMLNode *tree) std::vector<LLXMLNodePtr>::iterator itor3; for (itor3=to_delete_list.begin(); itor3!=to_delete_list.end(); ++itor3) { - (*itor3)->setParent(NULL); + (*itor3)->setParent(LLXMLNodePtr()); } } } @@ -2733,7 +2681,8 @@ void LLXMLNode::setName(LLStringTableEntry* name) mName = name; if (old_parent) { - old_parent->addChild(this); + LLXMLNodePtr this_ptr(this); + old_parent->addChild(this_ptr); } } diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h index e3da7169e7..ec486d7957 100644 --- a/indra/llxml/llxmlnode.h +++ b/indra/llxml/llxmlnode.h @@ -127,8 +127,8 @@ public: BOOL isNull(); BOOL deleteChild(LLXMLNode* child); - void addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child = LLXMLNodePtr(NULL)); - void setParent(LLXMLNodePtr new_parent); // reparent if necessary + void addChild(LLXMLNodePtr& new_child); + void setParent(LLXMLNodePtr& new_parent); // reparent if necessary // Serialization static bool parseFile( @@ -147,7 +147,6 @@ public: static bool updateNode( LLXMLNodePtr& node, LLXMLNodePtr& update_node); - static LLXMLNodePtr replaceNode(LLXMLNodePtr node, LLXMLNodePtr replacement_node); static bool getLayeredXMLNode(LLXMLNodePtr& root, const std::vector<std::string>& paths); diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp index 3c0d0aaa7e..bb160b3c0b 100644 --- a/indra/llxuixml/llinitparam.cpp +++ b/indra/llxuixml/llinitparam.cpp @@ -227,12 +227,7 @@ namespace LLInitParam if (serialize_func) { const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; - // each param descriptor remembers its serial number - // so we can inspect the same param under different names - // and see that it has the same number - name_stack.push_back(std::make_pair("", true)); serialize_func(*param, parser, name_stack, diff_param); - name_stack.pop_back(); } } diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index d44ccac6e4..606676be2c 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -1317,10 +1317,18 @@ namespace LLInitParam static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) { + Parser::name_stack_range_t new_name_stack_range(name_stack_range); self_t& typed_param = static_cast<self_t&>(param); value_t value; + + // pop first element if empty string + if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty()) + { + ++new_name_stack_range.first; + } + // no further names in stack, attempt to parse value now - if (name_stack_range.first == name_stack_range.second) + if (new_name_stack_range.first == new_name_stack_range.second) { // attempt to read value directly if (parser.readValue(value)) @@ -1353,14 +1361,14 @@ namespace LLInitParam static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) { const self_t& typed_param = static_cast<const self_t&>(param); - if (!typed_param.isProvided() || name_stack.empty()) return; + if (!typed_param.isProvided()) return; for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); it != end_it; ++it) { std::string key = it->getValueName(); - name_stack.back().second = true; + name_stack.push_back(std::make_pair(std::string(), true)); if(key.empty()) // not parsed via name values, write out value directly @@ -1382,6 +1390,8 @@ namespace LLInitParam break; } } + + name_stack.pop_back(); } } @@ -1519,9 +1529,16 @@ namespace LLInitParam static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) { + Parser::name_stack_range_t new_name_stack_range(name_stack_range); self_t& typed_param = static_cast<self_t&>(param); bool new_value = false; + // pop first element if empty string + if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty()) + { + new_value |= new_name_stack_range.first->second; + ++new_name_stack_range.first; + } if (new_name || typed_param.mValues.empty()) { new_value = true; @@ -1531,7 +1548,7 @@ namespace LLInitParam param_value_t& value = typed_param.mValues.back(); // attempt to parse block... - if(value.deserializeBlock(parser, name_stack_range, new_name)) + if(value.deserializeBlock(parser, new_name_stack_range, new_name)) { typed_param.setProvided(); return true; @@ -1564,13 +1581,13 @@ namespace LLInitParam static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) { const self_t& typed_param = static_cast<const self_t&>(param); - if (!typed_param.isProvided() || name_stack.empty()) return; + if (!typed_param.isProvided()) return; for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); it != end_it; ++it) { - name_stack.back().second = true; + name_stack.push_back(std::make_pair(std::string(), true)); std::string key = it->getValueName(); if (!key.empty()) @@ -1583,6 +1600,8 @@ namespace LLInitParam { it->serializeBlock(parser, name_stack, NULL); } + + name_stack.pop_back(); } } diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index 9cd88a1620..3ad5ad7d42 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -621,7 +621,7 @@ void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& p nodep->createChild("schemaLocation", true)->setStringValue(widget_name + ".xsd"); // add to front of schema - mSchemaNode->addChild(nodep, mSchemaNode); + mSchemaNode->addChild(nodep); } for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems(); @@ -877,16 +877,24 @@ LLXMLNodePtr LLXUIParser::getNode(name_stack_t& stack) it = next_it) { ++next_it; + bool force_new_node = false; + if (it->first.empty()) { it->second = false; continue; } + if (next_it != stack.end() && next_it->first.empty() && next_it->second) + { + force_new_node = true; + } + + out_nodes_t::iterator found_it = mOutNodes.find(it->first); // node with this name not yet written - if (found_it == mOutNodes.end() || it->second) + if (found_it == mOutNodes.end() || it->second || force_new_node) { // make an attribute if we are the last element on the name stack bool is_attribute = next_it == stack.end(); -- cgit v1.2.3 From 0a28a63ce05755d22b09badc41bdd23d5baab1bb Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 24 Jul 2012 12:03:00 -0700 Subject: fix for gcc builds --- indra/llxml/llxmlnode.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 45839595a0..afb0d87da9 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -147,13 +147,15 @@ LLXMLNodePtr LLXMLNode::deepCopy() for (LLXMLChildList::iterator iter = mChildren->map.begin(); iter != mChildren->map.end(); ++iter) { - newnode->addChild(iter->second->deepCopy()); + LLXMLNodePtr temp_ptr_for_gcc(iter->second->deepCopy()); + newnode->addChild(temp_ptr_for_gcc); } } for (LLXMLAttribList::iterator iter = mAttributes.begin(); iter != mAttributes.end(); ++iter) { - newnode->addChild(iter->second->deepCopy()); + LLXMLNodePtr temp_ptr_for_gcc(iter->second->deepCopy()); + newnode->addChild(temp_ptr_for_gcc); } return newnode; @@ -1146,7 +1148,8 @@ void LLXMLNode::scrubToTree(LLXMLNode *tree) std::vector<LLXMLNodePtr>::iterator itor3; for (itor3=to_delete_list.begin(); itor3!=to_delete_list.end(); ++itor3) { - (*itor3)->setParent(LLXMLNodePtr()); + LLXMLNodePtr ptr; + (*itor3)->setParent(ptr); } } } -- cgit v1.2.3 From f303eeccf705f677e48c5738e5119352fd86b31d Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Tue, 24 Jul 2012 22:47:35 +0300 Subject: CHUI-209 FIX for properly updating folder names in folder view after they have been renamed. The old display name should be cleared before refreshing the views for both items and folders in folder view, otherwise the old name will be used upon renaming. --- indra/newview/llinventorybridge.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index b4a91ca0f7..9997d1720f 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -81,7 +81,7 @@ public: // LLInvFVBridge functionality //-------------------------------------------------------------------- virtual const LLUUID& getUUID() const { return mUUID; } - virtual void clearDisplayName() {} + virtual void clearDisplayName() { mDisplayName.clear(); } virtual void restoreItem() {} virtual void restoreToWorld() {} @@ -229,8 +229,6 @@ public: virtual bool hasChildren() const { return FALSE; } virtual BOOL isUpToDate() const { return TRUE; } - /*virtual*/ void clearDisplayName() { mDisplayName.clear(); } - LLViewerInventoryItem* getItem() const; protected: -- cgit v1.2.3 From decd8a435d8fb15bab52eec9e447b176e33eb5cf Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 24 Jul 2012 14:42:28 -0700 Subject: CHUI-211: Problem was due to a non-heap variable being deleted and then referenced later (which was found by ProductEngine). Also the crash occurred at a specifc location llpangelobjectinventory::reset() during a static_cast, so now using a dynamic_cast as a safeguard. --- indra/llui/llfolderview.cpp | 3 ++- indra/newview/llpanelobjectinventory.cpp | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 8ade17b763..10729a3eae 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -266,7 +266,8 @@ LLFolderView::~LLFolderView( void ) mItems.clear(); mFolders.clear(); - delete mViewModel; + //product engine bugfix, prevent deletion of non-heap data + //delete mViewModel; mViewModel = NULL; } diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index ca20051a51..937d3bb8c5 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1565,7 +1565,12 @@ void LLPanelObjectInventory::reset() mFolders = LLUICtrlFactory::create<LLFolderView>(p); // this ensures that we never say "searching..." or "no items found" //TODO RN: make this happen by manipulating filter object directly - static_cast<LLInventoryFilter*>(mFolders->getFolderViewModel()->getFilter())->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + LLInventoryFilter* inventoryFilter = dynamic_cast<LLInventoryFilter*>(mFolders->getFolderViewModel()->getFilter()); + if(inventoryFilter) + { + inventoryFilter->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + } + mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); if (hasFocus()) -- cgit v1.2.3 From 1736c7b74e5291b1fee91ae72ff52391ae7d946f Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 24 Jul 2012 15:19:18 -0700 Subject: Backed out changeset: a20e437a726c --- indra/newview/llfolderviewmodelinventory.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index dff1e1be90..d23b4af8cb 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -158,20 +158,22 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite if (item->getLastFilterGeneration() < filter_generation) { - // recursive application of the filter for child items - item->filter( filter ); - if (item->getLastFilterGeneration() >= must_pass_generation && !item->passedFilter(must_pass_generation)) { // failed to pass an earlier filter that was a subset of the current one // go ahead and flag this item as done + item->filter(filter); if (item->passedFilter()) { llerrs << "Invalid shortcut in inventory filtering!" << llendl; } item->setPassedFilter(false, false, filter_generation); } + else + { + item->filter( filter ); + } } // track latest generation to pass any child items, for each folder up to root -- cgit v1.2.3 From 891a09561d4dff23836c8618d481a6cd2dd001de Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Tue, 24 Jul 2012 20:29:20 -0700 Subject: CHUI-206 FIX Viewer crash when selecting to cut inventory item, then selecting to cut another inventory item Seems to work now, without filtering de-optimization --- indra/llui/llfolderview.cpp | 2 +- indra/newview/llfolderviewmodelinventory.cpp | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 8ade17b763..943e690948 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1123,7 +1123,7 @@ void LLFolderView::paste() LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(item); if (folder == NULL) { - item = item->getParentFolder(); + folder = item->getParentFolder(); } folder_set.insert(folder); } diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index d23b4af8cb..faf5b3e7ac 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -163,11 +163,6 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite { // failed to pass an earlier filter that was a subset of the current one // go ahead and flag this item as done - item->filter(filter); - if (item->passedFilter()) - { - llerrs << "Invalid shortcut in inventory filtering!" << llendl; - } item->setPassedFilter(false, false, filter_generation); } else -- cgit v1.2.3 From de8cd534b985450f6d9ff9d2ad947a2a110f76a8 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 25 Jul 2012 16:16:06 +0300 Subject: CHUI-230 [FIXED] Torn off conversation window size resizes when viewer window is resized --- indra/newview/llnearbychat.cpp | 10 ---------- indra/newview/skins/default/xui/en/floater_im_session.xml | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a21690bed8..4e53082c05 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -391,17 +391,7 @@ void LLNearbyChat::onOpen(const LLSD& key) bool LLNearbyChat::applyRectControl() { - bool is_torn_off = getHost() == NULL; - - // Resize is limited to torn off floaters. - // A hosted floater is not resizable. - if (is_torn_off) - { - enableResizeCtrls(true); - } - setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); - return LLFloater::applyRectControl(); } diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 560e1be213..95f6708e96 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -9,7 +9,7 @@ can_dock="false" can_minimize="true" can_close="true" - save_rect="false" + save_rect="true" visible="false" width="394" can_resize="true" -- cgit v1.2.3 From c4f59fd5882d8b019830292e9e5ed1d2480f73ef Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 25 Jul 2012 14:30:17 -0700 Subject: CHUI-239 FIX Viewer crash when opening object with contents --- indra/newview/llfloatertools.cpp | 4 ++-- indra/newview/llfolderviewmodelinventory.cpp | 10 +++++----- indra/newview/llfolderviewmodelinventory.h | 10 +++------- indra/newview/llinventorybridge.cpp | 5 ++--- indra/newview/llinventorypanel.h | 1 + indra/newview/llpanelobjectinventory.cpp | 8 ++++++-- indra/newview/llpanelobjectinventory.h | 2 ++ indra/newview/llplacesinventorybridge.cpp | 2 -- 8 files changed, 21 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 6978e6a430..43465d4209 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -660,8 +660,8 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) mBtnEdit ->setToggleState( edit_visible ); mRadioGroupEdit->setVisible( edit_visible ); - bool linked_parts = gSavedSettings.getBOOL("EditLinkedParts"); - getChildView("RenderingCost")->setVisible( !linked_parts && (edit_visible || focus_visible || move_visible) && sShowObjectCost); + //bool linked_parts = gSavedSettings.getBOOL("EditLinkedParts"); + //getChildView("RenderingCost")->setVisible( !linked_parts && (edit_visible || focus_visible || move_visible) && sShowObjectCost); mBtnLink->setVisible(edit_visible); mBtnUnlink->setVisible(edit_visible); diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index dff1e1be90..e8135496d5 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -109,7 +109,7 @@ bool LLFolderViewModelInventory::contentsReady() void LLFolderViewModelItemInventory::requestSort() { LLFolderViewModelItemCommon::requestSort(); - if (mRootViewModel->getSorter().isByDate()) + if (mRootViewModel.getSorter().isByDate()) { // sort by date potentially affects parent folders which use a date // derived from newest item in them @@ -123,14 +123,14 @@ void LLFolderViewModelItemInventory::requestSort() bool LLFolderViewModelItemInventory::potentiallyVisible() { return passedFilter() // we've passed the filter - || getLastFilterGeneration() < mRootViewModel->getFilter()->getFirstSuccessGeneration() // or we don't know yet + || getLastFilterGeneration() < mRootViewModel.getFilter()->getFirstSuccessGeneration() // or we don't know yet || descendantsPassedFilter(); } bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) { - if (filter_generation < 0 && mRootViewModel) - filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); + if (filter_generation < 0) + filter_generation = mRootViewModel.getFilter()->getFirstSuccessGeneration(); return mPassedFolderFilter && mLastFilterGeneration >= filter_generation @@ -139,7 +139,7 @@ bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) { - if (filter_generation < 0) filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); + if (filter_generation < 0) filter_generation = mRootViewModel.getFilter()->getFirstSuccessGeneration(); return mMostFilteredDescendantGeneration >= filter_generation; } diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index 12a977b28b..eb2a4bfdec 100644 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -37,13 +37,9 @@ class LLFolderViewModelItemInventory : public LLFolderViewModelItemCommon { public: - LLFolderViewModelItemInventory() - : mRootViewModel(NULL) + LLFolderViewModelItemInventory(class LLFolderViewModelInventory& root_view_model) + : mRootViewModel(root_view_model) {} - void setRootViewModel(class LLFolderViewModelInventory* root_view_model) - { - mRootViewModel = root_view_model; - } virtual const LLUUID& getUUID() const = 0; virtual time_t getCreationDate() const = 0; // UTC seconds virtual void setCreationDate(time_t creation_date_utc) = 0; @@ -70,7 +66,7 @@ public: virtual LLToolDragAndDrop::ESource getDragSource() const = 0; protected: - class LLFolderViewModelInventory* mRootViewModel; + class LLFolderViewModelInventory& mRootViewModel; }; class LLInventorySort diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index d17c25d9f3..9f1d4bdec9 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -190,7 +190,8 @@ LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, mUUID(uuid), mRoot(root), mInvType(LLInventoryType::IT_NONE), - mIsLink(FALSE) + mIsLink(FALSE), + LLFolderViewModelItemInventory(inventory->getRootViewModel()) { mInventoryPanel = inventory->getInventoryPanelHandle(); const LLInventoryObject* obj = getInventoryObject(); @@ -1158,7 +1159,6 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, if (new_listener) { new_listener->mInvType = inv_type; - new_listener->setRootViewModel(view_model); } return new_listener; @@ -6484,7 +6484,6 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( && actual_asset_type != LLAssetType::AT_LINK_FOLDER) { new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid); - new_listener->setRootViewModel(view_model); } else { diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 4fcc93b0c4..910325cdbc 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -104,6 +104,7 @@ public: public: LLInventoryModel* getModel() { return mInventory; } + LLFolderViewModelInventory& getRootViewModel() { return mInventoryViewModel; } // LLView methods void draw(); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 937d3bb8c5..9bd716e900 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -155,7 +155,8 @@ LLTaskInvFVBridge::LLTaskInvFVBridge( LLPanelObjectInventory* panel, const LLUUID& uuid, const std::string& name, - U32 flags): + U32 flags) +: LLFolderViewModelItemInventory(panel->getRootViewModel()), mUUID(uuid), mName(name), mPanel(panel), @@ -1915,7 +1916,10 @@ void LLPanelObjectInventory::idle(void* user_data) { LLPanelObjectInventory* self = (LLPanelObjectInventory*)user_data; - + if (self->mFolders) + { + self->mFolders->update(); + } if (self->mInventoryNeedsUpdate) { self->updateInventory(); diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 7e857f8b31..593fb43b6d 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -56,6 +56,8 @@ public: virtual BOOL postBuild(); + LLFolderViewModelInventory& getRootViewModel() { return mInventoryViewModel; } + void doToSelected(const LLSD& userdata); void refresh(); diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index af29ab7ea9..1a5f64e295 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -165,7 +165,6 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; } new_listener = new LLPlacesLandmarkBridge(inv_type, inventory, root, uuid, flags); - new_listener->setRootViewModel(view_model); break; case LLAssetType::AT_CATEGORY: if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) @@ -183,7 +182,6 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( break; } new_listener = new LLPlacesFolderBridge(inv_type, inventory, root, uuid); - new_listener->setRootViewModel(view_model); break; default: new_listener = LLInventoryFVBridgeBuilder::createBridge( -- cgit v1.2.3 From f6dfd6bf0f3ea0e9b5f56a939867353c393539d6 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 25 Jul 2012 18:20:54 -0700 Subject: CHUI-222 FIX Selecting None in inventory filters does not update until inventory selected --- indra/llui/llfolderview.cpp | 2 - indra/llui/llfolderviewitem.cpp | 11 +++-- indra/llui/llfolderviewmodel.h | 4 +- indra/newview/llfolderviewmodelinventory.cpp | 74 +++++++++++++--------------- indra/newview/llfolderviewmodelinventory.h | 4 +- indra/newview/llimfloatercontainer.h | 2 +- indra/newview/llpanelobjectinventory.cpp | 2 +- 7 files changed, 49 insertions(+), 50 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 10729a3eae..147af04f30 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -266,8 +266,6 @@ LLFolderView::~LLFolderView( void ) mItems.clear(); mFolders.clear(); - //product engine bugfix, prevent deletion of non-heap data - //delete mViewModel; mViewModel = NULL; } diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 741fc9c324..a356d587f9 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1543,11 +1543,14 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) void LLFolderViewFolder::requestArrange() { - mLastArrangeGeneration = -1; - // flag all items up to root - if (mParentFolder) + //if ( mLastArrangeGeneration != -1) { - mParentFolder->requestArrange(); + mLastArrangeGeneration = -1; + // flag all items up to root + if (mParentFolder) + { + mParentFolder->requestArrange(); + } } } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 268ae8eea8..acdec53602 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -152,7 +152,7 @@ public: virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? - virtual bool filter( LLFolderViewFilter& filter) = 0; + virtual void filter( LLFolderViewFilter& filter) = 0; virtual bool passedFilter(S32 filter_generation = -1) = 0; virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) = 0; @@ -192,6 +192,7 @@ public: : mSortVersion(-1), mPassedFilter(true), mPassedFolderFilter(true), + mPrevPassedAllFilters(false), mFolderViewItem(NULL), mLastFilterGeneration(-1), mMostFilteredDescendantGeneration(-1), @@ -232,6 +233,7 @@ protected: S32 mSortVersion; bool mPassedFilter; bool mPassedFolderFilter; + bool mPrevPassedAllFilters; S32 mLastFilterGeneration; S32 mMostFilteredDescendantGeneration; diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index e8135496d5..13ca73917b 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -133,8 +133,9 @@ bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) filter_generation = mRootViewModel.getFilter()->getFirstSuccessGeneration(); return mPassedFolderFilter - && mLastFilterGeneration >= filter_generation - && (mPassedFilter || descendantsPassedFilter(filter_generation)); + && (descendantsPassedFilter(filter_generation) + || (mLastFilterGeneration >= filter_generation + && mPassedFilter)); } bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) @@ -148,30 +149,29 @@ void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_fo mPassedFilter = passed; mPassedFolderFilter = passed_folder; mLastFilterGeneration = filter_generation; + + bool passed_filter_before = mPrevPassedAllFilters; + mPrevPassedAllFilters = passedFilter(filter_generation); + + if (passed_filter_before != mPrevPassedAllFilters) + { + //TODO RN: ensure this still happens, but without dependency on folderview + LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder(); + if (parent_folder) + { + parent_folder->requestArrange(); + } + } } -bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) +void LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) { - bool passed_filter_before = item->passedFilter(); S32 filter_generation = filter.getCurrentGeneration(); - S32 must_pass_generation = filter.getFirstRequiredGeneration(); if (item->getLastFilterGeneration() < filter_generation) { // recursive application of the filter for child items item->filter( filter ); - - if (item->getLastFilterGeneration() >= must_pass_generation - && !item->passedFilter(must_pass_generation)) - { - // failed to pass an earlier filter that was a subset of the current one - // go ahead and flag this item as done - if (item->passedFilter()) - { - llerrs << "Invalid shortcut in inventory filtering!" << llendl; - } - item->setPassedFilter(false, false, filter_generation); - } } // track latest generation to pass any child items, for each folder up to root @@ -184,39 +184,36 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite view_model->mMostFilteredDescendantGeneration = filter_generation; view_model = static_cast<LLFolderViewModelItemInventory*>(view_model->mParent); } - - return !passed_filter_before; - } - else // !item->passedfilter() - { - return passed_filter_before; } } -bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) +void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) { - bool changed = false; + const S32 filter_generation = filter.getCurrentGeneration(); + const S32 must_pass_generation = filter.getFirstRequiredGeneration(); + + if (getLastFilterGeneration() >= must_pass_generation + && !passedFilter(must_pass_generation)) + { + // failed to pass an earlier filter that was a subset of the current one + // go ahead and flag this item as done + setPassedFilter(false, false, filter_generation); + return; + } if(!mChildren.empty() - && (getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass - || descendantsPassedFilter(filter.getFirstRequiredGeneration()))) // or at least one descendant has passed the minimum requirement + && (getLastFilterGeneration() < must_pass_generation // haven't checked descendants against minimum required generation to pass + || descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement { // now query children - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end() && filter.getFilterCount() > 0; + for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end(); + iter != end_iter && filter.getFilterCount() > 0; ++iter) { - changed |= filterChildItem((*iter), filter); + filterChildItem((*iter), filter); } } - if (changed) - { - //TODO RN: ensure this still happens, but without dependency on folderview - LLFolderViewFolder* folder = static_cast<LLFolderViewFolder*>(mFolderViewItem); - folder->requestArrange(); - } - // if we didn't use all filter iterations // that means we filtered all of our descendants // so filter ourselves now @@ -229,11 +226,10 @@ bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) ? filter.checkFolder(this) : true; - setPassedFilter(passed_filter, passed_filter_folder, filter.getCurrentGeneration()); + setPassedFilter(passed_filter, passed_filter_folder, filter_generation); //TODO RN: create interface for string highlighting //mStringMatchOffset = filter.getStringMatchOffset(this); } - return changed; } LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index eb2a4bfdec..ab67c93897 100644 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -59,8 +59,8 @@ public: virtual bool passedFilter(S32 filter_generation = -1); virtual bool descendantsPassedFilter(S32 filter_generation = -1); virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); - virtual bool filter( LLFolderViewFilter& filter); - virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); + virtual void filter( LLFolderViewFilter& filter); + virtual void filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; virtual LLToolDragAndDrop::ESource getDragSource() const = 0; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index a25ea0ab46..7005ab7b6a 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -89,7 +89,7 @@ public: virtual bool hasChildren() const { return FALSE; } virtual bool potentiallyVisible() { return true; } - virtual bool filter( LLFolderViewFilter& filter) { return true; } + virtual void filter( LLFolderViewFilter& filter) { } virtual bool descendantsPassedFilter(S32 filter_generation = -1) { return true; } virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) { } virtual bool passedFilter(S32 filter_generation = -1) { return true; } diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 9bd716e900..4719191231 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1616,7 +1616,7 @@ void LLPanelObjectInventory::inventoryChanged(LLViewerObject* object, iter != inventory->end(); ) { LLInventoryObject* item = *iter++; - LLFloaterProperties* floater = LLFloaterReg::findTypedInstance<LLFloaterProperties>("properites", item->getUUID()); + LLFloaterProperties* floater = LLFloaterReg::findTypedInstance<LLFloaterProperties>("properties", item->getUUID()); if(floater) { floater->refresh(); -- cgit v1.2.3 From 69b57d4ac075db855d88c2ff0e8c580e9e41ebf7 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 25 Jul 2012 19:54:39 -0700 Subject: CHUI-252 FIX Deleting an item from object contents in build tools crashes viewer also improved selection behavior for object contents when deleting/adding items --- indra/llui/llhandle.h | 13 +++---- indra/newview/llpanelobjectinventory.cpp | 64 ++++++++++++++++++++++++++------ indra/newview/llpanelobjectinventory.h | 7 ++++ 3 files changed, 66 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/llui/llhandle.h b/indra/llui/llhandle.h index 37c657dd92..680a1a7f1d 100644 --- a/indra/llui/llhandle.h +++ b/indra/llui/llhandle.h @@ -158,13 +158,6 @@ public: return mHandle; } -protected: - typedef LLHandle<T> handle_type_t; - LLHandleProvider() - { - // provided here to enforce T deriving from LLHandleProvider<T> - } - template <typename U> LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const { @@ -173,6 +166,12 @@ protected: return downcast_handle; } +protected: + typedef LLHandle<T> handle_type_t; + LLHandleProvider() + { + // provided here to enforce T deriving from LLHandleProvider<T> + } private: mutable LLRootHandle<T> mHandle; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 4719191231..473b5d9479 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1535,6 +1535,8 @@ void LLPanelObjectInventory::clearContents() LLToolDragAndDrop::getInstance()->endDrag(); } + clearItemIDs(); + if( mScroller ) { // removes mFolders @@ -1550,8 +1552,6 @@ void LLPanelObjectInventory::reset() { clearContents(); - //setBorderVisible(FALSE); - mCommitCallbackRegistrar.pushScope(); // push local callbacks LLRect dummy_rect(0, 1, 1, 0); @@ -1631,15 +1631,20 @@ void LLPanelObjectInventory::updateInventory() // << " panel UUID: " << panel->mTaskUUID << "\n" // << " task UUID: " << object->mID << llendl; // We're still interested in this task's inventory. + std::vector<LLUUID> selected_item_ids; std::set<LLFolderViewItem*> selected_items; BOOL inventory_has_focus = FALSE; - if (mHaveInventory) + if (mHaveInventory && mFolders) { selected_items = mFolders->getSelectionList(); inventory_has_focus = gFocusMgr.childHasKeyboardFocus(mFolders); } - - reset(); + for (std::set<LLFolderViewItem*>::iterator it = selected_items.begin(), end_it = selected_items.end(); + it != end_it; + ++it) + { + selected_item_ids.push_back(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); + } LLViewerObject* objectp = gObjectList.findObject(mTaskUUID); if (objectp) @@ -1647,10 +1652,11 @@ void LLPanelObjectInventory::updateInventory() LLInventoryObject* inventory_root = objectp->getInventoryRoot(); LLInventoryObject::object_list_t contents; objectp->getInventoryContents(contents); - mHaveInventory = TRUE; if (inventory_root && !contents.empty()) { + reset(); + createFolderViews(inventory_root, contents); mIsInventoryEmpty = FALSE; mFolders->setEnabled(TRUE); @@ -1660,6 +1666,8 @@ void LLPanelObjectInventory::updateInventory() // TODO: create an empty inventory mIsInventoryEmpty = TRUE; } + + mHaveInventory = TRUE; } else { @@ -1669,11 +1677,12 @@ void LLPanelObjectInventory::updateInventory() } // restore previous selection - std::set<LLFolderViewItem*>::iterator selection_it; - BOOL first_item = TRUE; - for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it) + std::vector<LLUUID>::iterator selection_it; + bool first_item = true; + for (selection_it = selected_item_ids.begin(); selection_it != selected_item_ids.end(); ++selection_it) { - LLFolderViewItem* selected_item = (*selection_it); + LLFolderViewItem* selected_item = getItemByID(*selection_it); + if (selected_item) { //HACK: "set" first item then "change" each other one to get keyboard focus right @@ -1689,7 +1698,10 @@ void LLPanelObjectInventory::updateInventory() } } - mFolders->requestArrange(); + if (mFolders) + { + mFolders->requestArrange(); + } mInventoryNeedsUpdate = FALSE; // Edit menu handler is set in onFocusReceived } @@ -1761,6 +1773,7 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li view = LLUICtrlFactory::create<LLFolderViewItem> (params); } view->addToFolder(folder); + addItemID(obj->getUUID(), view); } } @@ -1944,3 +1957,32 @@ void LLPanelObjectInventory::onFocusReceived() LLPanel::onFocusReceived(); } + + +LLFolderViewItem* LLPanelObjectInventory::getItemByID( const LLUUID& id ) +{ + std::map<LLUUID, LLFolderViewItem*>::iterator map_it; + map_it = mItemMap.find(id); + if (map_it != mItemMap.end()) + { + return map_it->second; + } + + return NULL; +} + +void LLPanelObjectInventory::removeItemID( const LLUUID& id ) +{ + mItemMap.erase(id); +} + +void LLPanelObjectInventory::addItemID( const LLUUID& id, LLFolderViewItem* itemp ) +{ + mItemMap[id] = itemp; +} + +void LLPanelObjectInventory::clearItemIDs() +{ + mItemMap.clear(); +} + diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 593fb43b6d..f497c695b3 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -88,8 +88,15 @@ protected: LLInventoryObject* parent, LLFolderViewFolder* folder); void clearContents(); + LLFolderViewItem* getItemByID(const LLUUID& id); + + void addItemID( const LLUUID& id, LLFolderViewItem* itemp ); + void removeItemID(const LLUUID& id); + void clearItemIDs(); private: + std::map<LLUUID, LLFolderViewItem*> mItemMap; + LLScrollContainer* mScroller; LLFolderView* mFolders; -- cgit v1.2.3 From 88f259f7c1aefea197ae8b6c49a79de09feebf5b Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 25 Jul 2012 20:08:17 -0700 Subject: optimization of LLSD param parsing --- indra/llui/llsdparam.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index 5a0d688f4f..54c8389772 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -305,6 +305,12 @@ namespace LLInitParam // block param interface bool ParamValue<LLSD, NOT_BLOCK>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) { + if (name_stack.first == name_stack.second + && p.readValue<LLSD>(mValue)) + { + return true; + } + LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack); LLSD::String string; @@ -325,7 +331,11 @@ namespace LLInitParam void ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const { - // read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) - LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack); + // attempt to write LLSD out directly + if (!p.writeValue<LLSD>(mValue, name_stack)) + { + // otherwise read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) + LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack); + } } } -- cgit v1.2.3 From 779d982717098e608285b171ac06f5b9f43a94a0 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 26 Jul 2012 16:30:27 -0700 Subject: made Deprecated params write-only --- indra/llxuixml/llinitparam.h | 36 ++++++++++++++++++++++++++++++++---- indra/newview/llinventoryfilter.cpp | 2 +- 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 606676be2c..71cd550693 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -2015,10 +2015,12 @@ namespace LLInitParam } }; - class Deprecated : public Param + // can appear in data files, but will ignored during parsing + // cannot read or write in code + class Ignored : public Param { public: - explicit Deprecated(const char* name) + explicit Ignored(const char* name) : Param(DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr) { BlockDescriptor& block_descriptor = DERIVED_BLOCK::getBlockDescriptor(); @@ -2049,8 +2051,34 @@ namespace LLInitParam } }; - // different semantics for documentation purposes, but functionally identical - typedef Deprecated Ignored; + // can appear in data files, or be written to in code, but data will be ignored + // cannot be read in code + class Deprecated : public Ignored + { + public: + explicit Deprecated(const char* name) : Ignored(name) {} + + // dummy writer interfaces + template<typename T> + Deprecated& operator =(const T& val) + { + // do nothing + return *this; + } + + template<typename T> + DERIVED_BLOCK& operator()(const T& val) + { + // do nothing + return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); + } + + template<typename T> + void set(const T& val, bool flag_as_provided = true) + { + // do nothing + } + }; public: static BlockDescriptor& getBlockDescriptor() diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 3f38d80a39..3e14faa55e 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -89,7 +89,7 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item) const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE); // If it's a folder and we're showing all folders, return automatically. - const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY;; + const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY; if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)) { return passed_clipboard; -- cgit v1.2.3 From 5221e48ef64d3965f6d4d3dbf0f937982230d11c Mon Sep 17 00:00:00 2001 From: Todd Stinson <stinson@lindenlab.com> Date: Thu, 26 Jul 2012 17:26:27 -0700 Subject: CHUI-251: Resetting the object inventory panel after deleting the last object. --- indra/newview/llpanelobjectinventory.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 473b5d9479..fe1ff01bc2 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1653,13 +1653,16 @@ void LLPanelObjectInventory::updateInventory() LLInventoryObject::object_list_t contents; objectp->getInventoryContents(contents); - if (inventory_root && !contents.empty()) + if (inventory_root) { reset(); + mIsInventoryEmpty = contents.empty(); + if (!mIsInventoryEmpty) + { - createFolderViews(inventory_root, contents); - mIsInventoryEmpty = FALSE; - mFolders->setEnabled(TRUE); + createFolderViews(inventory_root, contents); + mFolders->setEnabled(TRUE); + } } else { -- cgit v1.2.3 From 1e65ba1f909604b027cb7dee5631f698a9f550a8 Mon Sep 17 00:00:00 2001 From: Todd Stinson <stinson@lindenlab.com> Date: Thu, 26 Jul 2012 18:57:54 -0700 Subject: CHUI-251: Adding back in the root 'Contents' folder under the Build floater Content tab. --- indra/newview/llpanelobjectinventory.cpp | 25 +++++++++++++++++-------- indra/newview/skins/default/xui/en/strings.xml | 3 --- 2 files changed, 17 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index fe1ff01bc2..5887f4d244 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1656,13 +1656,9 @@ void LLPanelObjectInventory::updateInventory() if (inventory_root) { reset(); - mIsInventoryEmpty = contents.empty(); - if (!mIsInventoryEmpty) - { - - createFolderViews(inventory_root, contents); - mFolders->setEnabled(TRUE); - } + mIsInventoryEmpty = FALSE; + createFolderViews(inventory_root, contents); + mFolders->setEnabled(TRUE); } else { @@ -1725,7 +1721,20 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root bridge = LLTaskInvFVBridge::createObjectBridge(this, inventory_root); if(bridge) { - createViewsForCategory(&contents, inventory_root, mFolders); + LLFolderViewFolder::Params p; + p.name = inventory_root->getName(); + p.tool_tip = p.name; + p.root = mFolders; + p.listener = bridge; + + LLFolderViewFolder* new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); + new_folder->addToFolder(mFolders); + new_folder->toggleOpen(); + + if (!contents.empty()) + { + createViewsForCategory(&contents, inventory_root, new_folder); + } } } diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 7790a382d9..fff892af68 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2447,9 +2447,6 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale <string name="GroupMoneyDebits">Debits</string> <string name="GroupMoneyDate">[weekday,datetime,utc] [mth,datetime,utc] [day,datetime,utc], [year,datetime,utc]</string> - <!-- viewer object --> - <string name="ViewerObjectContents">Contents</string> - <!-- Viewer menu --> <string name="AcquiredItems">Acquired Items</string> <string name="Cancel">Cancel</string> -- cgit v1.2.3 From e9f640a26fd6c9219ba28336231621e2ad2558fc Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 27 Jul 2012 17:36:41 +0300 Subject: CHUI-198 FIXED (Hitting minimize option on conversations floater closes floater, not minimize) - Removed code which was hiding floater on minimizing floater. --- indra/newview/llimfloatercontainer.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 005794444b..c19683b1c2 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -257,8 +257,6 @@ void LLIMFloaterContainer::setMinimized(BOOL b) if (isMinimized() == b) return; LLMultiFloater::setMinimized(b); - // Hide minimized floater (see EXT-5315) - setVisible(!b); if (isMinimized()) return; -- cgit v1.2.3 From f82d0b171964a0b24ab0eca64febc0c1e3821138 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 27 Jul 2012 17:51:40 +0300 Subject: CHUI-204 FIXED (Conversations panel can be re-sized too small with all conversations torn off) - Increased min width of conversations panel by 10 pixels --- indra/newview/skins/default/xui/en/floater_im_container.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 8e434b5848..e5ef80e352 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -33,7 +33,7 @@ auto_resize="true" height="430" name="conversations_layout_panel" - min_dim="41" + min_dim="51" width="268"> <layout_stack animate="false" -- cgit v1.2.3 From 0ee0a5eff41a3763b1fc3fc45a36f87fc6eedac5 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 27 Jul 2012 22:25:17 +0300 Subject: CHUI-151 FIXED (Implement conversation log) A brief explanation of what have been implemented. More information can be found in comments. 1. Created conversation history viewer (llfloaterconversationpreview) 2. Created LLConversation and LLConversationLog classes which represent and hold data of conversations (llconversationlog) 3. Created LLConversationLogList and LLConversationLogListItem which are the visual representation of LLConversationLog and LLConversation respectively 4. Created LLFloaterConversationLog - which holds and displays LLConversationLogList --- indra/newview/CMakeLists.txt | 10 + indra/newview/app_settings/settings.xml | 22 ++ indra/newview/llappviewer.cpp | 4 + indra/newview/llconversationlog.cpp | 336 ++++++++++++++++ indra/newview/llconversationlog.h | 164 ++++++++ indra/newview/llconversationloglist.cpp | 422 +++++++++++++++++++++ indra/newview/llconversationloglist.h | 143 +++++++ indra/newview/llconversationloglistitem.cpp | 157 ++++++++ indra/newview/llconversationloglistitem.h | 77 ++++ indra/newview/llfloaterconversationlog.cpp | 127 +++++++ indra/newview/llfloaterconversationlog.h | 61 +++ indra/newview/llfloaterconversationpreview.cpp | 112 ++++++ indra/newview/llfloaterconversationpreview.h | 51 +++ indra/newview/llimfloater.cpp | 12 + indra/newview/llimfloater.h | 6 + indra/newview/llimview.cpp | 17 +- indra/newview/llimview.h | 10 +- indra/newview/llstartup.cpp | 3 + indra/newview/llviewerfloaterreg.cpp | 4 + indra/newview/llviewermessage.cpp | 5 +- indra/newview/llvoicevivox.cpp | 1 + .../default/xui/en/floater_conversation_log.xml | 84 ++++ .../xui/en/floater_conversation_preview.xml | 53 +++ .../skins/default/xui/en/floater_im_container.xml | 1 + .../default/xui/en/menu_conversation_log_gear.xml | 134 +++++++ .../default/xui/en/menu_conversation_log_view.xml | 37 ++ .../skins/default/xui/en/menu_participant_view.xml | 16 + .../xui/en/panel_conversation_log_list_item.xml | 108 ++++++ 28 files changed, 2167 insertions(+), 10 deletions(-) create mode 100644 indra/newview/llconversationlog.cpp create mode 100644 indra/newview/llconversationlog.h create mode 100644 indra/newview/llconversationloglist.cpp create mode 100644 indra/newview/llconversationloglist.h create mode 100644 indra/newview/llconversationloglistitem.cpp create mode 100644 indra/newview/llconversationloglistitem.h create mode 100644 indra/newview/llfloaterconversationlog.cpp create mode 100644 indra/newview/llfloaterconversationlog.h create mode 100644 indra/newview/llfloaterconversationpreview.cpp create mode 100644 indra/newview/llfloaterconversationpreview.h create mode 100644 indra/newview/skins/default/xui/en/floater_conversation_log.xml create mode 100644 indra/newview/skins/default/xui/en/floater_conversation_preview.xml create mode 100644 indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml create mode 100644 indra/newview/skins/default/xui/en/menu_conversation_log_view.xml create mode 100644 indra/newview/skins/default/xui/en/menu_participant_view.xml create mode 100644 indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b31b99f47c..3fe1aec5ff 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -130,6 +130,9 @@ set(viewer_SOURCE_FILES llcommandlineparser.cpp llcompilequeue.cpp llconfirmationmanager.cpp + llconversationlog.cpp + llconversationloglist.cpp + llconversationloglistitem.cpp llcurrencyuimanager.cpp llcylinder.cpp lldateutil.cpp @@ -185,6 +188,8 @@ set(viewer_SOURCE_FILES llfloaterbuyland.cpp llfloatercamera.cpp llfloatercolorpicker.cpp + llfloaterconversationlog.cpp + llfloaterconversationpreview.cpp llfloaterdeleteenvpreset.cpp llfloaterdestinations.cpp llfloaterdisplayname.cpp @@ -687,6 +692,9 @@ set(viewer_HEADER_FILES llcommandlineparser.h llcompilequeue.h llconfirmationmanager.h + llconversationlog.h + llconversationloglist.h + llconversationloglistitem.h llcurrencyuimanager.h llcylinder.h lldateutil.h @@ -742,6 +750,8 @@ set(viewer_HEADER_FILES llfloaterbuyland.h llfloatercamera.h llfloatercolorpicker.h + llfloaterconversationlog.h + llfloaterconversationpreview.h llfloaterdeleteenvpreset.h llfloaterdestinations.h llfloaterdisplayname.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index da3ff2d1ee..7a5abba971 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10004,6 +10004,28 @@ <key>Value</key> <integer>2</integer> </map> + <key>CallLogSortOrder</key> + <map> + <key>Comment</key> + <string>Specifies sort order for Call Log (0 = by name, 1 = by date)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>2</integer> + </map> + <key>SortFriendsFirst</key> + <map> + <key>Comment</key> + <string>Specifies whether friends will be sorted first in Call Log</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>ShowPGSearchAll</key> <map> <key>Comment</key> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 1174d108d2..fe3a1ebf65 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -59,6 +59,7 @@ #include "llares.h" #include "llcurl.h" #include "llcalc.h" +#include "llconversationlog.h" #include "lltexturestats.h" #include "lltexturestats.h" #include "llviewerwindow.h" @@ -1757,6 +1758,9 @@ bool LLAppViewer::cleanup() // save mute list. gMuteList used to also be deleted here too. LLMuteList::getInstance()->cache(gAgent.getID()); + //save call log list + LLConversationLog::instance().cache(); + if (mPurgeOnExit) { llinfos << "Purging all cache files on exit" << llendflush; diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp new file mode 100644 index 0000000000..df9350407d --- /dev/null +++ b/indra/newview/llconversationlog.cpp @@ -0,0 +1,336 @@ +/** + * @file llconversationlog.h + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llagent.h" +#include "llconversationlog.h" +#include "lltrans.h" + +struct Conversation_params +{ + Conversation_params(time_t time) + : mTime(time), + mTimestamp(LLConversation::createTimestamp(time)) + {} + + time_t mTime; + std::string mTimestamp; + SessionType mConversationType; + std::string mConversationName; + std::string mHistoryFileName; + LLUUID mSessionID; + LLUUID mParticipantID; + bool mIsVoice; + bool mHasOfflineIMs; +}; + +/************************************************************************/ +/* LLConversation implementation */ +/************************************************************************/ + +LLConversation::LLConversation(const Conversation_params& params) +: mTime(params.mTime), + mTimestamp(params.mTimestamp), + mConversationType(params.mConversationType), + mConversationName(params.mConversationName), + mHistoryFileName(params.mHistoryFileName), + mSessionID(params.mSessionID), + mParticipantID(params.mParticipantID), + mIsVoice(params.mIsVoice), + mHasOfflineIMs(params.mHasOfflineIMs) +{ + setListenIMFloaterOpened(); +} + +LLConversation::LLConversation(const LLIMModel::LLIMSession& session) +: mTime(time_corrected()), + mTimestamp(createTimestamp(mTime)), + mConversationType(session.mSessionType), + mConversationName(session.mName), + mHistoryFileName(session.mHistoryFileName), + mSessionID(session.mSessionID), + mParticipantID(session.mOtherParticipantID), + mIsVoice(session.mStartedAsIMCall), + mHasOfflineIMs(session.mHasOfflineMessage) +{ + setListenIMFloaterOpened(); +} + +LLConversation::LLConversation(const LLConversation& conversation) +{ + mTime = conversation.getTime(); + mTimestamp = conversation.getTimestamp(); + mConversationType = conversation.getConversationType(); + mConversationName = conversation.getConversationName(); + mHistoryFileName = conversation.getHistoryFileName(); + mSessionID = conversation.getSessionID(); + mParticipantID = conversation.getParticipantID(); + mIsVoice = conversation.isVoice(); + mHasOfflineIMs = conversation.hasOfflineMessages(); + + setListenIMFloaterOpened(); +} + +LLConversation::~LLConversation() +{ + mIMFloaterShowedConnection.disconnect(); +} + +void LLConversation::onIMFloaterShown(const LLUUID& session_id) +{ + if (mSessionID == session_id) + { + mHasOfflineIMs = false; + } +} + +// static +const std::string LLConversation::createTimestamp(const time_t& utc_time) +{ + std::string timeStr; + LLSD substitution; + substitution["datetime"] = (S32) utc_time; + + timeStr = "["+LLTrans::getString ("TimeMonth")+"]/[" + +LLTrans::getString ("TimeDay")+"]/[" + +LLTrans::getString ("TimeYear")+"] [" + +LLTrans::getString ("TimeHour")+"]:[" + +LLTrans::getString ("TimeMin")+"]"; + + + LLStringUtil::format (timeStr, substitution); + return timeStr; +} + +void LLConversation::setListenIMFloaterOpened() +{ + LLIMFloater* floater = LLIMFloater::findInstance(mSessionID); + + bool has_offline_ims = !mIsVoice && mHasOfflineIMs; + bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); + + // we don't need to listen for im floater with this conversation is opened + // if floater is already opened or this conversation doesn't have unread offline messages + if (has_offline_ims && !ims_are_read) + { + mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1)); + } +} +/************************************************************************/ +/* LLConversationLog implementation */ +/************************************************************************/ + +LLConversationLog::LLConversationLog() +{ + loadFromFile(getFileName()); + + LLIMMgr::instance().addSessionObserver(this); + LLAvatarTracker::instance().addObserver(this); +} +void LLConversationLog::logConversation(const LLConversation& conversation) +{ + mConversations.push_back(conversation); + notifyObservers(); +} + +void LLConversationLog::removeConversation(const LLConversation& conversation) +{ + conversations_vec_t::iterator conv_it = mConversations.begin(); + for(; conv_it != mConversations.end(); ++conv_it) + { + if (conv_it->getSessionID() == conversation.getSessionID() && conv_it->getTime() == conversation.getTime()) + { + mConversations.erase(conv_it); + notifyObservers(); + return; + } + } +} + +const LLConversation* LLConversationLog::getConversation(const LLUUID& session_id) +{ + conversations_vec_t::const_iterator conv_it = mConversations.begin(); + for(; conv_it != mConversations.end(); ++conv_it) + { + if (conv_it->getSessionID() == session_id) + { + return &*conv_it; + } + } + + return NULL; +} + +void LLConversationLog::addObserver(LLConversationLogObserver* observer) +{ + mObservers.insert(observer); +} + +void LLConversationLog::removeObserver(LLConversationLogObserver* observer) +{ + mObservers.erase(observer); +} + +void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +{ + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); + if (session) + { + LLConversation conversation(*session); + LLConversationLog::instance().logConversation(conversation); + } +} + +// LLFriendObserver +void LLConversationLog::changed(U32 mask) +{ + if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE)) + { + notifyObservers(); + } +} + +void LLConversationLog::cache() +{ + saveToFile(getFileName()); +} + +std::string LLConversationLog::getFileName() +{ + std::string agent_id_string; + gAgent.getID().toString(agent_id_string); + + return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, agent_id_string) + ".call_log"; +} + +bool LLConversationLog::saveToFile(const std::string& filename) +{ + if(!filename.size()) + { + llwarns << "Call log list filename is empty!" << llendl; + return false; + } + + LLFILE* fp = LLFile::fopen(filename, "wb"); + if (!fp) + { + llwarns << "Couldn't open call log list" << filename << llendl; + return false; + } + + std::string participant_id; + std::string conversation_id; + + conversations_vec_t::const_iterator conv_it = mConversations.begin(); + for (; conv_it != mConversations.end(); ++conv_it) + { + conv_it->getSessionID().toString(conversation_id); + conv_it->getParticipantID().toString(participant_id); + + // examples of two file entries + // [1343221177] 0 1 0 John Doe| 7e4ec5be-783f-49f5-71dz-16c58c64c145 4ec62a74-c246-0d25-2af6-846beac2aa55 john.doe| + // [1343222639] 2 0 0 Ad-hoc Conference| c3g67c89-c479-4c97-b21d-32869bcfe8rc 68f1c33e-4135-3e3e-a897-8c9b23115c09 Ad-hoc Conference hash597394a0-9982-766d-27b8-c75560213b9a| + + fprintf(fp, "[%d] %d %d %d %s| %s %s %s|\n", + (S32)conv_it->getTime(), + (S32)conv_it->getConversationType(), + (S32)conv_it->isVoice(), + (S32)conv_it->hasOfflineMessages(), + conv_it->getConversationName().c_str(), + participant_id.c_str(), + conversation_id.c_str(), + conv_it->getHistoryFileName().c_str()); + } + fclose(fp); + return true; +} +bool LLConversationLog::loadFromFile(const std::string& filename) +{ + if(!filename.size()) + { + llwarns << "Call log list filename is empty!" << llendl; + return false; + } + + LLFILE* fp = LLFile::fopen(filename, "rb"); + if (!fp) + { + llwarns << "Couldn't open call log list" << filename << llendl; + return false; + } + + char buffer[MAX_STRING]; + char conv_name_buffer[MAX_STRING]; + char part_id_buffer[MAX_STRING]; + char conv_id_buffer[MAX_STRING]; + char history_file_name[MAX_STRING]; + int is_voice; + int has_offline_ims; + int stype; + S32 time; + + while (!feof(fp) && fgets(buffer, MAX_STRING, fp)) + { + conv_name_buffer[0] = '\0'; + part_id_buffer[0] = '\0'; + conv_id_buffer[0] = '\0'; + + sscanf(buffer, "[%d] %d %d %d %[^|]| %s %s %[^|]|", + &time, + &stype, + &is_voice, + &has_offline_ims, + conv_name_buffer, + part_id_buffer, + conv_id_buffer, + history_file_name); + + Conversation_params params(time); + params.mConversationType = (SessionType)stype; + params.mIsVoice = is_voice; + params.mHasOfflineIMs = has_offline_ims; + params.mConversationName = std::string(conv_name_buffer); + params.mParticipantID = LLUUID(part_id_buffer); + params.mSessionID = LLUUID(conv_id_buffer); + params.mHistoryFileName = std::string(history_file_name); + + LLConversation conversation(params); + mConversations.push_back(conversation); + } + fclose(fp); + + notifyObservers(); + return true; +} + +void LLConversationLog::notifyObservers() +{ + std::set<LLConversationLogObserver*>::const_iterator iter = mObservers.begin(); + for (; iter != mObservers.end(); ++iter) + { + (*iter)->changed(); + } +} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h new file mode 100644 index 0000000000..700472ca8b --- /dev/null +++ b/indra/newview/llconversationlog.h @@ -0,0 +1,164 @@ +/** + * @file llconversationlog.h + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLCONVERSATIONLOG_H_ +#define LLCONVERSATIONLOG_H_ + +#include "llcallingcard.h" +#include "llimfloater.h" +#include "llimview.h" + +class LLConversationLogObserver; +class Conversation_params; + +typedef LLIMModel::LLIMSession::SType SessionType; + +/* + * This class represents a particular session(conversation) of any type(im/voice/p2p/group/...) by storing some of session's data. + * Each LLConversation object has a corresponding visual representation in a form of LLConversationLogListItem. + */ +class LLConversation +{ +public: + + LLConversation(const Conversation_params& params); + LLConversation(const LLIMModel::LLIMSession& session); + LLConversation(const LLConversation& conversation); + + ~LLConversation(); + + const SessionType& getConversationType() const { return mConversationType; } + const std::string& getConversationName() const { return mConversationName; } + const std::string& getHistoryFileName() const { return mHistoryFileName; } + const LLUUID& getSessionID() const { return mSessionID; } + const LLUUID& getParticipantID() const { return mParticipantID; } + const std::string& getTimestamp() const { return mTimestamp; } + const time_t& getTime() const { return mTime; } + bool isVoice() const { return mIsVoice; } + bool hasOfflineMessages() const { return mHasOfflineIMs; } + + /* + * Resets flag of unread offline message to false when im floater with this conversation is opened. + */ + void onIMFloaterShown(const LLUUID& session_id); + + /* + * returns string representation(in form of: mm/dd/yyyy hh:mm) of time when conversation was started + */ + static const std::string createTimestamp(const time_t& utc_time); + +private: + + /* + * If conversation has unread offline messages sets callback for opening LLIMFloater + * with this conversation. + */ + void setListenIMFloaterOpened(); + + boost::signals2::connection mIMFloaterShowedConnection; + + time_t mTime; // start time of conversation + SessionType mConversationType; + std::string mConversationName; + std::string mHistoryFileName; + LLUUID mSessionID; + LLUUID mParticipantID; + bool mIsVoice; + bool mHasOfflineIMs; + std::string mTimestamp; // conversation start time in form of: mm/dd/yyyy hh:mm +}; + +/** + * LLConversationLog stores all agent's conversations. + * This class is responsible for creating and storing LLConversation objects when im or voice session starts. + * Also this class saves/retrieves conversations to/from file. + * + * Also please note that it may be several conversations with the same sessionID stored in the conversation log. + * To distinguish two conversations with the same sessionID it's also needed to compare their creation date. + */ + +class LLConversationLog : public LLSingleton<LLConversationLog>, LLIMSessionObserver, LLFriendObserver +{ + friend class LLSingleton<LLConversationLog>; +public: + + /** + * adds conversation to the conversation list and notifies observers + */ + void logConversation(const LLConversation& conversation); + void removeConversation(const LLConversation& conversation); + + /** + * Returns first conversation with matched session_id + */ + const LLConversation* getConversation(const LLUUID& session_id); + + void addObserver(LLConversationLogObserver* observer); + void removeObserver(LLConversationLogObserver* observer); + + const std::vector<LLConversation>& getConversations() { return mConversations; } + + // LLIMSessionObserver triggers + virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){} // Stub + virtual void sessionRemoved(const LLUUID& session_id){} // Stub + virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){} // Stub + + // LLFriendObserver trigger + virtual void changed(U32 mask); + + /** + * public method which is called on viewer exit to save conversation log + */ + void cache(); + +private: + + LLConversationLog(); + void notifyObservers(); + + /** + * constructs file name in which conversations log will be saved + * file name template: agentID.call_log. + * For example: a086icaa-782d-88d0-ae29-987a55c99sss.call_log + */ + std::string getFileName(); + + bool saveToFile(const std::string& filename); + bool loadFromFile(const std::string& filename); + + typedef std::vector<LLConversation> conversations_vec_t; + std::vector<LLConversation> mConversations; + std::set<LLConversationLogObserver*> mObservers; +}; + +class LLConversationLogObserver +{ +public: + virtual ~LLConversationLogObserver(){} + virtual void changed() = 0; +}; + +#endif /* LLCONVERSATIONLOG_H_ */ diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp new file mode 100644 index 0000000000..0433719a89 --- /dev/null +++ b/indra/newview/llconversationloglist.cpp @@ -0,0 +1,422 @@ +/** + * @file llconversationloglist.cpp + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llavataractions.h" +#include "llagent.h" +#include "llfloaterreg.h" +#include "llfloaterconversationpreview.h" +#include "llgroupactions.h" +#include "llconversationloglist.h" +#include "llconversationloglistitem.h" +#include "llviewermenu.h" + +static LLDefaultChildRegistry::Register<LLConversationLogList> r("conversation_log_list"); + +static LLConversationLogListNameComparator NAME_COMPARATOR; +static LLConversationLogListDateComparator DATE_COMPARATOR; + +LLConversationLogList::LLConversationLogList(const Params& p) +: LLFlatListViewEx(p), + mIsDirty(true) +{ + LLConversationLog::instance().addObserver(this); + + // Set up context menu. + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar check_registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + + registrar.add ("Calllog.Action", boost::bind(&LLConversationLogList::onCustomAction, this, _2)); + check_registrar.add ("Calllog.Check", boost::bind(&LLConversationLogList::isActionChecked,this, _2)); + enable_registrar.add("Calllog.Enable", boost::bind(&LLConversationLogList::isActionEnabled,this, _2)); + + LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>( + "menu_conversation_log_gear.xml", + gMenuHolder, + LLViewerMenuHolderGL::child_registry_t::instance()); + if(context_menu) + { + mContextMenu = context_menu->getHandle(); + } + + mIsFriendsOnTop = gSavedSettings.getBOOL("SortFriendsFirst"); +} + +LLConversationLogList::~LLConversationLogList() +{ + if (mContextMenu.get()) + { + mContextMenu.get()->die(); + } + + LLConversationLog::instance().removeObserver(this); +} + +void LLConversationLogList::draw() +{ + if (mIsDirty) + { + refresh(); + } + LLFlatListViewEx::draw(); +} + +BOOL LLConversationLogList::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); + + LLToggleableMenu* context_menu = mContextMenu.get(); + { + context_menu->buildDrawLabels(); + if (context_menu && size()) + context_menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, context_menu, x, y); + } + + return handled; +} + +void LLConversationLogList::setNameFilter(const std::string& filter) +{ + std::string filter_upper = filter; + LLStringUtil::toUpper(filter_upper); + if (mNameFilter != filter_upper) + { + mNameFilter = filter_upper; + setDirty(); + } +} + +bool LLConversationLogList::findInsensitive(std::string haystack, const std::string& needle_upper) +{ + LLStringUtil::toUpper(haystack); + return haystack.find(needle_upper) != std::string::npos; +} + +void LLConversationLogList::sortByName() +{ + setComparator(&NAME_COMPARATOR); + sort(); +} + +void LLConversationLogList::sortByDate() +{ + setComparator(&DATE_COMPARATOR); + sort(); +} + +void LLConversationLogList::toggleSortFriendsOnTop() +{ + mIsFriendsOnTop = !mIsFriendsOnTop; + gSavedSettings.setBOOL("SortFriendsFirst", mIsFriendsOnTop); + sort(); +} + +void LLConversationLogList::changed() +{ + refresh(); +} + +void LLConversationLogList::addNewItem(const LLConversation* conversation) +{ + LLConversationLogListItem* item = new LLConversationLogListItem(&*conversation); + if (!mNameFilter.empty()) + { + item->highlightNameDate(mNameFilter); + } + addItem(item, conversation->getSessionID(), ADD_TOP); +} + +void LLConversationLogList::refresh() +{ + rebuildList(); + sort(); + + mIsDirty = false; +} + +void LLConversationLogList::rebuildList() +{ + clear(); + + bool have_filter = !mNameFilter.empty(); + + const std::vector<LLConversation>& conversations = LLConversationLog::instance().getConversations(); + std::vector<LLConversation>::const_iterator iter = conversations.begin(); + + for (; iter != conversations.end(); ++iter) + { + bool not_found = have_filter && !findInsensitive(iter->getConversationName(), mNameFilter) && !findInsensitive(iter->getTimestamp(), mNameFilter); + if (not_found) + continue; + + addNewItem(&*iter); + } +} + +void LLConversationLogList::onCustomAction(const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); + LLIMModel::LLIMSession::SType stype = getSelectedSessionType(); + + if ("im" == command_name) + { + switch (stype) + { + case LLIMModel::LLIMSession::P2P_SESSION: + LLAvatarActions::startIM(selected_id); + break; + + case LLIMModel::LLIMSession::GROUP_SESSION: + LLGroupActions::startIM(selected_id); + break; + + default: + break; + } + } + else if ("call" == command_name) + { + switch (stype) + { + case LLIMModel::LLIMSession::P2P_SESSION: + LLAvatarActions::startCall(selected_id); + break; + + case LLIMModel::LLIMSession::GROUP_SESSION: + LLGroupActions::startCall(selected_id); + break; + + default: + break; + } + } + else if ("view_profile" == command_name) + { + switch (stype) + { + case LLIMModel::LLIMSession::P2P_SESSION: + LLAvatarActions::showProfile(selected_id); + break; + + case LLIMModel::LLIMSession::GROUP_SESSION: + LLGroupActions::show(selected_id); + break; + + default: + break; + } + } + else if ("chat_history" == command_name) + { + const LLUUID& session_id = getSelectedConversation()->getSessionID(); + LLFloaterReg::showInstance("preview_conversation", session_id, true); + } + else if ("offer_teleport" == command_name) + { + LLAvatarActions::offerTeleport(selected_id); + } + else if("add_rem_friend" == command_name) + { + if (LLAvatarActions::isFriend(selected_id)) + { + LLAvatarActions::removeFriendDialog(selected_id); + } + else + { + LLAvatarActions::requestFriendshipDialog(selected_id); + } + } + else if ("invite_to_group" == command_name) + { + LLAvatarActions::inviteToGroup(selected_id); + } + else if ("show_on_map" == command_name) + { + LLAvatarActions::showOnMap(selected_id); + } + else if ("share" == command_name) + { + LLAvatarActions::share(selected_id); + } + else if ("pay" == command_name) + { + LLAvatarActions::pay(selected_id); + } + else if ("block" == command_name) + { + LLAvatarActions::toggleBlock(selected_id); + } +} + +bool LLConversationLogList::isActionEnabled(const LLSD& userdata) +{ + if (numSelected() != 1) + { + return false; + } + + const std::string command_name = userdata.asString(); + + LLIMModel::LLIMSession::SType stype = getSelectedSessionType(); + const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); + + bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == stype; + bool is_group = LLIMModel::LLIMSession::GROUP_SESSION == stype; + + if ("can_im" == command_name || "can_view_profile" == command_name) + { + return is_p2p || is_group; + } + else if ("can_view_chat_history" == command_name) + { + return true; + } + else if ("can_call" == command_name) + { + return (is_p2p || is_group) && LLAvatarActions::canCall(); + } + else if ("add_rem_friend" == command_name || + "can_invite_to_group" == command_name || + "can_share" == command_name || + "can_block" == command_name || + "can_pay" == command_name) + { + return is_p2p; + } + else if("can_offer_teleport" == command_name) + { + return is_p2p && LLAvatarActions::canOfferTeleport(selected_id); + } + else if ("can_show_on_map") + { + return is_p2p && ((LLAvatarTracker::instance().isBuddyOnline(selected_id) && is_agent_mappable(selected_id)) || gAgent.isGodlike()); + } + + return false; +} + +bool LLConversationLogList::isActionChecked(const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + + const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); + bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == getSelectedSessionType(); + + if ("is_blocked" == command_name) + { + return is_p2p && LLAvatarActions::isBlocked(selected_id); + } + else if ("is_friend" == command_name) + { + return is_p2p && LLAvatarActions::isFriend(selected_id); + } + + return false; +} + +LLIMModel::LLIMSession::SType LLConversationLogList::getSelectedSessionType() +{ + const LLConversationLogListItem* item = getSelectedConversationPanel(); + + if (item) + { + return item->getConversation()->getConversationType(); + } + + return LLIMModel::LLIMSession::NONE_SESSION; +} + +const LLConversationLogListItem* LLConversationLogList::getSelectedConversationPanel() +{ + LLPanel* panel = LLFlatListViewEx::getSelectedItem(); + LLConversationLogListItem* conv_panel = dynamic_cast<LLConversationLogListItem*>(panel); + + return conv_panel; +} + +const LLConversation* LLConversationLogList::getSelectedConversation() +{ + const LLConversationLogListItem* panel = getSelectedConversationPanel(); + + if (panel) + { + return panel->getConversation(); + } + + return NULL; +} + +bool LLConversationLogListItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const +{ + const LLConversationLogListItem* conversation_item1 = dynamic_cast<const LLConversationLogListItem*>(item1); + const LLConversationLogListItem* conversation_item2 = dynamic_cast<const LLConversationLogListItem*>(item2); + + if (!conversation_item1 || !conversation_item2) + { + llerror("conversation_item1 and conversation_item2 cannot be null", 0); + return true; + } + + return doCompare(conversation_item1, conversation_item2); +} + +bool LLConversationLogListNameComparator::doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const +{ + std::string name1 = conversation1->getConversation()->getConversationName(); + std::string name2 = conversation2->getConversation()->getConversationName(); + const LLUUID& id1 = conversation1->getConversation()->getParticipantID(); + const LLUUID& id2 = conversation2->getConversation()->getParticipantID(); + + LLStringUtil::toUpper(name1); + LLStringUtil::toUpper(name2); + + bool friends_first = gSavedSettings.getBOOL("SortFriendsFirst"); + if (friends_first && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2))) + { + return LLAvatarActions::isFriend(id1); + } + + return name1 < name2; +} + +bool LLConversationLogListDateComparator::doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const +{ + time_t date1 = conversation1->getConversation()->getTime(); + time_t date2 = conversation2->getConversation()->getTime(); + const LLUUID& id1 = conversation1->getConversation()->getParticipantID(); + const LLUUID& id2 = conversation2->getConversation()->getParticipantID(); + + bool friends_first = gSavedSettings.getBOOL("SortFriendsFirst"); + if (friends_first && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2))) + { + return LLAvatarActions::isFriend(id1); + } + + return date1 > date2; +} diff --git a/indra/newview/llconversationloglist.h b/indra/newview/llconversationloglist.h new file mode 100644 index 0000000000..dff34a74c6 --- /dev/null +++ b/indra/newview/llconversationloglist.h @@ -0,0 +1,143 @@ +/** + * @file llconversationloglist.h + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLCONVERSATIONLOGLIST_H_ +#define LLCONVERSATIONLOGLIST_H_ + +#include "llconversationlog.h" +#include "llflatlistview.h" +#include "lltoggleablemenu.h" + +class LLConversationLogListItem; + +/** + * List of all agent's conversations. I.e. history of conversations. + * This list represents contents of the LLConversationLog. + * Each change in LLConversationLog leads to rebuilding this list, so + * it's always in actual state. + */ + +class LLConversationLogList: public LLFlatListViewEx, public LLConversationLogObserver +{ + LOG_CLASS(LLConversationLogList); +public: + struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params> + { + Params(){}; + }; + + LLConversationLogList(const Params& p); + virtual ~LLConversationLogList(); + + virtual void draw(); + + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + + LLToggleableMenu* getContextMenu() const { return mContextMenu.get(); } + + void addNewItem(const LLConversation* conversation); + void setNameFilter(const std::string& filter); + void sortByName(); + void sortByDate(); + void toggleSortFriendsOnTop(); + bool getSortFriendsOnTop() const { return mIsFriendsOnTop; } + + /** + * Changes from LLConversationLogObserver + */ + virtual void changed(); + +private: + + void setDirty(bool dirty = true) { mIsDirty = dirty; } + void refresh(); + + /** + * Clears list and re-adds items from LLConverstationLog + * If filter is not empty re-adds items which match the filter + */ + void rebuildList(); + + bool findInsensitive(std::string haystack, const std::string& needle_upper); + + void onCustomAction (const LLSD& userdata); + bool isActionEnabled(const LLSD& userdata); + bool isActionChecked(const LLSD& userdata); + + LLIMModel::LLIMSession::SType getSelectedSessionType(); + const LLConversationLogListItem* getSelectedConversationPanel(); + const LLConversation* getSelectedConversation(); + + LLHandle<LLToggleableMenu> mContextMenu; + bool mIsDirty; + bool mIsFriendsOnTop; + std::string mNameFilter; +}; + +/** + * Abstract comparator for ConversationLogList items + */ +class LLConversationLogListItemComparator : public LLFlatListView::ItemComparator +{ + LOG_CLASS(LLConversationLogListItemComparator); + +public: + LLConversationLogListItemComparator() {}; + virtual ~LLConversationLogListItemComparator() {}; + + virtual bool compare(const LLPanel* item1, const LLPanel* item2) const; + +protected: + + virtual bool doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const = 0; +}; + +class LLConversationLogListNameComparator : public LLConversationLogListItemComparator +{ + LOG_CLASS(LLConversationLogListNameComparator); + +public: + LLConversationLogListNameComparator() {}; + virtual ~LLConversationLogListNameComparator() {}; + +protected: + + virtual bool doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const; +}; + +class LLConversationLogListDateComparator : public LLConversationLogListItemComparator +{ + LOG_CLASS(LLConversationLogListDateComparator); + +public: + LLConversationLogListDateComparator() {}; + virtual ~LLConversationLogListDateComparator() {}; + +protected: + + virtual bool doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const; +}; + +#endif /* LLCONVERSATIONLOGLIST_H_ */ diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp new file mode 100644 index 0000000000..fc2e757864 --- /dev/null +++ b/indra/newview/llconversationloglistitem.cpp @@ -0,0 +1,157 @@ +/** + * @file llconversationloglistitem.cpp + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +// llui +#include "lliconctrl.h" +#include "lltextbox.h" +#include "lltextutil.h" + +// newview +#include "llavatariconctrl.h" +#include "llconversationlog.h" +#include "llconversationloglistitem.h" +#include "llgroupiconctrl.h" +#include "llinventoryicon.h" + +LLConversationLogListItem::LLConversationLogListItem(const LLConversation* conversation) +: LLPanel(), + mConversation(conversation), + mConversationName(NULL), + mConversationDate(NULL) +{ + buildFromFile("panel_conversation_log_list_item.xml"); + + LLIMFloater* floater = LLIMFloater::findInstance(mConversation->getSessionID()); + + bool has_offline_ims = !mConversation->isVoice() && mConversation->hasOfflineMessages(); + bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); + + if (has_offline_ims && !ims_are_read) + { + mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversationLogListItem::onIMFloaterShown, this, _1)); + } +} + +LLConversationLogListItem::~LLConversationLogListItem() +{ + mIMFloaterShowedConnection.disconnect(); +} + +BOOL LLConversationLogListItem::postBuild() +{ + initIcons(); + + // set conversation name + mConversationName = getChild<LLTextBox>("conversation_name"); + mConversationName->setValue(mConversation->getConversationName()); + + // set conversation date and time + mConversationDate = getChild<LLTextBox>("date_time"); + mConversationDate->setValue(mConversation->getTimestamp()); + + getChild<LLButton>("delete_btn")->setClickedCallback(boost::bind(&LLConversationLogListItem::onRemoveBtnClicked, this)); + + return TRUE; +} + +void LLConversationLogListItem::initIcons() +{ + switch (mConversation->getConversationType()) + { + case LLIMModel::LLIMSession::P2P_SESSION: + case LLIMModel::LLIMSession::ADHOC_SESSION: + { + LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon"); + avatar_icon->setVisible(TRUE); + avatar_icon->setValue(mConversation->getParticipantID()); + break; + } + case LLIMModel::LLIMSession::GROUP_SESSION: + { + LLGroupIconCtrl* group_icon = getChild<LLGroupIconCtrl>("group_icon"); + group_icon->setVisible(TRUE); + group_icon->setValue(mConversation->getSessionID()); + break; + } + default: + break; + } + + if (mConversation->isVoice()) + { + getChild<LLIconCtrl>("voice_session_icon")->setVisible(TRUE); + } + else + { + if (mConversation->hasOfflineMessages()) + { + getChild<LLIconCtrl>("unread_ims_icon")->setVisible(TRUE); + } + } +} + +void LLConversationLogListItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ + getChildView("hovered_icon")->setVisible(true); + LLPanel::onMouseEnter(x, y, mask); +} + +void LLConversationLogListItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ + getChildView("hovered_icon")->setVisible(false); + LLPanel::onMouseLeave(x, y, mask); +} + +void LLConversationLogListItem::setValue(const LLSD& value) +{ + if (!value.isMap() || !value.has("selected")) + { + return; + } + + getChildView("selected_icon")->setVisible(value["selected"]); +} + +void LLConversationLogListItem::onIMFloaterShown(const LLUUID& session_id) +{ + if (mConversation->getSessionID() == session_id) + { + getChild<LLIconCtrl>("unread_ims_icon")->setVisible(FALSE); + } +} + +void LLConversationLogListItem::onRemoveBtnClicked() +{ + LLConversationLog::instance().removeConversation(*mConversation); +} + +void LLConversationLogListItem::highlightNameDate(const std::string& highlited_text) +{ + LLStyle::Params params; + LLTextUtil::textboxSetHighlightedVal(mConversationName, params, mConversation->getConversationName(), highlited_text); + LLTextUtil::textboxSetHighlightedVal(mConversationDate, params, mConversation->getTimestamp(), highlited_text); +} diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h new file mode 100644 index 0000000000..deba7d4563 --- /dev/null +++ b/indra/newview/llconversationloglistitem.h @@ -0,0 +1,77 @@ +/** + * @file llconversationloglistitem.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLCONVERSATIONLOGLISTITEM_H_ +#define LLCONVERSATIONLOGLISTITEM_H_ + +#include "llimfloater.h" +#include "llpanel.h" + +class LLTextBox; +class LLConversation; + +/** + * This class is a visual representation of LLConversation, each of which is LLConversationLog entry. + * LLConversationLogList consists of these LLConversationLogListItems. + * LLConversationLogListItem consists of: + * conversaion_type_icon + * conversaion_name + * conversaion_date + * Also LLConversationLogListItem holds pointer to its LLConversationLog. + */ + +class LLConversationLogListItem : public LLPanel +{ +public: + LLConversationLogListItem(const LLConversation* conversation); + virtual ~LLConversationLogListItem(); + + void onMouseEnter(S32 x, S32 y, MASK mask); + void onMouseLeave(S32 x, S32 y, MASK mask); + + virtual void setValue(const LLSD& value); + + virtual BOOL postBuild(); + + void onIMFloaterShown(const LLUUID& session_id); + void onRemoveBtnClicked(); + + const LLConversation* getConversation() const { return mConversation; } + + void highlightNameDate(const std::string& highlited_text); + +private: + + void initIcons(); + + const LLConversation* mConversation; + + LLTextBox* mConversationName; + LLTextBox* mConversationDate; + + boost::signals2::connection mIMFloaterShowedConnection; +}; + +#endif /* LLCONVERSATIONLOGITEM_H_ */ diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp new file mode 100644 index 0000000000..569ba12ed6 --- /dev/null +++ b/indra/newview/llfloaterconversationlog.cpp @@ -0,0 +1,127 @@ +/** + * @file llfloaterconversationlog.cpp + * @brief Functionality of the "conversation log" floater + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#include "llviewerprecompiledheaders.h" + +#include "llconversationloglist.h" +#include "llfiltereditor.h" +#include "llfloaterconversationlog.h" +#include "llmenubutton.h" + +LLFloaterConversationLog::LLFloaterConversationLog(const LLSD& key) +: LLFloater(key), + mConversationLogList(NULL) +{ + mCommitCallbackRegistrar.add("CallLog.Action", boost::bind(&LLFloaterConversationLog::onCustomAction, this, _2)); + mEnableCallbackRegistrar.add("CallLog.Check", boost::bind(&LLFloaterConversationLog::isActionChecked, this, _2)); +} + +BOOL LLFloaterConversationLog::postBuild() +{ + mConversationLogList = getChild<LLConversationLogList>("conversation_log_list"); + + switch (gSavedSettings.getU32("CallLogSortOrder")) + { + case E_SORT_BY_NAME: + mConversationLogList->sortByName(); + break; + + case E_SORT_BY_DATE: + mConversationLogList->sortByDate(); + break; + } + + // Use the context menu of the Conversation list for the Conversation tab gear menu. + LLToggleableMenu* conversations_gear_menu = mConversationLogList->getContextMenu(); + if (conversations_gear_menu) + { + getChild<LLMenuButton>("conversations_gear_btn")->setMenu(conversations_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); + } + + getChild<LLFilterEditor>("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); + + return LLFloater::postBuild(); +} + +void LLFloaterConversationLog::draw() +{ + LLFloater::draw(); +} + +void LLFloaterConversationLog::onFilterEdit(const std::string& search_string) +{ + std::string filter = search_string; + LLStringUtil::trimHead(filter); + + mConversationLogList->setNameFilter(filter); +} + + +void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + + if ("sort_by_name" == command_name) + { + mConversationLogList->sortByName(); + gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_NAME); + } + else if ("sort_by_date" == command_name) + { + mConversationLogList->sortByDate(); + gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_DATE); + } + else if ("sort_friends_on_top" == command_name) + { + mConversationLogList->toggleSortFriendsOnTop(); + } +} + +bool LLFloaterConversationLog::isActionEnabled(const LLSD& userdata) +{ + return true; +} + +bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + + U32 sort_order = gSavedSettings.getU32("CallLogSortOrder"); + + if ("sort_by_name" == command_name) + { + return sort_order == E_SORT_BY_NAME; + } + else if ("sort_by_date" == command_name) + { + return sort_order == E_SORT_BY_DATE; + } + else if ("sort_friends_on_top" == command_name) + { + return gSavedSettings.getBOOL("SortFriendsFirst"); + } + + return false; +} diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h new file mode 100644 index 0000000000..40dd266663 --- /dev/null +++ b/indra/newview/llfloaterconversationlog.h @@ -0,0 +1,61 @@ +/** + * @file llfloaterconversationlog.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERCONVERSATIONLOG_H_ +#define LL_LLFLOATERCONVERSATIONLOG_H_ + +#include "llfloater.h" + +class LLConversationLogList; + +class LLFloaterConversationLog : public LLFloater +{ +public: + + typedef enum e_sort_oder{ + E_SORT_BY_NAME = 0, + E_SORT_BY_DATE = 1, + } ESortOrder; + + LLFloaterConversationLog(const LLSD& key); + virtual ~LLFloaterConversationLog(){}; + + virtual BOOL postBuild(); + + virtual void draw(); + + void onFilterEdit(const std::string& search_string); + +private: + + void onCustomAction (const LLSD& userdata); + bool isActionEnabled(const LLSD& userdata); + bool isActionChecked(const LLSD& userdata); + + LLConversationLogList* mConversationLogList; +}; + + +#endif /* LLFLOATERCONVERSATIONLOG_H_ */ diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp new file mode 100644 index 0000000000..e8554bb066 --- /dev/null +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -0,0 +1,112 @@ +/** + * @file llfloaterconversationpreview.cpp + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llconversationlog.h" +#include "llfloaterconversationpreview.h" +#include "llimview.h" +#include "lllineeditor.h" + +LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id) +: LLFloater(session_id), + mChatHistory(NULL), + mSessionID(session_id.asUUID()) +{} + +BOOL LLFloaterConversationPreview::postBuild() +{ + mChatHistory = getChild<LLChatHistory>("chat_history"); + + const LLConversation* conv = LLConversationLog::instance().getConversation(mSessionID); + if (conv) + { + std::string name = conv->getConversationName(); + LLStringUtil::format_map_t args; + args["[NAME]"] = name; + std::string title = getString("Title", args); + setTitle(title); + + getChild<LLLineEditor>("description")->setValue(name); + } + + return LLFloater::postBuild(); +} + +void LLFloaterConversationPreview::draw() +{ + LLFloater::draw(); +} + +void LLFloaterConversationPreview::onOpen(const LLSD& session_id) +{ + const LLConversation* conv = LLConversationLog::instance().getConversation(session_id); + if (!conv) + { + return; + } + std::list<LLSD> messages; + std::string file = conv->getHistoryFileName(); + LLLogChat::loadAllHistory(file, messages); + + if (messages.size()) + { + std::ostringstream message; + std::list<LLSD>::const_iterator iter = messages.begin(); + for (; iter != messages.end(); ++iter) + { + LLSD msg = *iter; + + std::string time = msg["time"].asString(); + LLUUID from_id = msg["from_id"].asUUID(); + std::string from = msg["from"].asString(); + std::string message = msg["message"].asString(); + bool is_history = msg["is_history"].asBoolean(); + + LLChat chat; + chat.mFromID = from_id; + chat.mSessionID = session_id; + chat.mFromName = from; + chat.mTimeStr = time; + chat.mChatStyle = is_history ? CHAT_STYLE_HISTORY : chat.mChatStyle; + chat.mText = message; + + appendMessage(chat); + } + } +} + +void LLFloaterConversationPreview::appendMessage(const LLChat& chat) +{ + if (!chat.mMuted) + { + LLSD args; + args["use_plain_text_chat_history"] = true; + args["show_time"] = true; + args["show_names_for_p2p_conv"] = true; + + mChatHistory->appendMessage(chat); + } +} diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h new file mode 100644 index 0000000000..cfc7c34485 --- /dev/null +++ b/indra/newview/llfloaterconversationpreview.h @@ -0,0 +1,51 @@ +/** + * @file llfloaterconversationpreview.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLFLOATERCONVERSATIONPREVIEW_H_ +#define LLFLOATERCONVERSATIONPREVIEW_H_ + +#include "llchathistory.h" +#include "llfloater.h" + +class LLFloaterConversationPreview : public LLFloater +{ +public: + + LLFloaterConversationPreview(const LLSD& session_id); + virtual ~LLFloaterConversationPreview(){}; + + virtual BOOL postBuild(); + + virtual void draw(); + virtual void onOpen(const LLSD& session_id); + +private: + void appendMessage(const LLChat& chat); + + LLChatHistory* mChatHistory; + LLUUID mSessionID; +}; + +#endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */ diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 22ce3cd42b..f1d7d1c04f 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -59,6 +59,8 @@ #include "llviewerchat.h" #include "llnotificationmanager.h" +floater_showed_signal_t LLIMFloater::sIMFloaterShowedSignal; + LLIMFloater::LLIMFloater(const LLUUID& session_id) : LLIMConversation(session_id), mLastMessageIndex(-1), @@ -765,6 +767,11 @@ void LLIMFloater::setVisible(BOOL visible) chiclet->setToggleState(false); } } + + if (visible) + { + sIMFloaterShowedSignal(mSessionID); + } } BOOL LLIMFloater::getVisible() @@ -1334,3 +1341,8 @@ void LLIMFloater::addToHost(const LLUUID& session_id) } } } + +boost::signals2::connection LLIMFloater::setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb) +{ + return LLIMFloater::sIMFloaterShowedSignal.connect(cb); +} diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 2ac11ded20..7e45cf42c2 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -44,6 +44,8 @@ class LLChatHistory; class LLInventoryItem; class LLInventoryCategory; +typedef boost::signals2::signal<void(const LLUUID& session_id)> floater_showed_signal_t; + /** * Individual IM window that appears at the bottom of the screen, * optionally "docked" to the bottom tray. @@ -125,7 +127,11 @@ public: bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; } + static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); + static floater_showed_signal_t sIMFloaterShowedSignal; + private: + // process focus events to set a currently active session /* virtual */ void onFocusLost(); /* virtual */ void onFocusReceived(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cdbb7c7cca..c66c0cd865 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -175,10 +175,11 @@ LLIMModel::LLIMModel() addNewMsgCallback(boost::bind(&toast_callback, _1)); } -LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice) +LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg) : mSessionID(session_id), mName(name), mType(type), + mHasOfflineMessage(has_offline_msg), mParticipantUnreadMessageCount(0), mNumUnread(0), mOtherParticipantID(other_participant_id), @@ -375,6 +376,8 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES break; } } + default: + break; } // Update speakers list when connected if (LLVoiceChannel::STATE_CONNECTED == new_state) @@ -676,7 +679,7 @@ void LLIMModel::testMessages() //session name should not be empty bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, - const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice) + const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg) { if (name.empty()) { @@ -690,7 +693,7 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co return false; } - LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids, voice); + LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids, voice, has_offline_msg); mId2SessionMap[session_id] = session; // When notifying observer, name of session is used instead of "name", because they may not be the @@ -702,10 +705,10 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co } -bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, bool voice) +bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, bool voice, bool has_offline_msg) { uuid_vec_t no_ids; - return newSession(session_id, name, type, other_participant_id, no_ids, voice); + return newSession(session_id, name, type, other_participant_id, no_ids, voice, has_offline_msg); } bool LLIMModel::clearSession(const LLUUID& session_id) @@ -2398,6 +2401,7 @@ void LLIMMgr::addMessage( const LLUUID& target_id, const std::string& from, const std::string& msg, + bool is_offline_msg, const std::string& session_name, EInstantMessage dialog, U32 parent_estate_id, @@ -2423,7 +2427,7 @@ void LLIMMgr::addMessage( bool new_session = !hasSession(new_session_id); if (new_session) { - LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id); + LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg); // When we get a new IM, and if you are a god, display a bit // of information about the source. This is to help liaisons @@ -3315,6 +3319,7 @@ public: from_id, name, buffer, + IM_OFFLINE == offline, std::string((char*)&bin_bucket[0]), IM_SESSION_INVITE, message_params["parent_estate_id"].asInteger(), diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 80bf315aa8..fa9d20ca53 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -70,10 +70,11 @@ public: GROUP_SESSION, ADHOC_SESSION, AVALINE_SESSION, + NONE_SESSION, } SType; LLIMSession(const LLUUID& session_id, const std::string& name, - const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice); + const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg); virtual ~LLIMSession(); void sessionInitReplyReceived(const LLUUID& new_session_id); @@ -133,6 +134,8 @@ public: //if IM session is created for a voice call bool mStartedAsIMCall; + bool mHasOfflineMessage; + private: void onAdHocNameCache(const LLAvatarName& av_name); @@ -181,10 +184,10 @@ public: * @param name session name should not be empty, will return false if empty */ bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, - const uuid_vec_t& ids, bool voice = false); + const uuid_vec_t& ids, bool voice = false, bool has_offline_msg = false); bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, - const LLUUID& other_participant_id, bool voice = false); + const LLUUID& other_participant_id, bool voice = false, bool has_offline_msg = false); /** * Remove all session data associated with a session specified by session_id @@ -325,6 +328,7 @@ public: const LLUUID& target_id, const std::string& from, const std::string& msg, + bool is_offline_msg = false, const std::string& session_name = LLStringUtil::null, EInstantMessage dialog = IM_NOTHING_SPECIAL, U32 parent_estate_id = 0, diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 65fd6d7019..4cf6ff55a4 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -94,6 +94,7 @@ #include "llcallingcard.h" #include "llconsole.h" #include "llcontainerview.h" +#include "llconversationlog.h" #include "lldebugview.h" #include "lldrawable.h" #include "lleventnotifier.h" @@ -1266,6 +1267,8 @@ bool idle_startup() display_startup(); LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT ); + LLConversationLog::getInstance(); + return FALSE; } diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index bf12b08321..5c662af875 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -50,6 +50,8 @@ #include "llfloaterbump.h" #include "llfloaterbvhpreview.h" #include "llfloatercamera.h" +#include "llfloaterconversationlog.h" +#include "llfloaterconversationpreview.h" #include "llfloaterdeleteenvpreset.h" #include "llfloaterdisplayname.h" #include "llfloatereditdaycycle.h" @@ -188,6 +190,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>); LLFloaterReg::add("chat_bar", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>); LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>); + LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>); LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>); @@ -253,6 +256,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("picks", "floater_picks.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>); LLFloaterReg::add("preview_anim", "floater_preview_animation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewAnim>, "preview"); + LLFloaterReg::add("preview_conversation", "floater_conversation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationPreview>); LLFloaterReg::add("preview_gesture", "floater_preview_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewGesture>, "preview"); LLFloaterReg::add("preview_notecard", "floater_preview_notecard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewNotecard>, "preview"); LLFloaterReg::add("preview_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewLSL>, "preview"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 03c113ecb3..20887f7832 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2396,6 +2396,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) from_id, name, buffer, + IM_OFFLINE == offline, LLStringUtil::null, dialog, parent_estate_id, @@ -2435,7 +2436,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) if (!gIMMgr->isNonFriendSessionNotified(session_id)) { std::string message = LLTrans::getString("IM_unblock_only_groups_friends"); - gIMMgr->addMessage(session_id, from_id, name, message); + gIMMgr->addMessage(session_id, from_id, name, message, IM_OFFLINE == offline); gIMMgr->addNotifiedNonFriendSessionID(session_id); } @@ -2448,6 +2449,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) from_id, name, buffer, + IM_OFFLINE == offline, LLStringUtil::null, dialog, parent_estate_id, @@ -2788,6 +2790,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) from_id, name, buffer, + IM_OFFLINE == offline, ll_safe_string((char*)binary_bucket), IM_SESSION_INVITE, parent_estate_id, diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index df1d3f2955..f4c88403a5 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -4072,6 +4072,7 @@ void LLVivoxVoiceClient::messageEvent( session->mCallerID, session->mName.c_str(), message.c_str(), + false, LLStringUtil::null, // default arg IM_NOTHING_SPECIAL, // default arg 0, // default arg diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml new file mode 100644 index 0000000000..1c5800e25f --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> + +<floater + can_resize="true" + positioning="cascading" + height="400" + min_height="100" + min_width="390" + layout="topleft" + name="floater_conversation_log" + save_rect="true" + single_instance="true" + reuse_instance="true" + title="CONVERSATION LOG" + width="450"> + <panel + follows="left|top|right" + height="27" + layout="topleft" + left="0" + name="buttons_panel" + top="0"> + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="8" + label="Filter People" + max_length_chars="300" + name="people_filter_input" + text_color="Black" + text_pad_left="10" + top="4" + width="364" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_sort" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="5" + menu_filename="menu_conversation_log_view.xml" + menu_position="bottomleft" + name="conversation_view_btn" + top="3" + width="31" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + name="conversations_gear_btn" + top="3" + width="31" /> + </panel> + <panel + follows="all" + height="370" + layout="topleft" + left="5" + name="buttons_panel" + right="-5" + top_pad="5"> + <conversation_log_list + opaque="true" + allow_select="true" + follows="all" + height="360" + layout="topleft" + left="3" + keep_selection_visible_on_reshape="true" + item_pad="2" + multi_select="false" + name="conversation_log_list" + right="-3" + top="5" /> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml new file mode 100644 index 0000000000..27b744aefb --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_resize="true" + default_tab_group="1" + height="361" + layout="topleft" + min_height="243" + min_width="234" + name="preview_conversation" + title="CONVERSATION:" + width="400"> + <floater.string + name="Title"> + CONVERSATION: [NAME] + </floater.string> + <text + type="string" + length="1" + follows="left|top" + font="SansSerif" + height="19" + layout="topleft" + left="10" + name="desc txt" + top="22" + width="90"> + Description: + </text> + <line_editor + border_style="line" + border_thickness="1" + enabled="false" + follows="left|top|right" + font="SansSerif" + height="22" + layout="topleft" + left_pad="0" + max_length_bytes="127" + name="description" + width="296" /> + <chat_history + font="SansSerifSmall" + follows="all" + visible="true" + height="310" + name="chat_history" + parse_highlights="true" + parse_urls="true" + left="5" + width="390"> + </chat_history> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e5ef80e352..e8ef3c1df9 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -56,6 +56,7 @@ image_overlay="Conv_toolbar_sort" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" + menu_filename="menu_participant_view.xml" layout="topleft" left="10" name="sort_btn" diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml new file mode 100644 index 0000000000..b8d0eef956 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Conversation Context Menu"> + <menu_item_call + label="IM..." + layout="topleft" + name="IM"> + <on_click + function="Calllog.Action" + parameter="im" /> + <on_enable + function="Calllog.Enable" + parameter="can_im" /> + </menu_item_call> + <menu_item_call + label="Voice call..." + layout="topleft" + name="Call"> + <on_click + function="Calllog.Action" + parameter="call" /> + <on_enable + function="Calllog.Enable" + parameter="can_call" /> + </menu_item_call> + <menu_item_call + label="Open chat history..." + layout="topleft" + name="Chat history"> + <on_click + function="Calllog.Action" + parameter="chat_history" /> + <on_enable + function="Calllog.Enable" + parameter="can_view_chat_history" /> + </menu_item_call> + <menu_item_call + label="View Profile" + layout="topleft" + name="View Profile"> + <on_click + function="Calllog.Action" + parameter="view_profile" /> + <on_enable + function="Calllog.Enable" + parameter="can_view_profile" /> + </menu_item_call> + <menu_item_call + label="Offer Teleport" + name="teleport"> + <on_click + function="Calllog.Action" + parameter="offer_teleport"/> + <on_enable + function="Calllog.Enable" + parameter="can_offer_teleport"/> + </menu_item_call> + <menu_item_separator /> + <menu_item_check + label="Add friend/Remove friend" + layout="topleft" + name="Friend_add_remove"> + <menu_item_check.on_click + function="Calllog.Action" + parameter="add_rem_friend" /> + <menu_item_check.on_check + function="Calllog.Check" + parameter="is_friend" /> + <menu_item_check.on_enable + function="Calllog.Enable" + parameter="add_rem_friend" /> + </menu_item_check> + <menu_item_call + label="Invite to group..." + layout="topleft" + name="Invite"> + <on_click + function="Calllog.Action" + parameter="invite_to_group"/> + <on_enable + function="Calllog.Enable" + parameter="can_invite_to_group" /> + </menu_item_call> + <menu_item_separator /> + <menu_item_call + label="Map" + layout="topleft" + name="Map"> + <on_click + function="Calllog.Action" + parameter="show_on_map" /> + <on_enable + function="Calllog.Enable" + parameter="can_show_on_map" /> + </menu_item_call> + <menu_item_call + label="Share" + layout="topleft" + name="Share"> + <on_click + function="Calllog.Action" + parameter="share" /> + <on_enable + function="Calllog.Enable" + parameter="can_share" /> + </menu_item_call> + <menu_item_call + label="Pay" + layout="topleft" + name="Pay"> + <on_click + function="Calllog.Action" + parameter="pay" /> + <on_enable + function="Calllog.Enable" + parameter="can_pay" /> + </menu_item_call> + <menu_item_check + label="Block/Unblock" + layout="topleft" + name="Block/Unblock"> + <menu_item_check.on_click + function="Calllog.Action" + parameter="block"/> + <menu_item_check.on_check + function="Calllog.Check" + parameter="is_blocked" /> + <menu_item_check.on_enable + function="Calllog.Enable" + parameter="can_block" /> + </menu_item_check> + +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml new file mode 100644 index 0000000000..4ab8cb4f7d --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_conversation_view" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_check + label="Sort by name" + name="sort_by_name"> + <on_click + function="CallLog.Action" + parameter="sort_by_name"/> + <on_check + function="CallLog.Check" + parameter="sort_by_name"/> + </menu_item_check> + <menu_item_check + label="Sort by date" + name="sort_by_date"> + <on_click + function="CallLog.Action" + parameter="sort_by_date" /> + <on_check + function="CallLog.Check" + parameter="sort_by_date" /> + </menu_item_check> + <menu_item_separator /> + <menu_item_check + label="Sort friends on top" + name="sort_by_friends"> + <on_click + function="CallLog.Action" + parameter="sort_friends_on_top" /> + <on_check + function="CallLog.Check" + parameter="sort_friends_on_top" /> + </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml new file mode 100644 index 0000000000..6401b0e3b7 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="participant_manu_view"> + <menu_item_check + label="Open conversation log" + name="Conversation" + visible="true"> + <menu_item_check.on_check + function="Floater.Visible" + parameter="conversation" /> + <menu_item_check.on_click + function="Floater.Toggle" + parameter="conversation" /> + </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml new file mode 100644 index 0000000000..3c98e32e7d --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="top|right|left" + height="23" + layout="topleft" + left="0" + name="conversation_log_list_item" + top="0" + width="380"> + <icon + height="24" + follows="top|right|left" + image_name="ListItem_Select" + layout="topleft" + left="0" + name="selected_icon" + top="0" + visible="false" + width="380" /> + <icon + follows="top|right|left" + height="24" + image_name="ListItem_Over" + layout="topleft" + left="0" + name="hovered_icon" + top="0" + visible="false" + width="380" /> + <icon + default_icon_name="voice_session_icon" + follows="top|left" + height="20" + layout="topleft" + left="5" + image_name="Audio_Press" + mouse_opaque="true" + name="voice_session_icon" + top="2" + visible="false" + width="20" /> + <icon + default_icon_name="incoming_unread_im_icon" + follows="top|left" + height="20" + layout="topleft" + left="5" + image_name="Movement_Backward_Off" + mouse_opaque="false" + name="unread_ims_icon" + top="2" + visible="false" + width="20" /> + <avatar_icon + default_icon_name="Generic_Person" + follows="top|left" + height="20" + layout="topleft" + left_pad="5" + mouse_opaque="true" + top="2" + visible="false" + width="20" /> + <group_icon + default_icon_name="Generic_Group" + follows="top|left" + height="20" + layout="topleft" + mouse_opaque="true" + top="2" + visible="false" + width="20" /> + <text + follows="left|right" + font="SansSerifSmall" + font.color="DkGray" + height="15" + layout="topleft" + left_pad="5" + name="conversation_name" + parse_urls="false" + top="6" + use_ellipses="true" + width="180" /> + <text + follows="right" + font="SansSerifSmall" + font.color="DkGray" + height="15" + layout="topleft" + left_pad="5" + name="date_time" + parse_urls="false" + top="6" + use_ellipses="true" + width="110"/> + <button + name="delete_btn" + layout="topleft" + follows="top|right" + image_unselected="Toast_CloseBtn" + image_selected="Toast_CloseBtn" + top="5" + left_pad="0" + height="14" + width="14" + tab_stop="false"/> +</panel> \ No newline at end of file -- cgit v1.2.3 From 1da3e890a6a426113c79513d74e94783c5762409 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 27 Jul 2012 13:38:10 -0700 Subject: CHUI-253 FIX Not able to view the contents of a Buy Contents object for sale --- indra/llui/llsdparam.cpp | 2 +- indra/llxuixml/llinitparam.cpp | 5 +++-- indra/llxuixml/llinitparam.h | 45 +++++++++++++++++++++++++----------------- 3 files changed, 31 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index 54c8389772..9f4460a988 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -303,7 +303,7 @@ namespace LLInitParam { // LLSD specialization // block param interface - bool ParamValue<LLSD, NOT_BLOCK>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) + bool ParamValue<LLSD, NOT_BLOCK>::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack, bool new_name) { if (name_stack.first == name_stack.second && p.readValue<LLSD>(mValue)) diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp index bb160b3c0b..451b638a3f 100644 --- a/indra/llxuixml/llinitparam.cpp +++ b/indra/llxuixml/llinitparam.cpp @@ -181,7 +181,8 @@ namespace LLInitParam bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent) { - if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), true)) + Parser::name_stack_range_t range = std::make_pair(name_stack.begin(), name_stack.end()); + if (!deserializeBlock(p, range, true)) { if (!silent) { @@ -321,7 +322,7 @@ namespace LLInitParam return true; } - bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool ignored) + bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool ignored) { BlockDescriptor& block_data = mostDerivedBlockDescriptor(); bool names_left = name_stack_range.first != name_stack_range.second; diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 606676be2c..a07818dfce 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -571,7 +571,7 @@ namespace LLInitParam }; typedef bool(*merge_func_t)(Param&, const Param&, bool); - typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool); + typedef bool(*deserialize_func_t)(Param&, Parser&, Parser::name_stack_range_t&, bool); typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param); typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count); typedef bool(*validation_func_t)(const Param*); @@ -837,7 +837,7 @@ namespace LLInitParam // Blocks can override this to do custom tracking of changes virtual void paramChanged(const Param& changed_param, bool user_provided) {} - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); + bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name); void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const; @@ -969,7 +969,7 @@ namespace LLInitParam bool isProvided() const { return Param::anyProvided(); } - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { self_t& typed_param = static_cast<self_t&>(param); // no further names in stack, attempt to parse value now @@ -1127,7 +1127,7 @@ namespace LLInitParam } } - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { self_t& typed_param = static_cast<self_t&>(param); // attempt to parse block... @@ -1286,7 +1286,7 @@ namespace LLInitParam } }; - // container of non-block parameters + // list of non-block parameters template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> : public Param @@ -1315,7 +1315,7 @@ namespace LLInitParam bool isProvided() const { return Param::anyProvided(); } - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { Parser::name_stack_range_t new_name_stack_range(name_stack_range); self_t& typed_param = static_cast<self_t&>(param); @@ -1498,7 +1498,7 @@ namespace LLInitParam } }; - // container of block parameters + // list of block parameters template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> : public Param @@ -1527,30 +1527,35 @@ namespace LLInitParam bool isProvided() const { return Param::anyProvided(); } - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { Parser::name_stack_range_t new_name_stack_range(name_stack_range); self_t& typed_param = static_cast<self_t&>(param); bool new_value = false; + bool new_array_value = false; // pop first element if empty string if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty()) { - new_value |= new_name_stack_range.first->second; + new_array_value = new_name_stack_range.first->second; ++new_name_stack_range.first; } - if (new_name || typed_param.mValues.empty()) + + if (new_name || new_array_value || typed_param.mValues.empty()) { new_value = true; typed_param.mValues.push_back(value_t()); } - param_value_t& value = typed_param.mValues.back(); // attempt to parse block... if(value.deserializeBlock(parser, new_name_stack_range, new_name)) { typed_param.setProvided(); + if (new_array_value) + { + name_stack_range.first->second = false; + } return true; } else if(named_value_t::valueNamesExist()) @@ -1564,6 +1569,10 @@ namespace LLInitParam { typed_param.mValues.back().setValueName(name); typed_param.setProvided(); + if (new_array_value) + { + name_stack_range.first->second = false; + } return true; } @@ -2036,7 +2045,7 @@ namespace LLInitParam } } - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { if (name_stack_range.first == name_stack_range.second) { @@ -2149,14 +2158,14 @@ namespace LLInitParam return mValue.getValue(); } - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) + bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name) { if (new_name) { resetToDefault(); } return mValue.deserializeBlock(p, name_stack_range, new_name); - } + } void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const { @@ -2242,7 +2251,7 @@ namespace LLInitParam return mValue.getValue(); } - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) + bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name) { if (new_name) { @@ -2372,7 +2381,7 @@ namespace LLInitParam return mValue.get().getValue(); } - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) + bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name) { return mValue.get().deserializeBlock(p, name_stack_range, new_name); } @@ -2481,7 +2490,7 @@ namespace LLInitParam LLSD& getValue() { return mValue; } // block param interface - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); + bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name); void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const { @@ -2524,7 +2533,7 @@ namespace LLInitParam mValidated(false) {} - bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack_range, bool new_name) + bool deserializeBlock(Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { derived_t& typed_param = static_cast<derived_t&>(*this); // try to parse direct value T -- cgit v1.2.3 From e9c436e00e36710228a7d8856d18e116c0b17503 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 27 Jul 2012 13:43:38 -0700 Subject: fixed line endings --- .../default/xui/en/floater_conversation_log.xml | 168 ++++++++++----------- 1 file changed, 84 insertions(+), 84 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml index 1c5800e25f..9cdeb0d788 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -1,84 +1,84 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> - -<floater - can_resize="true" - positioning="cascading" - height="400" - min_height="100" - min_width="390" - layout="topleft" - name="floater_conversation_log" - save_rect="true" - single_instance="true" - reuse_instance="true" - title="CONVERSATION LOG" - width="450"> - <panel - follows="left|top|right" - height="27" - layout="topleft" - left="0" - name="buttons_panel" - top="0"> - <filter_editor - follows="left|top|right" - height="23" - layout="topleft" - left="8" - label="Filter People" - max_length_chars="300" - name="people_filter_input" - text_color="Black" - text_pad_left="10" - top="4" - width="364" /> - <menu_button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Conv_toolbar_sort" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="5" - menu_filename="menu_conversation_log_view.xml" - menu_position="bottomleft" - name="conversation_view_btn" - top="3" - width="31" /> - <menu_button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="2" - name="conversations_gear_btn" - top="3" - width="31" /> - </panel> - <panel - follows="all" - height="370" - layout="topleft" - left="5" - name="buttons_panel" - right="-5" - top_pad="5"> - <conversation_log_list - opaque="true" - allow_select="true" - follows="all" - height="360" - layout="topleft" - left="3" - keep_selection_visible_on_reshape="true" - item_pad="2" - multi_select="false" - name="conversation_log_list" - right="-3" - top="5" /> - </panel> -</floater> +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> + +<floater + can_resize="true" + positioning="cascading" + height="400" + min_height="100" + min_width="390" + layout="topleft" + name="floater_conversation_log" + save_rect="true" + single_instance="true" + reuse_instance="true" + title="CONVERSATION LOG" + width="450"> + <panel + follows="left|top|right" + height="27" + layout="topleft" + left="0" + name="buttons_panel" + top="0"> + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="8" + label="Filter People" + max_length_chars="300" + name="people_filter_input" + text_color="Black" + text_pad_left="10" + top="4" + width="364" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_sort" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="5" + menu_filename="menu_conversation_log_view.xml" + menu_position="bottomleft" + name="conversation_view_btn" + top="3" + width="31" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + name="conversations_gear_btn" + top="3" + width="31" /> + </panel> + <panel + follows="all" + height="370" + layout="topleft" + left="5" + name="buttons_panel" + right="-5" + top_pad="5"> + <conversation_log_list + opaque="true" + allow_select="true" + follows="all" + height="360" + layout="topleft" + left="3" + keep_selection_visible_on_reshape="true" + item_pad="2" + multi_select="false" + name="conversation_log_list" + right="-3" + top="5" /> + </panel> +</floater> -- cgit v1.2.3 From f9ccd6bc9d9a1da849ac21913ff870e2db8ad6a1 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Fri, 27 Jul 2012 23:46:25 +0300 Subject: Fixed line endings in files added in CHUI-151. --- indra/newview/llfloaterconversationlog.cpp | 254 ++++++++++++++--------------- indra/newview/llfloaterconversationlog.h | 122 +++++++------- 2 files changed, 188 insertions(+), 188 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index 569ba12ed6..c77a9e74bb 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -1,127 +1,127 @@ -/** - * @file llfloaterconversationlog.cpp - * @brief Functionality of the "conversation log" floater - * - * $LicenseInfo:firstyear=2012&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ -#include "llviewerprecompiledheaders.h" - -#include "llconversationloglist.h" -#include "llfiltereditor.h" -#include "llfloaterconversationlog.h" -#include "llmenubutton.h" - -LLFloaterConversationLog::LLFloaterConversationLog(const LLSD& key) -: LLFloater(key), - mConversationLogList(NULL) -{ - mCommitCallbackRegistrar.add("CallLog.Action", boost::bind(&LLFloaterConversationLog::onCustomAction, this, _2)); - mEnableCallbackRegistrar.add("CallLog.Check", boost::bind(&LLFloaterConversationLog::isActionChecked, this, _2)); -} - -BOOL LLFloaterConversationLog::postBuild() -{ - mConversationLogList = getChild<LLConversationLogList>("conversation_log_list"); - - switch (gSavedSettings.getU32("CallLogSortOrder")) - { - case E_SORT_BY_NAME: - mConversationLogList->sortByName(); - break; - - case E_SORT_BY_DATE: - mConversationLogList->sortByDate(); - break; - } - - // Use the context menu of the Conversation list for the Conversation tab gear menu. - LLToggleableMenu* conversations_gear_menu = mConversationLogList->getContextMenu(); - if (conversations_gear_menu) - { - getChild<LLMenuButton>("conversations_gear_btn")->setMenu(conversations_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); - } - - getChild<LLFilterEditor>("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); - - return LLFloater::postBuild(); -} - -void LLFloaterConversationLog::draw() -{ - LLFloater::draw(); -} - -void LLFloaterConversationLog::onFilterEdit(const std::string& search_string) -{ - std::string filter = search_string; - LLStringUtil::trimHead(filter); - - mConversationLogList->setNameFilter(filter); -} - - -void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) -{ - const std::string command_name = userdata.asString(); - - if ("sort_by_name" == command_name) - { - mConversationLogList->sortByName(); - gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_NAME); - } - else if ("sort_by_date" == command_name) - { - mConversationLogList->sortByDate(); - gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_DATE); - } - else if ("sort_friends_on_top" == command_name) - { - mConversationLogList->toggleSortFriendsOnTop(); - } -} - -bool LLFloaterConversationLog::isActionEnabled(const LLSD& userdata) -{ - return true; -} - -bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) -{ - const std::string command_name = userdata.asString(); - - U32 sort_order = gSavedSettings.getU32("CallLogSortOrder"); - - if ("sort_by_name" == command_name) - { - return sort_order == E_SORT_BY_NAME; - } - else if ("sort_by_date" == command_name) - { - return sort_order == E_SORT_BY_DATE; - } - else if ("sort_friends_on_top" == command_name) - { - return gSavedSettings.getBOOL("SortFriendsFirst"); - } - - return false; -} +/** + * @file llfloaterconversationlog.cpp + * @brief Functionality of the "conversation log" floater + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#include "llviewerprecompiledheaders.h" + +#include "llconversationloglist.h" +#include "llfiltereditor.h" +#include "llfloaterconversationlog.h" +#include "llmenubutton.h" + +LLFloaterConversationLog::LLFloaterConversationLog(const LLSD& key) +: LLFloater(key), + mConversationLogList(NULL) +{ + mCommitCallbackRegistrar.add("CallLog.Action", boost::bind(&LLFloaterConversationLog::onCustomAction, this, _2)); + mEnableCallbackRegistrar.add("CallLog.Check", boost::bind(&LLFloaterConversationLog::isActionChecked, this, _2)); +} + +BOOL LLFloaterConversationLog::postBuild() +{ + mConversationLogList = getChild<LLConversationLogList>("conversation_log_list"); + + switch (gSavedSettings.getU32("CallLogSortOrder")) + { + case E_SORT_BY_NAME: + mConversationLogList->sortByName(); + break; + + case E_SORT_BY_DATE: + mConversationLogList->sortByDate(); + break; + } + + // Use the context menu of the Conversation list for the Conversation tab gear menu. + LLToggleableMenu* conversations_gear_menu = mConversationLogList->getContextMenu(); + if (conversations_gear_menu) + { + getChild<LLMenuButton>("conversations_gear_btn")->setMenu(conversations_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); + } + + getChild<LLFilterEditor>("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); + + return LLFloater::postBuild(); +} + +void LLFloaterConversationLog::draw() +{ + LLFloater::draw(); +} + +void LLFloaterConversationLog::onFilterEdit(const std::string& search_string) +{ + std::string filter = search_string; + LLStringUtil::trimHead(filter); + + mConversationLogList->setNameFilter(filter); +} + + +void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + + if ("sort_by_name" == command_name) + { + mConversationLogList->sortByName(); + gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_NAME); + } + else if ("sort_by_date" == command_name) + { + mConversationLogList->sortByDate(); + gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_DATE); + } + else if ("sort_friends_on_top" == command_name) + { + mConversationLogList->toggleSortFriendsOnTop(); + } +} + +bool LLFloaterConversationLog::isActionEnabled(const LLSD& userdata) +{ + return true; +} + +bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + + U32 sort_order = gSavedSettings.getU32("CallLogSortOrder"); + + if ("sort_by_name" == command_name) + { + return sort_order == E_SORT_BY_NAME; + } + else if ("sort_by_date" == command_name) + { + return sort_order == E_SORT_BY_DATE; + } + else if ("sort_friends_on_top" == command_name) + { + return gSavedSettings.getBOOL("SortFriendsFirst"); + } + + return false; +} diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h index 40dd266663..7d788c0290 100644 --- a/indra/newview/llfloaterconversationlog.h +++ b/indra/newview/llfloaterconversationlog.h @@ -1,61 +1,61 @@ -/** - * @file llfloaterconversationlog.h - * - * $LicenseInfo:firstyear=2012&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLFLOATERCONVERSATIONLOG_H_ -#define LL_LLFLOATERCONVERSATIONLOG_H_ - -#include "llfloater.h" - -class LLConversationLogList; - -class LLFloaterConversationLog : public LLFloater -{ -public: - - typedef enum e_sort_oder{ - E_SORT_BY_NAME = 0, - E_SORT_BY_DATE = 1, - } ESortOrder; - - LLFloaterConversationLog(const LLSD& key); - virtual ~LLFloaterConversationLog(){}; - - virtual BOOL postBuild(); - - virtual void draw(); - - void onFilterEdit(const std::string& search_string); - -private: - - void onCustomAction (const LLSD& userdata); - bool isActionEnabled(const LLSD& userdata); - bool isActionChecked(const LLSD& userdata); - - LLConversationLogList* mConversationLogList; -}; - - -#endif /* LLFLOATERCONVERSATIONLOG_H_ */ +/** + * @file llfloaterconversationlog.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERCONVERSATIONLOG_H_ +#define LL_LLFLOATERCONVERSATIONLOG_H_ + +#include "llfloater.h" + +class LLConversationLogList; + +class LLFloaterConversationLog : public LLFloater +{ +public: + + typedef enum e_sort_oder{ + E_SORT_BY_NAME = 0, + E_SORT_BY_DATE = 1, + } ESortOrder; + + LLFloaterConversationLog(const LLSD& key); + virtual ~LLFloaterConversationLog(){}; + + virtual BOOL postBuild(); + + virtual void draw(); + + void onFilterEdit(const std::string& search_string); + +private: + + void onCustomAction (const LLSD& userdata); + bool isActionEnabled(const LLSD& userdata); + bool isActionChecked(const LLSD& userdata); + + LLConversationLogList* mConversationLogList; +}; + + +#endif /* LLFLOATERCONVERSATIONLOG_H_ */ -- cgit v1.2.3 From 3ba619053de562fc623263704af2bc2f415e8389 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 27 Jul 2012 14:10:29 -0700 Subject: CHUI-256 FIX Invalid param warnings in llfolderview when adding and deleting items from object inventory --- indra/newview/llconversationlog.h | 2 +- indra/newview/llimfloatercontainer.cpp | 1 + indra/newview/llinventorypanel.cpp | 1 + indra/newview/llpanelobjectinventory.cpp | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 700472ca8b..18865bb80e 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -31,7 +31,7 @@ #include "llimview.h" class LLConversationLogObserver; -class Conversation_params; +struct Conversation_params; typedef LLIMModel::LLIMSession::SType SessionType; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index c19683b1c2..74f089811e 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -107,6 +107,7 @@ BOOL LLIMFloaterContainer::postBuild() p.rect = mConversationsListPanel->getLocalRect(); p.follows.flags = FOLLOWS_ALL; p.listener = base_item; + p.root = NULL; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); mConversationsListPanel->addChild(mConversationsRoot); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 6a7ee3b6a0..be1cd2510d 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -659,6 +659,7 @@ LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool u p.allow_multiselect = mAllowMultiSelect; p.show_empty_message = mShowEmptyMessage; p.show_item_link_overlays = mShowItemLinkOverlays; + p.root = NULL; return LLUICtrlFactory::create<LLFolderView>(p); } diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 5887f4d244..4f2c515bde 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1563,6 +1563,7 @@ void LLPanelObjectInventory::reset() p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL); p.folder_indentation = -14; // subtract space normally reserved for folder expanders p.view_model = &mInventoryViewModel; + p.root = NULL; mFolders = LLUICtrlFactory::create<LLFolderView>(p); // this ensures that we never say "searching..." or "no items found" //TODO RN: make this happen by manipulating filter object directly -- cgit v1.2.3 From 0479e8d4ad1212b0028805cd4e39b6fe593b86c7 Mon Sep 17 00:00:00 2001 From: Todd Stinson <stinson@lindenlab.com> Date: Fri, 27 Jul 2012 14:28:31 -0700 Subject: Updating comments for merge conflicts after reviewing with Richard. --- indra/llui/llfolderviewitem.cpp | 4 ++-- indra/newview/llimfloater.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index cd8d8bafbc..777e778bc0 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1495,7 +1495,7 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) item->getViewModelItem()->dirtyFilter(); - // XXX stinson TODO : handle the creation date + // TODO RN - port creation date management to new code location #if 0 // Update the folder creation date if the child is newer than our current date setCreationDate(llmax<time_t>(mCreationDate, item->getCreationDate())); @@ -1506,7 +1506,7 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) requestSort(); getViewModelItem()->addChild(item->getViewModelItem()); - // XXX stinson TODO : handle the creation date + // TODO RN - port creation date management to new code location #if 0 // Traverse parent folders and update creation date and resort, if necessary LLFolderViewFolder* parentp = getParentFolder(); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 5e0e0973fc..260957011e 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -316,7 +316,7 @@ BOOL LLIMFloater::postBuild() mInputEditor = getChild<LLChatEntry>("chat_editor"); mInputEditor->setMaxTextLength(1023); // enable line history support for instant message bar - // XXX stinson TODO : resolve merge conflict + // XXX stinson TODO : resolve merge by adding autoreplace to text editors #if 0 // *TODO Establish LineEditor with autoreplace callback mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); -- cgit v1.2.3 From ca7b9a944b164602cd8b11bf6512f790743964f3 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 27 Jul 2012 14:36:23 -0700 Subject: build fix --- indra/llui/tests/llurlentry_stub.cpp | 2 +- indra/llui/tests/llurlmatch_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index 61e30d89d0..20e98adf2b 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -123,7 +123,7 @@ namespace LLInitParam { descriptor.mCurrentBlockPtr = this; } - bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name){ return true; } + bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack, bool new_name){ return true; } void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const {} bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_value, S32 max_value) const { return true; } bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index 97fe5b2eea..f37d270844 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -93,7 +93,7 @@ namespace LLInitParam mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16; } - bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name){ return true; } + bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack, bool new_name){ return true; } void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const {} bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const { return true; } bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } -- cgit v1.2.3 From 0b5abcfa8e2adbeb9c9f12644f36ee2c4daee560 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 27 Jul 2012 16:14:31 +0300 Subject: Micro fix for string.xml --- indra/newview/skins/default/xui/en/strings.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 9ccd6b5cbe..752710373c 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2140,8 +2140,10 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale <string name="InvFolder Gestures">Gestures</string> <string name="InvFolder Favorite">My Favorites</string> <!-- historically default name of the Favorites folder can start from either "f" or "F" letter. - We should localize both of them with the same value --> + Also, it can be written as "Favorite" or "Favorites". + We should localize all variants of them with the same value --> <string name="InvFolder favorite">My Favorites</string> + <string name="InvFolder Favorites">My Favorites</string> <string name="InvFolder Current Outfit">Current Outfit</string> <string name="InvFolder Initial Outfits">Initial Outfits</string> <string name="InvFolder My Outfits">My Outfits</string> @@ -2150,6 +2152,7 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale <!-- are used for Friends and Friends/All folders in Inventory "Calling cards" folder. See EXT-694--> <string name="InvFolder Friends">Friends</string> + <string name="InvFolder Received Items">Received Items</string> <string name="InvFolder All">All</string> <string name="no_attachments">No attachments worn</string> -- cgit v1.2.3 From 209fd15176647a4b8defbb6e66daea6eb12d4b42 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Mon, 30 Jul 2012 19:38:27 +0300 Subject: CHUI-244 FIX for propagating the dirty filter flag to the folder view item's parent. The filter dirty flag is set after a new child item is added to ensure that this item already has a parent and the dirty flag can be bubbled up. --- indra/llui/llfolderviewitem.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 777e778bc0..b9b6ea7444 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1492,8 +1492,6 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) item->setVisible(FALSE); addChild(item); - - item->getViewModelItem()->dirtyFilter(); // TODO RN - port creation date management to new code location #if 0 @@ -1531,6 +1529,8 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) // parentp = parentp->getParentFolder(); //} + item->getViewModelItem()->dirtyFilter(); + return TRUE; } @@ -1547,13 +1547,14 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) folder->reshape(getRect().getWidth(), 0); folder->setVisible(FALSE); addChild( folder ); - folder->getViewModelItem()->dirtyFilter(); // rearrange all descendants too, as our indentation level might have changed folder->requestArrange(); requestSort(); getViewModelItem()->addChild(folder->getViewModelItem()); + folder->getViewModelItem()->dirtyFilter(); + return TRUE; } -- cgit v1.2.3 From 9fa3407c9c18e0e9592bd659a515ec0b77ba13bd Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 30 Jul 2012 11:35:01 -0700 Subject: CHUI-213: When a new folder is added to inventory, its parent is assigned before calling dirtyFilter(). This allows dirtyFilter() to propogate the dirty flag up. --- indra/llui/llfolderviewitem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index b9b6ea7444..2f17fa7c35 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1552,8 +1552,8 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) requestSort(); getViewModelItem()->addChild(folder->getViewModelItem()); - - folder->getViewModelItem()->dirtyFilter(); + //After addChild since addChild assigns parent to bubble up to when calling dirtyFilter + folder->getViewModelItem()->dirtyFilter(); return TRUE; } -- cgit v1.2.3 From 4285cc271eacaca31a1d5d76c8e88debf00235c2 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Mon, 30 Jul 2012 15:15:42 -0700 Subject: CHUI-217 FIX Items are not visible in Merchant Outbox cleaned up a lot custom code for folder view item creation in inbox and outbox proper initialization of views from inventory panel starting folder --- indra/llui/llfolderviewitem.cpp | 13 +- indra/llui/llfolderviewitem.h | 10 +- indra/llui/lluictrlfactory.cpp | 5 - indra/llui/lluictrlfactory.h | 5 +- indra/newview/CMakeLists.txt | 2 - indra/newview/llagentwearablesfetch.cpp | 2 +- indra/newview/llappearancemgr.cpp | 2 +- indra/newview/llfloateroutbox.cpp | 3 +- indra/newview/llinventorybridge.cpp | 16 +- indra/newview/llinventorybridge.h | 12 +- indra/newview/llinventorymodel.cpp | 46 ++++- indra/newview/llinventorymodel.h | 9 +- indra/newview/llinventorypanel.cpp | 198 ++++++++++++--------- indra/newview/llinventorypanel.h | 59 ++++-- indra/newview/llpanellandmarks.cpp | 12 +- indra/newview/llpanelmarketplaceinboxinventory.cpp | 70 +------- indra/newview/llpanelmarketplaceinboxinventory.h | 13 +- .../newview/llpanelmarketplaceoutboxinventory.cpp | 141 --------------- indra/newview/llpanelmarketplaceoutboxinventory.h | 78 -------- indra/newview/llplacesinventorybridge.cpp | 4 +- indra/newview/llplacesinventorybridge.h | 2 +- indra/newview/llplacesinventorypanel.cpp | 5 - indra/newview/llplacesinventorypanel.h | 6 +- indra/newview/llsidepanelinventory.cpp | 3 +- indra/newview/lltooldraganddrop.cpp | 2 +- indra/newview/pipeline.cpp | 2 +- .../skins/default/xui/en/panel_inbox_inventory.xml | 2 +- .../skins/default/xui/en/panel_landmarks.xml | 8 +- .../default/xui/en/panel_outbox_inventory.xml | 18 +- .../xui/en/widgets/inbox_inventory_panel.xml | 3 +- .../xui/en/widgets/outbox_folder_view_folder.xml | 9 - .../xui/en/widgets/outbox_inventory_panel.xml | 2 - 32 files changed, 282 insertions(+), 480 deletions(-) delete mode 100644 indra/newview/llpanelmarketplaceoutboxinventory.cpp delete mode 100644 indra/newview/llpanelmarketplaceoutboxinventory.h delete mode 100644 indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml delete mode 100644 indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index b9b6ea7444..1d8dfbbafa 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -89,7 +89,8 @@ LLFolderViewItem::Params::Params() selection_image("selection_image"), item_height("item_height"), item_top_pad("item_top_pad"), - creation_date() + creation_date(), + allow_open("allow_open", true) {} // Default constructor @@ -112,7 +113,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mLabel(p.name), mRoot(p.root), mViewModelItem(p.listener), - mIsMouseOverTitle(false) + mIsMouseOverTitle(false), + mAllowOpen(p.allow_open) { if (mViewModelItem) { @@ -404,7 +406,10 @@ void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) void LLFolderViewItem::openItem( void ) { - getViewModelItem()->openItem(); + if (mAllowOpen) + { + getViewModelItem()->openItem(); + } } void LLFolderViewItem::rename(const std::string& new_name) @@ -517,7 +522,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) { - getViewModelItem()->openItem(); + openItem(); return TRUE; } diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 50d3e0580e..df007dd15d 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -61,6 +61,7 @@ public: item_top_pad; Optional<time_t> creation_date; + Optional<bool> allow_open; Params(); }; @@ -92,14 +93,11 @@ protected: bool mLabelWidthDirty; LLFolderViewFolder* mParentFolder; LLFolderViewModelItem* mViewModelItem; - BOOL mIsCurSelection; - BOOL mSelectPending; LLFontGL::StyleFlags mLabelStyle; std::string mLabelSuffix; LLUIImagePtr mIcon; LLUIImagePtr mIconOpen; LLUIImagePtr mIconOverlay; - BOOL mHasVisibleChildren; S32 mIndentation; S32 mItemHeight; S32 mDragStartX, @@ -109,8 +107,12 @@ protected: //std::string::size_type mStringMatchOffset; F32 mControlLabelRotation; LLFolderView* mRoot; - BOOL mDragAndDropTarget; + bool mHasVisibleChildren; + bool mIsCurSelection; + bool mDragAndDropTarget; bool mIsMouseOverTitle; + bool mAllowOpen; + bool mSelectPending; // this is an internal method used for adding items to folders. A // no-op at this level, but reimplemented in derived classes. diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index f64f33bc5e..91a6b3259c 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -304,9 +304,4 @@ void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const st //LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type, &get_empty_param_block<T>); } -//static -const std::string* LLUICtrlFactory::getWidgetName(const std::type_info* widget_type) -{ - return LLWidgetNameRegistry::instance().getValue(widget_type); -} diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index b441cb0c9d..9f18be2371 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -105,7 +105,7 @@ private: ParamDefaults() { // look up template file for this param block... - const std::string* param_block_tag = getWidgetName(&typeid(PARAM_BLOCK)); + const std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK)); if (param_block_tag) { // ...and if it exists, back fill values using the most specific template first PARAM_BLOCK params; @@ -139,7 +139,6 @@ public: template<typename T> static const typename T::Params& getDefaultParams() { - //#pragma message("Generating ParamDefaults") return ParamDefaults<typename T::Params, 0>::instance().get(); } @@ -303,8 +302,6 @@ private: } - static const std::string* getWidgetName(const std::type_info* widget_type); - // this exists to get around dependency on llview static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b71f13a450..626fb8caa5 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -383,7 +383,6 @@ set(viewer_SOURCE_FILES llpanelmaininventory.cpp llpanelmarketplaceinbox.cpp llpanelmarketplaceinboxinventory.cpp - llpanelmarketplaceoutboxinventory.cpp llpanelmediasettingsgeneral.cpp llpanelmediasettingspermissions.cpp llpanelmediasettingssecurity.cpp @@ -942,7 +941,6 @@ set(viewer_HEADER_FILES llpanelmaininventory.h llpanelmarketplaceinbox.h llpanelmarketplaceinboxinventory.h - llpanelmarketplaceoutboxinventory.h llpanelmediasettingsgeneral.h llpanelmediasettingspermissions.h llpanelmediasettingssecurity.h diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index e2417cdddb..e31e39dca2 100644 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -342,7 +342,7 @@ void LLLibraryOutfitsFetch::folderDone() } mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); - mLibraryClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); + mLibraryClothingID = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_CLOTHING, false); // If Library->Clothing->Initial Outfits exists, use that. LLNameCategoryCollector matchFolderFunctor("Initial Outfits"); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 6d67e098a6..510abf198a 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2330,7 +2330,7 @@ void LLAppearanceMgr::copyLibraryGestures() // Copy gestures LLUUID lib_gesture_cat_id = - gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE,false,true); + gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_GESTURE,false); if (lib_gesture_cat_id.isNull()) { llwarns << "Unable to copy gestures, source category not found" << llendl; diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index 04a55b261c..e4ed97892e 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -174,9 +174,8 @@ void LLFloaterOutbox::onOpen(const LLSD& key) if (mOutboxId.isNull()) { const bool do_not_create_folder = false; - const bool do_not_find_in_library = false; - const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library); + const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder); if (outbox_id.isNull()) { diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 9f1d4bdec9..14616ca7ab 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -955,7 +955,7 @@ BOOL LLInvFVBridge::isCOFFolder() const BOOL LLInvFVBridge::isInboxFolder() const { - const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false); + const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false); if (inbox_id.isNull()) { @@ -995,7 +995,7 @@ BOOL LLInvFVBridge::isOutboxFolderDirectParent() const const LLUUID LLInvFVBridge::getOutboxFolder() const { - const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); + const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); return outbox_id; } @@ -1330,7 +1330,7 @@ LLToolDragAndDrop::ESource LLInvFVBridge::getDragSource() const // +=================================================+ // | InventoryFVBridgeBuilder | // +=================================================+ -LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type, +LLInvFVBridge* LLInventoryFolderViewModelBuilder::createBridge(LLAssetType::EType asset_type, LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, @@ -1438,7 +1438,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) LLInventoryItem* itemp = model->getItem(mUUID); if (!itemp) return; - const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); + const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); copy_item_to_outbox(itemp, outbox_id, LLUUID::null, LLToolDragAndDrop::getOperationId()); } } @@ -2469,7 +2469,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } else { - if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false))) + if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false))) { set_dad_inbox_object(cat_id); } @@ -2909,7 +2909,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) LLInventoryCategory * cat = gInventory.getCategory(mUUID); if (!cat) return; - const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); + const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); copy_folder_to_outbox(cat, outbox_id, cat->getUUID(), LLToolDragAndDrop::getOperationId()); } #if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU @@ -4068,7 +4068,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, else { // set up observer to select item once drag and drop from inbox is complete - if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false))) + if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false))) { set_dad_inbox_object(inv_item->getUUID()); } @@ -6487,7 +6487,7 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( } else { - new_listener = LLInventoryFVBridgeBuilder::createBridge(asset_type, + new_listener = LLInventoryFolderViewModelBuilder::createBridge(asset_type, actual_asset_type, inv_type, inventory, diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 9997d1720f..fc0b15acad 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -185,15 +185,15 @@ protected: }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInvFVBridgeBuilder +// Class LLInventoryFolderViewModelBuilder // -// This class intended to build Folder View Bridge via LLInvFVBridge::createBridge. -// It can be overridden with another way of creation necessary Inventory-Folder-View-Bridge. +// This class intended to build Folder View Model via LLInvFVBridge::createBridge. +// It can be overridden with another way of creation necessary Inventory Folder View Models. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryFVBridgeBuilder +class LLInventoryFolderViewModelBuilder { public: - virtual ~LLInventoryFVBridgeBuilder() {} + virtual ~LLInventoryFolderViewModelBuilder() {} virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type, LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, @@ -637,7 +637,7 @@ public: }; // Bridge builder to create Inventory-Folder-View-Bridge for Recent Inventory Panel -class LLRecentInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder +class LLRecentInventoryBridgeBuilder : public LLInventoryFolderViewModelBuilder { public: // Overrides FolderBridge for Recent Inventory Panel. diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 5cb7f53bfa..0673970d89 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -373,13 +373,12 @@ void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id) // specifies 'type' as what it defaults to containing. The category is // not necessarily only for that type. *NOTE: This will create a new // inventory category on the fly if one does not exist. -const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type, - bool create_folder, - bool find_in_library) +const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder/*, + bool find_in_library*/) { LLUUID rv = LLUUID::null; - const LLUUID &root_id = (find_in_library) ? gInventory.getLibraryRootFolderID() : gInventory.getRootFolderID(); + const LLUUID &root_id = /*(find_in_library) ? gInventory.getLibraryRootFolderID() :*/ gInventory.getRootFolderID(); if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) { rv = root_id; @@ -402,7 +401,44 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe } } - if(rv.isNull() && isInventoryUsable() && (create_folder && !find_in_library)) + if(rv.isNull() && isInventoryUsable() && (create_folder && true/*!find_in_library*/)) + { + if(root_id.notNull()) + { + return createNewCategory(root_id, preferred_type, LLStringUtil::null); + } + } + return rv; +} + +const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder) +{ + LLUUID rv = LLUUID::null; + + const LLUUID &root_id = gInventory.getLibraryRootFolderID(); + if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) + { + rv = root_id; + } + else if (root_id.notNull()) + { + cat_array_t* cats = NULL; + cats = get_ptr_in_map(mParentChildCategoryTree, root_id); + if(cats) + { + S32 count = cats->count(); + for(S32 i = 0; i < count; ++i) + { + if(cats->get(i)->getPreferredType() == preferred_type) + { + rv = cats->get(i)->getUUID(); + break; + } + } + } + } + + if(rv.isNull() && isInventoryUsable() && (create_folder && true/*!find_in_library*/)) { if(root_id.notNull()) { diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 3613bc4917..503de627a0 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -231,11 +231,12 @@ public: // Returns the uuid of the category that specifies 'type' as what it // defaults to containing. The category is not necessarily only for that type. // NOTE: If create_folder is true, this will create a new inventory category - // on the fly if one does not exist. *NOTE: if find_in_library is true it - // will search in the user's library folder instead of "My Inventory" + // on the fly if one does not exist. const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type, - bool create_folder = true, - bool find_in_library = false); + bool create_folder = true); + // will search in the user's library folder instead of "My Inventory" + const LLUUID findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type, + bool create_folder = true); // Get whatever special folder this object is a child of, if any. const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index be1cd2510d..e9b128e836 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -55,7 +55,7 @@ static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel"); const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder"); const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder"); const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); -static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; +static const LLInventoryFolderViewModelBuilder INVENTORY_BRIDGE_BUILDER; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryPanelObserver @@ -140,7 +140,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : { mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER; - // contex menu callbacks + // context menu callbacks mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2)); mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)); mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); @@ -151,71 +151,60 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : } -void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) -{ - // Determine the root folder in case specified, and - // build the views starting with that folder. - - std::string start_folder_name(params.start_folder()); - - const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(start_folder_name); - - LLUUID root_id; - - if ("LIBRARY" == params.start_folder()) - { - root_id = gInventory.getLibraryRootFolderID(); - } - else - { - root_id = (preferred_type != LLFolderType::FT_NONE) - ? gInventory.findCategoryUUIDForType(preferred_type, false, false) - : LLUUID::null; - } - - if ((root_id == LLUUID::null) && !start_folder_name.empty()) - { - llwarns << "No category found that matches start_folder: " << start_folder_name << llendl; - root_id = LLUUID::generateNewID(); - } - - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, - LLAssetType::AT_CATEGORY, - LLInventoryType::IT_CATEGORY, - this, - &mInventoryViewModel, - NULL, - root_id); - - mFolderRoot = createFolderView(new_listener, params.use_label_suffix()); - addItemID(root_id, mFolderRoot); -} void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) { + // save off copy of params + mParams = params; // Clear up the root view // Note: This needs to be done *before* we build the new folder view - LLFolderViewItem* root_view = getItemByID(gInventory.getRootFolderID()); - if (root_view) + LLUUID root_id = getRootFolderID(); + if (mFolderRoot) { - removeItemID(static_cast<LLFolderViewModelItemInventory*>(root_view->getViewModelItem())->getUUID()); - root_view->destroyView(); + removeItemID(root_id); + mFolderRoot->destroyView(); + mFolderRoot = NULL; } LLMemType mt(LLMemType::MTYPE_INVENTORY_POST_BUILD); - - mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves - buildFolderView(params); - + mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves + { + // Determine the root folder in case specified, and + // build the views starting with that folder. + + + LLFolderView::Params p(mParams.folder_view); + p.name = getName(); + p.title = getLabel(); + p.rect = LLRect(0, 0, getRect().getWidth(), 0); + p.parent_panel = this; + p.tool_tip = p.name; + p.listener = mInvFVBridgeBuilder->createBridge( LLAssetType::AT_CATEGORY, + LLAssetType::AT_CATEGORY, + LLInventoryType::IT_CATEGORY, + this, + &mInventoryViewModel, + NULL, + root_id); + p.view_model = &mInventoryViewModel; + p.use_label_suffix = mParams.use_label_suffix; + p.allow_multiselect = mAllowMultiSelect; + p.show_empty_message = mShowEmptyMessage; + p.show_item_link_overlays = mShowItemLinkOverlays; + p.root = NULL; + + mFolderRoot = LLUICtrlFactory::create<LLFolderView>(p); + + addItemID(root_id, mFolderRoot); + } mCommitCallbackRegistrar.popScope(); - mFolderRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); // Scroller LLRect scroller_view_rect = getRect(); scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); - LLScrollContainer::Params scroller_params(params.scroll()); + LLScrollContainer::Params scroller_params(mParams.scroll()); scroller_params.rect(scroller_view_rect); mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); addChild(mScroller); @@ -263,7 +252,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) mClipboardState = LLClipboard::instance().getGeneration(); // Initialize base class params. - LLPanel::initFromParams(params); + LLPanel::initFromParams(mParams); } LLInventoryPanel::~LLInventoryPanel() @@ -562,7 +551,40 @@ LLFolderView* LLInventoryPanel::getRootFolder() LLUUID LLInventoryPanel::getRootFolderID() { - return static_cast<LLFolderViewModelItemInventory*>(mFolderRoot->getViewModelItem())->getUUID(); + if (mFolderRoot && mFolderRoot->getViewModelItem()) + { + return static_cast<LLFolderViewModelItemInventory*>(mFolderRoot->getViewModelItem())->getUUID(); + + } + else + { + LLUUID root_id; + if (mParams.start_folder.id.isChosen()) + { + root_id = mParams.start_folder.id; + } + else + { + const LLFolderType::EType preferred_type = mParams.start_folder.type.isChosen() + ? mParams.start_folder.type + : LLViewerFolderType::lookupTypeFromNewCategoryName(mParams.start_folder.name); + + if ("LIBRARY" == mParams.start_folder.name()) + { + root_id = gInventory.getLibraryRootFolderID(); + } + else if (preferred_type != LLFolderType::FT_NONE) + { + root_id = gInventory.findCategoryUUIDForType(preferred_type, false); + if (root_id.isNull()) + { + llwarns << "Could not find folder of type " << preferred_type << llendl; + root_id.generateNewID(); + } + } + } + return root_id; + } } @@ -612,7 +634,16 @@ void LLInventoryPanel::initializeViews() { if (!gInventory.isInventoryUsable()) return; - buildNewViews(gInventory.getRootFolderID()); + LLUUID root_id = getRootFolderID(); + if (root_id.notNull()) + { + buildNewViews(getRootFolderID()); + } + else + { + buildNewViews(gInventory.getRootFolderID()); + buildNewViews(gInventory.getLibraryRootFolderID()); + } gIdleCallbacks.addFunction(idle, this); @@ -639,34 +670,10 @@ void LLInventoryPanel::initializeViews() } } -LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix) -{ - LLRect folder_rect(0, - 0, - getRect().getWidth(), - 0); - - LLFolderView::Params p; - - p.name = getName(); - p.title = getLabel(); - p.rect = folder_rect; - p.parent_panel = this; - p.tool_tip = p.name; - p.listener = bridge; - p.view_model = &mInventoryViewModel; - p.use_label_suffix = useLabelSuffix; - p.allow_multiselect = mAllowMultiSelect; - p.show_empty_message = mShowEmptyMessage; - p.show_item_link_overlays = mShowItemLinkOverlays; - p.root = NULL; - - return LLUICtrlFactory::create<LLFolderView>(p); -} LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge) { - LLFolderViewFolder::Params params; + LLFolderViewFolder::Params params(mParams.folder); params.name = bridge->getDisplayName(); params.root = mFolderRoot; @@ -678,7 +685,7 @@ LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * br LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge) { - LLFolderViewItem::Params params; + LLFolderViewItem::Params params(mParams.item); params.name = bridge->getDisplayName(); params.creation_date = bridge->getCreationDate(); @@ -1329,3 +1336,34 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params) mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER; } +namespace LLInitParam +{ + void TypeValues<LLFolderType::EType>::declareValues() + { + declare(LLFolderType::lookup(LLFolderType::FT_TEXTURE) , LLFolderType::FT_TEXTURE); + declare(LLFolderType::lookup(LLFolderType::FT_SOUND) , LLFolderType::FT_SOUND); + declare(LLFolderType::lookup(LLFolderType::FT_CALLINGCARD) , LLFolderType::FT_CALLINGCARD); + declare(LLFolderType::lookup(LLFolderType::FT_LANDMARK) , LLFolderType::FT_LANDMARK); + declare(LLFolderType::lookup(LLFolderType::FT_CLOTHING) , LLFolderType::FT_CLOTHING); + declare(LLFolderType::lookup(LLFolderType::FT_OBJECT) , LLFolderType::FT_OBJECT); + declare(LLFolderType::lookup(LLFolderType::FT_NOTECARD) , LLFolderType::FT_NOTECARD); + declare(LLFolderType::lookup(LLFolderType::FT_ROOT_INVENTORY) , LLFolderType::FT_ROOT_INVENTORY); + declare(LLFolderType::lookup(LLFolderType::FT_LSL_TEXT) , LLFolderType::FT_LSL_TEXT); + declare(LLFolderType::lookup(LLFolderType::FT_BODYPART) , LLFolderType::FT_BODYPART); + declare(LLFolderType::lookup(LLFolderType::FT_TRASH) , LLFolderType::FT_TRASH); + declare(LLFolderType::lookup(LLFolderType::FT_SNAPSHOT_CATEGORY), LLFolderType::FT_SNAPSHOT_CATEGORY); + declare(LLFolderType::lookup(LLFolderType::FT_LOST_AND_FOUND) , LLFolderType::FT_LOST_AND_FOUND); + declare(LLFolderType::lookup(LLFolderType::FT_ANIMATION) , LLFolderType::FT_ANIMATION); + declare(LLFolderType::lookup(LLFolderType::FT_GESTURE) , LLFolderType::FT_GESTURE); + declare(LLFolderType::lookup(LLFolderType::FT_FAVORITE) , LLFolderType::FT_FAVORITE); + declare(LLFolderType::lookup(LLFolderType::FT_ENSEMBLE_START) , LLFolderType::FT_ENSEMBLE_START); + declare(LLFolderType::lookup(LLFolderType::FT_ENSEMBLE_END) , LLFolderType::FT_ENSEMBLE_END); + declare(LLFolderType::lookup(LLFolderType::FT_CURRENT_OUTFIT) , LLFolderType::FT_CURRENT_OUTFIT); + declare(LLFolderType::lookup(LLFolderType::FT_OUTFIT) , LLFolderType::FT_OUTFIT); + declare(LLFolderType::lookup(LLFolderType::FT_MY_OUTFITS) , LLFolderType::FT_MY_OUTFITS); + declare(LLFolderType::lookup(LLFolderType::FT_MESH ) , LLFolderType::FT_MESH ); + declare(LLFolderType::lookup(LLFolderType::FT_INBOX) , LLFolderType::FT_INBOX); + declare(LLFolderType::lookup(LLFolderType::FT_OUTBOX) , LLFolderType::FT_OUTBOX); + declare(LLFolderType::lookup(LLFolderType::FT_BASIC_ROOT) , LLFolderType::FT_BASIC_ROOT); + } +} diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 910325cdbc..b66b53f642 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -41,10 +41,19 @@ #include <set> class LLInvFVBridge; -class LLInventoryFVBridgeBuilder; +class LLInventoryFolderViewModelBuilder; class LLInvPanelComplObserver; class LLFolderViewModelInventory; +namespace LLInitParam +{ + template<> + struct TypeValues<LLFolderType::EType> : public TypeValuesHelper<LLFolderType::EType> + { + static void declareValues(); + }; +} + class LLInventoryPanel : public LLPanel { //-------------------------------------------------------------------- @@ -64,6 +73,19 @@ public: {} }; + struct StartFolder : public LLInitParam::ChoiceBlock<StartFolder> + { + Alternative<std::string> name; + Alternative<LLUUID> id; + Alternative<LLFolderType::EType> type; + + StartFolder() + : name("name"), + id("id"), + type("type") + {} + }; + struct Params : public LLInitParam::Block<Params, LLPanel::Params> { @@ -72,11 +94,14 @@ public: Optional<bool> allow_multi_select; Optional<bool> show_item_link_overlays; Optional<Filter> filter; - Optional<std::string> start_folder; + Optional<StartFolder> start_folder; Optional<bool> use_label_suffix; Optional<bool> show_empty_message; Optional<LLScrollContainer::Params> scroll; Optional<bool> accepts_drag_and_drop; + Optional<LLFolderView::Params> folder_view; + Optional<LLFolderViewFolder::Params> folder; + Optional<LLFolderViewItem::Params> item; Params() : sort_order_setting("sort_order_setting"), @@ -88,7 +113,10 @@ public: use_label_suffix("use_label_suffix", true), show_empty_message("show_empty_message", true), scroll("scroll"), - accepts_drag_and_drop("accepts_drag_and_drop") + accepts_drag_and_drop("accepts_drag_and_drop"), + folder_view("folder_view"), + folder("folder"), + item("item") {} }; @@ -98,6 +126,7 @@ public: protected: LLInventoryPanel(const Params&); void initFromParams(const Params&); + friend class LLUICtrlFactory; public: virtual ~LLInventoryPanel(); @@ -187,29 +216,30 @@ protected: void openStartFolderOrMyInventory(); // open the first level of inventory void onItemsCompletion(); // called when selected items are complete - LLUUID mSelectThisID; + LLUUID mSelectThisID; LLInventoryModel* mInventory; LLInventoryObserver* mInventoryObserver; LLInvPanelComplObserver* mCompletionObserver; - BOOL mAcceptsDragAndDrop; - BOOL mAllowMultiSelect; - BOOL mShowItemLinkOverlays; // Shows link graphic over inventory item icons - BOOL mShowEmptyMessage; + bool mAcceptsDragAndDrop; + bool mAllowMultiSelect; + bool mShowItemLinkOverlays; // Shows link graphic over inventory item icons + bool mShowEmptyMessage; LLFolderView* mFolderRoot; LLScrollContainer* mScroller; LLFolderViewModelInventory mInventoryViewModel; + Params mParams; // stored copy of parameter block std::map<LLUUID, LLFolderViewItem*> mItemMap; /** - * Pointer to LLInventoryFVBridgeBuilder. + * Pointer to LLInventoryFolderViewModelBuilder. * * It is set in LLInventoryPanel's constructor and can be overridden in derived classes with * another implementation. * Take into account it will not be deleted by LLInventoryPanel itself. */ - const LLInventoryFVBridgeBuilder* mInvFVBridgeBuilder; + const LLInventoryFolderViewModelBuilder* mInvFVBridgeBuilder; //-------------------------------------------------------------------- @@ -239,19 +269,14 @@ protected: // Builds the UI. Call this once the inventory is usable. void initializeViews(); - virtual void buildFolderView(const LLInventoryPanel::Params& params); LLFolderViewItem* buildNewViews(const LLUUID& id); BOOL getIsHiddenFolderType(LLFolderType::EType folder_type) const; - virtual LLFolderView* createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix); virtual LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge); virtual LLFolderViewItem* createFolderViewItem(LLInvFVBridge * bridge); private: - BOOL mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild() - BOOL mViewsInitialized; // Views have been generated - // UUID of category from which hierarchy should be built. Set with the - // "start_folder" xml property. Default is LLUUID::null that means total Inventory hierarchy. - LLUUID mStartFolderID; + bool mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild() + bool mViewsInitialized; // Views have been generated }; #endif // LL_LLINVENTORYPANEL_H diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 4bbab52e5a..1a4f3708ac 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -177,7 +177,7 @@ void LLLandmarksPanelObserver::changed(U32 mask) if (!mIsLibraryLandmarksOpen && library) { // Search for "Landmarks" folder in the Library and open it once on start up. See EXT-4827. - const LLUUID &landmarks_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false, true); + const LLUUID &landmarks_cat = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); if (landmarks_cat.notNull()) { LLOpenFolderByID opener(landmarks_cat); @@ -306,8 +306,7 @@ bool LLLandmarksPanel::isSingleItemSelected() if (mCurrentSelectedList != NULL) { - LLPlacesFolderView* root_view = - static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder()); + LLFolderView* root_view = mCurrentSelectedList->getRootFolder(); if (root_view->getSelectedCount() == 1) { @@ -588,7 +587,7 @@ void LLLandmarksPanel::initLibraryInventoryPanel() initLandmarksPanel(mLibraryInventoryPanel); // We want to fetch only "Landmarks" category from the library. - const LLUUID &landmarks_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false, true); + const LLUUID &landmarks_cat = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); if (landmarks_cat.notNull()) { LLInventoryModelBackgroundFetch::instance().start(landmarks_cat); @@ -918,8 +917,9 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const { std::string command_name = userdata.asString(); - LLPlacesFolderView* root_folder_view = mCurrentSelectedList ? - static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder()) : NULL; + LLFolderView* root_folder_view = mCurrentSelectedList + ? mCurrentSelectedList->getRootFolder() + : NULL; if ("collapse_all" == command_name) { diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index 6e5a522297..8ad3929999 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -54,69 +54,11 @@ static LLDefaultChildRegistry::Register<LLInboxFolderViewItem> r3("inbox_folder_ // LLInboxInventoryPanel::LLInboxInventoryPanel(const LLInboxInventoryPanel::Params& p) - : LLInventoryPanel(p) -{ -} +: LLInventoryPanel(p) +{} LLInboxInventoryPanel::~LLInboxInventoryPanel() -{ -} - -// virtual -void LLInboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) -{ - // Determine the root folder in case specified, and - // build the views starting with that folder. - - LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false); - - // leslie -- temporary HACK to work around sim not creating inbox with proper system folder type - if (root_id.isNull()) - { - std::string start_folder_name(params.start_folder()); - - LLInventoryModel::cat_array_t* cats; - LLInventoryModel::item_array_t* items; - - gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items); - - if (cats) - { - for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it) - { - LLInventoryCategory* cat = *cat_it; - - if (cat->getName() == start_folder_name) - { - root_id = cat->getUUID(); - break; - } - } - } - - if (root_id == LLUUID::null) - { - llwarns << "No category found that matches inbox inventory panel start_folder: " << start_folder_name << llendl; - } - } - // leslie -- end temporary HACK - - if (root_id == LLUUID::null) - { - llwarns << "Inbox inventory panel has no root folder!" << llendl; - root_id = LLUUID::generateNewID(); - } - - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, - LLAssetType::AT_CATEGORY, - LLInventoryType::IT_CATEGORY, - this, - &mInventoryViewModel, - NULL, - root_id); - - mFolderRoot = createFolderView(new_listener, params.use_label_suffix()); -} +{} LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge) { @@ -149,9 +91,9 @@ LLFolderViewItem * LLInboxInventoryPanel::createFolderViewItem(LLInvFVBridge * b // LLInboxFolderViewFolder::LLInboxFolderViewFolder(const Params& p) - : LLFolderViewFolder(p) - , LLBadgeOwner(getHandle()) - , mFresh(false) +: LLFolderViewFolder(p), + LLBadgeOwner(getHandle()), + mFresh(false) { #if SUPPORTING_FRESH_ITEM_COUNT initBadgeParams(p.new_badge()); diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h index 209f3a4098..d8b8a2fe63 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.h +++ b/indra/newview/llpanelmarketplaceinboxinventory.h @@ -46,9 +46,6 @@ public: LLInboxInventoryPanel(const Params& p); ~LLInboxInventoryPanel(); - // virtual - void buildFolderView(const LLInventoryPanel::Params& params); - // virtual LLFolderViewFolder * createFolderViewFolder(LLInvFVBridge * bridge); LLFolderViewItem * createFolderViewItem(LLInvFVBridge * bridge); @@ -63,9 +60,8 @@ public: Optional<LLBadge::Params> new_badge; Params() - : new_badge("new_badge") - { - } + : new_badge("new_badge") + {} }; LLInboxFolderViewFolder(const Params& p); @@ -93,9 +89,8 @@ public: Optional<LLBadge::Params> new_badge; Params() - : new_badge("new_badge") - { - } + : new_badge("new_badge") + {} }; LLInboxFolderViewItem(const Params& p); diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp deleted file mode 100644 index 2885dd6266..0000000000 --- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/** - * @file llpanelmarketplaceoutboxinventory.cpp - * @brief LLOutboxInventoryPanel class definition - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelmarketplaceoutboxinventory.h" - -#include "llfolderviewitem.h" -#include "llfolderviewmodel.h" -#include "llinventorybridge.h" -#include "llinventoryfunctions.h" -#include "llpanellandmarks.h" -#include "llplacesinventorybridge.h" -#include "lltrans.h" -#include "llviewerfoldertype.h" - - -// -// statics -// - -static LLDefaultChildRegistry::Register<LLOutboxInventoryPanel> r1("outbox_inventory_panel"); -static LLDefaultChildRegistry::Register<LLOutboxFolderViewFolder> r2("outbox_folder_view_folder"); - - -// -// LLOutboxInventoryPanel Implementation -// - -LLOutboxInventoryPanel::LLOutboxInventoryPanel(const LLOutboxInventoryPanel::Params& p) - : LLInventoryPanel(p) -{ -} - -LLOutboxInventoryPanel::~LLOutboxInventoryPanel() -{ -} - -// virtual -void LLOutboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) -{ - // Determine the root folder in case specified, and - // build the views starting with that folder. - - LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); - - if (root_id == LLUUID::null) - { - llwarns << "Outbox inventory panel has no root folder!" << llendl; - root_id = LLUUID::generateNewID(); - } - - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, - LLAssetType::AT_CATEGORY, - LLInventoryType::IT_CATEGORY, - this, - &mInventoryViewModel, - NULL, - root_id); - - mFolderRoot = createFolderView(new_listener, params.use_label_suffix()); -} - -LLFolderViewFolder * LLOutboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge) -{ - LLOutboxFolderViewFolder::Params params; - - params.name = bridge->getDisplayName(); - params.root = mFolderRoot; - params.listener = bridge; - params.tool_tip = params.name; - - return LLUICtrlFactory::create<LLOutboxFolderViewFolder>(params); -} - -LLFolderViewItem * LLOutboxInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge) -{ - LLFolderViewItem::Params params; - - params.name = bridge->getDisplayName(); - params.creation_date = bridge->getCreationDate(); - params.root = mFolderRoot; - params.listener = bridge; - params.rect = LLRect (0, 0, 0, 0); - params.tool_tip = params.name; - - return LLUICtrlFactory::create<LLOutboxFolderViewItem>(params); -} - -// -// LLOutboxFolderViewFolder Implementation -// - -LLOutboxFolderViewFolder::LLOutboxFolderViewFolder(const Params& p) - : LLFolderViewFolder(p) -{ -} - -// -// LLOutboxFolderViewItem Implementation -// - -LLOutboxFolderViewItem::LLOutboxFolderViewItem(const Params& p) - : LLFolderViewItem(p) -{ -} - -BOOL LLOutboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask) -{ - return TRUE; -} - -void LLOutboxFolderViewItem::openItem() -{ - // Intentionally do nothing to block attaching items from the outbox -} - -// eof diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.h b/indra/newview/llpanelmarketplaceoutboxinventory.h deleted file mode 100644 index a6c522b7c2..0000000000 --- a/indra/newview/llpanelmarketplaceoutboxinventory.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file llpanelmarketplaceoutboxinventory.h - * @brief LLOutboxInventoryPanel class declaration - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_OUTBOXINVENTORYPANEL_H -#define LL_OUTBOXINVENTORYPANEL_H - - -#include "llinventorypanel.h" -#include "llfolderviewitem.h" - - -class LLOutboxInventoryPanel : public LLInventoryPanel -{ -public: - struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params> - { - Params() {} - }; - - LLOutboxInventoryPanel(const Params& p); - ~LLOutboxInventoryPanel(); - - // virtual - void buildFolderView(const LLInventoryPanel::Params& params); - - // virtual - LLFolderViewFolder * createFolderViewFolder(LLInvFVBridge * bridge); - LLFolderViewItem * createFolderViewItem(LLInvFVBridge * bridge); -}; - - -class LLOutboxFolderViewFolder : public LLFolderViewFolder -{ -public: - struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params> - { - Params() {} - }; - - LLOutboxFolderViewFolder(const Params& p); -}; - - -class LLOutboxFolderViewItem : public LLFolderViewItem -{ -public: - LLOutboxFolderViewItem(const Params& p); - - // virtual - BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - void openItem(); -}; - - -#endif //LL_OUTBOXINVENTORYPANEL_H diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index 1a5f64e295..ebd9604c5b 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -170,7 +170,7 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) { // *TODO: Create a link folder handler instead if it is necessary - new_listener = LLInventoryFVBridgeBuilder::createBridge( + new_listener = LLInventoryFolderViewModelBuilder::createBridge( asset_type, actual_asset_type, inv_type, @@ -184,7 +184,7 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( new_listener = new LLPlacesFolderBridge(inv_type, inventory, root, uuid); break; default: - new_listener = LLInventoryFVBridgeBuilder::createBridge( + new_listener = LLInventoryFolderViewModelBuilder::createBridge( asset_type, actual_asset_type, inv_type, diff --git a/indra/newview/llplacesinventorybridge.h b/indra/newview/llplacesinventorybridge.h index 791502990b..07d18d03c5 100644 --- a/indra/newview/llplacesinventorybridge.h +++ b/indra/newview/llplacesinventorybridge.h @@ -82,7 +82,7 @@ protected: * * It builds Bridges for Landmarks and Folders in Places Landmarks Panel */ -class LLPlacesInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder +class LLPlacesInventoryBridgeBuilder : public LLInventoryFolderViewModelBuilder { public: /*virtual*/ LLInvFVBridge* createBridge(LLAssetType::EType asset_type, diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index c46681f556..db3f245389 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -58,11 +58,6 @@ LLPlacesInventoryPanel::~LLPlacesInventoryPanel() delete mSavedFolderState; } -void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) -{ - LLInventoryPanel::buildFolderView(params); -} - // save current folder open state void LLPlacesInventoryPanel::saveFolderState() { diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h index f647e7f970..1544b51aed 100644 --- a/indra/newview/llplacesinventorypanel.h +++ b/indra/newview/llplacesinventorypanel.h @@ -46,8 +46,6 @@ public: LLPlacesInventoryPanel(const Params& p); ~LLPlacesInventoryPanel(); - /*virtual*/ void buildFolderView(const LLInventoryPanel::Params& params); - void saveFolderState(); void restoreFolderState(); @@ -57,7 +55,7 @@ private: LLSaveFolderState* mSavedFolderState; }; - +//TODO RN: this class is currently unused, make sure that behavior remains class LLPlacesFolderView : public LLFolderView { public: @@ -77,8 +75,6 @@ public: mParentLandmarksPanel = panel; } - S32 getSelectedCount() { return (S32)mSelectedItems.size(); } - private: /** * holds pointer to landmark panel. This pointer is used in @c LLPlacesFolderView::handleRightMouseDown diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 47bd620fc6..acb232c77f 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -260,9 +260,8 @@ void LLSidepanelInventory::updateInbox() // const bool do_not_create_folder = false; - const bool do_not_find_in_library = false; - const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder, do_not_find_in_library); + const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder); // Set up observer to listen for creation of inbox if at least one of them doesn't exist if (inbox_id.isNull()) diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 2680e4451b..94c97158a8 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -812,7 +812,7 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, if (!handled) { // Disallow drag and drop to 3D from the outbox - const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); + const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); if (outbox_id.notNull()) { for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++) diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 7c744f3c3f..9268e5a869 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -5318,7 +5318,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) // crazy cast so that we can overwrite the fade value // even though gcc enforces sets as const // (fade value doesn't affect sort so this is safe) - Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin())))); + Light* farthest_light = (const_cast<Light*>(&(*(mNearbyLights.rbegin())))); if (light->dist < farthest_light->dist) { if (farthest_light->fade >= 0.f) diff --git a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml index 413e22e444..48d38d50e0 100644 --- a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml @@ -2,7 +2,7 @@ <inbox_inventory_panel accepts_drag_and_drop="false" name="inventory_inbox" - start_folder="Received Items" + start_folder.name="Received Items" follows="all" layout="topleft" top="0" left="0" height="165" width="308" top_pad="0" diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index 2a5933e3e9..39805637a0 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -35,7 +35,7 @@ left="0" mouse_opaque="true" name="favorites_list" - start_folder="Favorites" + start_folder.name="Favorites" width="307"/> </accordion_tab> <accordion_tab @@ -51,7 +51,7 @@ left="0" mouse_opaque="true" name="landmarks_list" - start_folder="Landmarks" + start_folder.name="Landmarks" width="307"/> </accordion_tab> <accordion_tab @@ -67,7 +67,7 @@ left="0" mouse_opaque="true" name="my_inventory_list" - start_folder="My Inventory" + start_folder.name="My Inventory" width="307"/> </accordion_tab> <accordion_tab @@ -83,7 +83,7 @@ left="0" mouse_opaque="true" name="library_list" - start_folder="LIBRARY" + start_folder.name="LIBRARY" width="313"/> </accordion_tab> </accordion> diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml index a3d39e55af..203febbf18 100644 --- a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml @@ -1,7 +1,10 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<outbox_inventory_panel +<inventory_panel name="inventory_outbox" - start_folder="Outbox" + start_folder.name="Outbox" + show_empty_message="false" + show_load_status="false" + start_folder.type="outbox" follows="all" layout="topleft" top="0" left="0" height="165" width="308" top_pad="0" @@ -12,6 +15,11 @@ bevel_style="none" show_item_link_overlays="true" tool_tip="Drag and drop items here to prepare them for sale on your storefront" - > - <scroll reserve_scroll_corner="false" /> -</outbox_inventory_panel> + scroll.reserve_scroll_corner="false"> + <folder folder_arrow_image="Folder_Arrow" + folder_indentation="8" + item_height="20" + item_top_pad="4" + selection_image="Rounded_Square"/> + <item allow_open="false"/> +</inventory_panel> diff --git a/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml index 830c27bdac..d5b10e7f51 100644 --- a/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml +++ b/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml @@ -1,2 +1,3 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<inbox_inventory_panel show_load_status="false" /> +<inbox_inventory_panel show_load_status="false" + start_folder.type="inbox"/> diff --git a/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml b/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml deleted file mode 100644 index d19c47f54f..0000000000 --- a/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<outbox_folder_view_folder - folder_arrow_image="Folder_Arrow" - folder_indentation="8" - item_height="20" - item_top_pad="4" - selection_image="Rounded_Square" - > -</outbox_folder_view_folder> diff --git a/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml deleted file mode 100644 index 3964569da2..0000000000 --- a/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<outbox_inventory_panel show_empty_message="false" show_load_status="false" /> -- cgit v1.2.3 From f29bdc27b3038a19317095ef914bd560f3199d28 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Mon, 30 Jul 2012 15:16:01 -0700 Subject: moved method from places inventory up into common llfolderview --- indra/llui/llfolderview.h | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index ba37a11bbe..5ebd8f73ac 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -217,6 +217,7 @@ public: BOOL getShowSingleSelection() { return mShowSingleSelection; } F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } bool getUseEllipses() { return mUseEllipses; } + S32 getSelectedCount() { return (S32)mSelectedItems.size(); } void update(); // needs to be called periodically (e.g. once per frame) -- cgit v1.2.3 From b57d8e9c06e01cc6aa2eca17fa80da0a36a52b91 Mon Sep 17 00:00:00 2001 From: Todd Stinson <stinson@lindenlab.com> Date: Mon, 30 Jul 2012 19:09:48 -0700 Subject: CHUI-258: Adding a method to better whether nearby chat is visible or not. --- indra/newview/llnearbychat.cpp | 29 ++++++++++++++++++++++ indra/newview/llnearbychat.h | 3 +-- indra/newview/llnotificationtiphandler.cpp | 2 +- .../newview/skins/default/xui/en/notifications.xml | 16 ++++++++++++ 4 files changed, 47 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 4e53082c05..3bd5f96add 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -419,6 +419,35 @@ void LLNearbyChat::show() setVisible(TRUE); } +bool LLNearbyChat::isChatVisible() const +{ + bool isVisible = false; + + if (isChatMultiTab()) + { + LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + // Is the IM floater container ever null? + llassert(im_box != NULL); + if (im_box != NULL) + { + if (gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) + { + isVisible = (im_box->getVisible() && !im_box->isMinimized()); + } + else + { + isVisible = (getVisible() && !isMinimized()); + } + } + } + else + { + isVisible = (getVisible() && !isMinimized()); + } + + return isVisible; +} + void LLNearbyChat::showHistory() { openFloater(); diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 90feb71488..a0928e67ef 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -66,6 +66,7 @@ public: void addToHost(); void show(); + bool isChatVisible() const; /** @param archive true - to save a message to the chat history log */ void addMessage (const LLChat& message,bool archive = true, const LLSD &args = LLSD()); @@ -99,8 +100,6 @@ protected: /* virtual */ bool applyRectControl(); - void onToggleNearbyChatPanel(); - /*virtual*/ void onTearOffClicked(); static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 507c6686fd..a420c0d2ed 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -86,7 +86,7 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) // don't show toast if Nearby Chat is opened LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - if (!nearby_chat->isMinimized() && nearby_chat->getVisible()) + if (nearby_chat->isChatVisible()) { return false; } diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 3d057fa8f5..f3d2762d3f 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4204,6 +4204,8 @@ Are you sure you want to change the Estate Covenant? <notification icon="notifytip.tga" name="RegionEntryAccessBlocked_Notify" + log_to_im="false" + log_to_chat="true" type="notifytip"> <tag>fail</tag> The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. @@ -4212,6 +4214,8 @@ The region you're trying to visit contains [REGIONMATURITY] content, but your cu <notification icon="notifytip.tga" name="RegionEntryAccessBlocked_NotifyAdultsOnly" + log_to_im="false" + log_to_chat="true" type="notifytip"> <tag>fail</tag> The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. @@ -4283,6 +4287,8 @@ The region you're trying to visit contains [REGIONMATURITY] content, but your cu <notification icon="notifytip.tga" name="TeleportEntryAccessBlocked_Notify" + log_to_im="false" + log_to_chat="true" type="notifytip"> <unique> <context>REGIONMATURITY</context> @@ -4294,6 +4300,8 @@ The region you're trying to visit contains [REGIONMATURITY] content, but your cu <notification icon="notifytip.tga" name="TeleportEntryAccessBlocked_NotifyAdultsOnly" + log_to_im="false" + log_to_chat="true" type="notifytip"> <unique> <context>REGIONMATURITY</context> @@ -4414,6 +4422,8 @@ You won't receive any more notifications that you're about to visit a region wit <notification icon="notifytip.tga" name="LandClaimAccessBlocked_Notify" + log_to_im="false" + log_to_chat="true" type="notifytip"> The land you're trying to claim contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. <tag>fail</tag> @@ -4422,6 +4432,8 @@ You won't receive any more notifications that you're about to visit a region wit <notification icon="notifytip.tga" name="LandClaimAccessBlocked_NotifyAdultsOnly" + log_to_im="false" + log_to_chat="true" type="notifytip"> <tag>fail</tag> The land you're trying to claim contains [REGIONMATURITY] content, which is accessible to adults only. @@ -4479,6 +4491,8 @@ You won't receive any more notifications that you're about to visit a region wit <notification icon="notifytip.tga" name="LandBuyAccessBlocked_Notify" + log_to_im="false" + log_to_chat="true" type="notifytip"> The land you're trying to buy contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. <tag>fail</tag> @@ -4487,6 +4501,8 @@ You won't receive any more notifications that you're about to visit a region wit <notification icon="notifytip.tga" name="LandBuyAccessBlocked_NotifyAdultsOnly" + log_to_im="false" + log_to_chat="true" type="notifytip"> <tag>fail</tag> The land you're trying to buy contains [REGIONMATURITY] content, which is accessible to adults only. -- cgit v1.2.3 From c8bc6a9d663c3abcaeec270eb443e30a9108afc4 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 30 Jul 2012 19:47:02 -0700 Subject: CHUI-229 : Fix disappearance of nearby chat list item by forcing all list widgets to be visible. --- indra/newview/llimfloatercontainer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index adcd840dfc..405a2b3255 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -418,6 +418,7 @@ void LLIMFloaterContainer::repositioningWidgets() widget_it++, ++index) { LLFolderViewItem* widget = widget_it->second; + widget->setVisible(TRUE); widget->setRect(LLRect(0, panel_rect.getHeight() - item_height*index, panel_rect.getWidth(), @@ -461,7 +462,7 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI widget->setVisible(TRUE); repositioningWidgets(); - + mConversationsListPanel->addChild(widget); return; -- cgit v1.2.3 From b7536a307cc51aadacc375a2376dde199f26a7d6 Mon Sep 17 00:00:00 2001 From: Todd Stinson <stinson@lindenlab.com> Date: Tue, 31 Jul 2012 13:48:59 -0700 Subject: CHUI-258: Ensuring that the teleport lure requests are logged to IM and not to nearby chat. --- indra/newview/skins/default/xui/en/notifications.xml | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index f3d2762d3f..e85637826d 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6413,6 +6413,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th icon="notify.tga" name="TeleportOffered" log_to_im="true" + log_to_chat="false" type="offer"> [NAME_SLURL] has offered to teleport you to their location: @@ -6434,6 +6435,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th <notification icon="notify.tga" name="TeleportOffered_MaturityExceeded" + log_to_im="true" + log_to_chat="false" type="offer"> [NAME_SLURL] has offered to teleport you to their location: @@ -6457,6 +6460,8 @@ This region contains [REGION_CONTENT_MATURITY] content, but your current prefere <notification icon="notify.tga" name="TeleportOffered_MaturityBlocked" + log_to_im="true" + log_to_chat="false" type="notifytip"> [NAME_SLURL] has offered to teleport you to their location: @@ -6471,6 +6476,7 @@ However, this region contains content accessible to adults only. icon="notify.tga" name="TeleportOfferSent" log_to_im="true" + log_to_chat="false" show_toast="false" type="offer"> Teleport offer sent to [TO_NAME] -- cgit v1.2.3 From bc54fc2750c02ea11e8485efc541739a90d9cb3f Mon Sep 17 00:00:00 2001 From: Todd Stinson <stinson@lindenlab.com> Date: Tue, 31 Jul 2012 16:33:36 -0700 Subject: CHUI-259: Resovling an issue introduced during the recent merge that incorrectly altered the conditional scope of when nametag text segments were created. --- indra/newview/llvoavatar.cpp | 316 +++++++++++++++++++++---------------------- 1 file changed, 158 insertions(+), 158 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index e5362261cf..2871b7b018 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3124,191 +3124,191 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) { debugAvatarRezTime("AvatarRezLeftAppearanceNotification","left appearance mode"); } + } - // Rebuild name tag if state change detected - if (mNameString.empty() - || new_name - || (!title && !mTitle.empty()) - || (title && mTitle != title->getString()) - || is_away != mNameAway - || is_busy != mNameBusy - || is_muted != mNameMute - || is_appearance != mNameAppearance - || is_friend != mNameFriend - || is_cloud != mNameCloud) - { - LLColor4 name_tag_color = getNameTagColor(is_friend); + // Rebuild name tag if state change detected + if (mNameString.empty() + || new_name + || (!title && !mTitle.empty()) + || (title && mTitle != title->getString()) + || is_away != mNameAway + || is_busy != mNameBusy + || is_muted != mNameMute + || is_appearance != mNameAppearance + || is_friend != mNameFriend + || is_cloud != mNameCloud) + { + LLColor4 name_tag_color = getNameTagColor(is_friend); - clearNameTag(); + clearNameTag(); - if (is_away || is_muted || is_busy || is_appearance) + if (is_away || is_muted || is_busy || is_appearance) + { + std::string line; + if (is_away) { - std::string line; - if (is_away) - { - line += LLTrans::getString("AvatarAway"); - line += ", "; - } - if (is_busy) - { - line += LLTrans::getString("AvatarBusy"); - line += ", "; - } - if (is_muted) - { - line += LLTrans::getString("AvatarMuted"); - line += ", "; - } - if (is_appearance) - { - line += LLTrans::getString("AvatarEditingAppearance"); - line += ", "; - } - if (is_cloud) - { - line += LLTrans::getString("LoadingData"); - line += ", "; - } - // trim last ", " - line.resize( line.length() - 2 ); - addNameTagLine(line, name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall()); + line += LLTrans::getString("AvatarAway"); + line += ", "; } - - if (sRenderGroupTitles - && title && title->getString() && title->getString()[0] != '\0') + if (is_busy) { - std::string title_str = title->getString(); - LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); - addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall()); + line += LLTrans::getString("AvatarBusy"); + line += ", "; } - - static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames"); - static LLUICachedControl<bool> show_usernames("NameTagShowUsernames"); - - if (LLAvatarNameCache::useDisplayNames()) + if (is_muted) { - LLAvatarName av_name; - if (!LLAvatarNameCache::get(getID(), &av_name)) - { - // ...call this function back when the name arrives - // and force a rebuild - LLAvatarNameCache::get(getID(), - boost::bind(&LLVOAvatar::clearNameTag, this)); - } - - // Might be blank if name not available yet, that's OK - if (show_display_names) - { - addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerif()); - } - // Suppress SLID display if display name matches exactly (ugh) - if (show_usernames && !av_name.mIsDisplayNameDefault) - { - // *HACK: Desaturate the color - LLColor4 username_color = name_tag_color * 0.83f; - addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall()); - } + line += LLTrans::getString("AvatarMuted"); + line += ", "; } - else + if (is_appearance) { - const LLFontGL* font = LLFontGL::getFontSansSerif(); - std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); - addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font); + line += LLTrans::getString("AvatarEditingAppearance"); + line += ", "; } - - mNameAway = is_away; - mNameBusy = is_busy; - mNameMute = is_muted; - mNameAppearance = is_appearance; - mNameFriend = is_friend; - mNameCloud = is_cloud; - mTitle = title ? title->getString() : ""; - LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); - new_name = TRUE; + if (is_cloud) + { + line += LLTrans::getString("LoadingData"); + line += ", "; + } + // trim last ", " + line.resize( line.length() - 2 ); + addNameTagLine(line, name_tag_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerifSmall()); } - if (mVisibleChat) + if (sRenderGroupTitles + && title && title->getString() && title->getString()[0] != '\0') { - mNameText->setFont(LLFontGL::getFontSansSerif()); - mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); + std::string title_str = title->getString(); + LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); + addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerifSmall()); + } - char line[MAX_STRING]; /* Flawfinder: ignore */ - line[0] = '\0'; - std::deque<LLChat>::iterator chat_iter = mChats.begin(); - mNameText->clearString(); + static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames"); + static LLUICachedControl<bool> show_usernames("NameTagShowUsernames"); - LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); - LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); - LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); - if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) + if (LLAvatarNameCache::useDisplayNames()) + { + LLAvatarName av_name; + if (!LLAvatarNameCache::get(getID(), &av_name)) { - ++chat_iter; + // ...call this function back when the name arrives + // and force a rebuild + LLAvatarNameCache::get(getID(), + boost::bind(&LLVOAvatar::clearNameTag, this)); } - for(; chat_iter != mChats.end(); ++chat_iter) + // Might be blank if name not available yet, that's OK + if (show_display_names) { - F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); - LLFontGL::StyleFlags style; - switch(chat_iter->mChatType) - { - case CHAT_TYPE_WHISPER: - style = LLFontGL::ITALIC; - break; - case CHAT_TYPE_SHOUT: - style = LLFontGL::BOLD; - break; - default: - style = LLFontGL::NORMAL; - break; - } - if (chat_fade_amt < 1.f) - { - F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); - } - else if (chat_fade_amt < 2.f) - { - F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); - } - else if (chat_fade_amt < 3.f) - { - // *NOTE: only remove lines down to minimum number - mNameText->addLine(chat_iter->mText, old_chat, style); - } + addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerif()); } - mNameText->setVisibleOffScreen(TRUE); - - if (mTyping) + // Suppress SLID display if display name matches exactly (ugh) + if (show_usernames && !av_name.mIsDisplayNameDefault) { - S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; - switch(dot_count) - { - case 1: - mNameText->addLine(".", new_chat); - break; - case 2: - mNameText->addLine("..", new_chat); - break; - case 3: - mNameText->addLine("...", new_chat); - break; - } - + // *HACK: Desaturate the color + LLColor4 username_color = name_tag_color * 0.83f; + addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerifSmall()); } } else { - // ...not using chat bubbles, just names - mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - mNameText->setVisibleOffScreen(FALSE); + const LLFontGL* font = LLFontGL::getFontSansSerif(); + std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); + addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font); + } + + mNameAway = is_away; + mNameBusy = is_busy; + mNameMute = is_muted; + mNameAppearance = is_appearance; + mNameFriend = is_friend; + mNameCloud = is_cloud; + mTitle = title ? title->getString() : ""; + LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); + new_name = TRUE; + } + + if (mVisibleChat) + { + mNameText->setFont(LLFontGL::getFontSansSerif()); + mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); + + char line[MAX_STRING]; /* Flawfinder: ignore */ + line[0] = '\0'; + std::deque<LLChat>::iterator chat_iter = mChats.begin(); + mNameText->clearString(); + + LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); + LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); + LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); + if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) + { + ++chat_iter; } + + for(; chat_iter != mChats.end(); ++chat_iter) + { + F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); + LLFontGL::StyleFlags style; + switch(chat_iter->mChatType) + { + case CHAT_TYPE_WHISPER: + style = LLFontGL::ITALIC; + break; + case CHAT_TYPE_SHOUT: + style = LLFontGL::BOLD; + break; + default: + style = LLFontGL::NORMAL; + break; + } + if (chat_fade_amt < 1.f) + { + F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); + } + else if (chat_fade_amt < 2.f) + { + F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); + } + else if (chat_fade_amt < 3.f) + { + // *NOTE: only remove lines down to minimum number + mNameText->addLine(chat_iter->mText, old_chat, style); + } + } + mNameText->setVisibleOffScreen(TRUE); + + if (mTyping) + { + S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; + switch(dot_count) + { + case 1: + mNameText->addLine(".", new_chat); + break; + case 2: + mNameText->addLine("..", new_chat); + break; + case 3: + mNameText->addLine("...", new_chat); + break; + } + + } + } + else + { + // ...not using chat bubbles, just names + mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + mNameText->setVisibleOffScreen(FALSE); } } -- cgit v1.2.3 From e9a484f98d0376a5651d4f6eb5a692db4f77c800 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 31 Jul 2012 23:46:13 -0700 Subject: CHUI-254 : Fix Inventory filter and item draw() to highlight matching substrings in inventory --- indra/llui/llfolderviewitem.cpp | 47 +++++++++++++--------------- indra/llui/llfolderviewitem.h | 2 -- indra/llui/llfolderviewmodel.h | 15 ++++++++- indra/newview/llfolderviewmodelinventory.cpp | 8 ++--- indra/newview/llfolderviewmodelinventory.h | 2 +- indra/newview/llimfloatercontainer.h | 4 ++- indra/newview/llinventoryfilter.cpp | 18 +++++++---- indra/newview/llinventoryfilter.h | 6 ++-- 8 files changed, 58 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 0f486d06c9..368e3caea8 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -106,8 +106,6 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mHasVisibleChildren(FALSE), mIndentation(0), mItemHeight(p.item_height), - //TODO RN: create interface for string highlighting - //mStringMatchOffset(std::string::npos), mControlLabelRotation(0.f), mDragAndDropTarget(FALSE), mLabel(p.name), @@ -778,29 +776,28 @@ void LLFolderViewItem::draw() //--------------------------------------------------------------------------------// // Highlight string match // - //TODO RN: expose interface for highlighting - //if (mStringMatchOffset != std::string::npos) - //{ - // // don't draw backgrounds for zero-length strings - // S32 filter_string_length = getRoot()->getFilterSubString().size(); - // if (filter_string_length > 0) - // { - // std::string combined_string = mLabel + mLabelSuffix; - // S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; - // S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; - // S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); - // S32 top = getRect().getHeight() - TOP_PAD; - // - // LLUIImage* box_image = default_params.selection_image; - // LLRect box_rect(left, top, right, bottom); - // box_image->draw(box_rect, sFilterBGColor); - // F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); - // F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; - // font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, - // sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - // filter_string_length, S32_MAX, &right_x, FALSE ); - // } - //} + if (mViewModelItem->hasFilterStringMatch()) + { + // don't draw backgrounds for zero-length strings + std::string::size_type filter_string_length = mViewModelItem->getFilterStringSize(); + if (filter_string_length > 0) + { + std::string combined_string = mLabel + mLabelSuffix; + S32 left = llround(text_left) + font->getWidth(combined_string, 0, mViewModelItem->getFilterStringOffset()) - 1; + S32 right = left + font->getWidth(combined_string, mViewModelItem->getFilterStringOffset(), filter_string_length) + 2; + S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); + S32 top = getRect().getHeight() - TOP_PAD; + + LLUIImage* box_image = default_params.selection_image; + LLRect box_rect(left, top, right, bottom); + box_image->draw(box_rect, sFilterBGColor); + F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mViewModelItem->getFilterStringOffset()); + F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + font->renderUTF8( combined_string, mViewModelItem->getFilterStringOffset(), match_string_left, yy, + sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + filter_string_length, S32_MAX, &right_x, FALSE ); + } + } } const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index df007dd15d..e323237b13 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -103,8 +103,6 @@ protected: S32 mDragStartX, mDragStartY; - //TODO RN: create interface for string highlighting - //std::string::size_type mStringMatchOffset; F32 mControlLabelRotation; LLFolderView* mRoot; bool mHasVisibleChildren; diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index acdec53602..f655e6e4d6 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -73,6 +73,8 @@ public: virtual bool showAllResults() const = 0; + virtual std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const = 0; + virtual std::string::size_type getFilterStringSize() const = 0; // +-------------------------------------------------------------------+ // + Status // +-------------------------------------------------------------------+ @@ -155,8 +157,11 @@ public: virtual void filter( LLFolderViewFilter& filter) = 0; virtual bool passedFilter(S32 filter_generation = -1) = 0; virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; - virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) = 0; + virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) = 0; virtual void dirtyFilter() = 0; + virtual bool hasFilterStringMatch() = 0; + virtual std::string::size_type getFilterStringOffset() = 0; + virtual std::string::size_type getFilterStringSize() = 0; virtual S32 getLastFilterGeneration() const = 0; @@ -193,6 +198,8 @@ public: mPassedFilter(true), mPassedFolderFilter(true), mPrevPassedAllFilters(false), + mStringMatchOffsetFilter(std::string::npos), + mStringFilterSize(0), mFolderViewItem(NULL), mLastFilterGeneration(-1), mMostFilteredDescendantGeneration(-1), @@ -216,6 +223,10 @@ public: mParent->dirtyFilter(); } } + bool hasFilterStringMatch() { return mStringMatchOffsetFilter != std::string::npos; } + std::string::size_type getFilterStringOffset() { return mStringMatchOffsetFilter; } + std::string::size_type getFilterStringSize() { return mStringFilterSize; } + virtual void addChild(LLFolderViewModelItem* child) { mChildren.push_back(child); @@ -234,6 +245,8 @@ protected: bool mPassedFilter; bool mPassedFolderFilter; bool mPrevPassedAllFilters; + std::string::size_type mStringMatchOffsetFilter; + std::string::size_type mStringFilterSize; S32 mLastFilterGeneration; S32 mMostFilteredDescendantGeneration; diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 13ca73917b..0878d15d06 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -144,11 +144,13 @@ bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generati return mMostFilteredDescendantGeneration >= filter_generation; } -void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) +void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_folder, S32 filter_generation, std::string::size_type string_offset, std::string::size_type string_size) { mPassedFilter = passed; mPassedFolderFilter = passed_folder; mLastFilterGeneration = filter_generation; + mStringMatchOffsetFilter = string_offset; + mStringFilterSize = string_size; bool passed_filter_before = mPrevPassedAllFilters; mPrevPassedAllFilters = passedFilter(filter_generation); @@ -226,9 +228,7 @@ void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) ? filter.checkFolder(this) : true; - setPassedFilter(passed_filter, passed_filter_folder, filter_generation); - //TODO RN: create interface for string highlighting - //mStringMatchOffset = filter.getStringMatchOffset(this); + setPassedFilter(passed_filter, passed_filter_folder, filter_generation, filter.getStringMatchOffset(this), filter.getFilterStringSize()); } } diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index ab67c93897..72c8047325 100644 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -58,7 +58,7 @@ public: virtual bool potentiallyVisible(); virtual bool passedFilter(S32 filter_generation = -1); virtual bool descendantsPassedFilter(S32 filter_generation = -1); - virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); + virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0); virtual void filter( LLFolderViewFilter& filter); virtual void filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 7005ab7b6a..9b487dd652 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -91,7 +91,7 @@ public: virtual bool potentiallyVisible() { return true; } virtual void filter( LLFolderViewFilter& filter) { } virtual bool descendantsPassedFilter(S32 filter_generation = -1) { return true; } - virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) { } + virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) { } virtual bool passedFilter(S32 filter_generation = -1) { return true; } // The action callbacks @@ -142,6 +142,8 @@ public: void setEmptyLookupMessage(const std::string& message) { } std::string getEmptyLookupMessage() const { return mEmpty; } bool showAllResults() const { return true; } + std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const { return std::string::npos; } + std::string::size_type getFilterStringSize() const { return 0; } bool isActive() const { return false; } bool isModified() const { return false; } diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index b4be927b09..4f4030550f 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -95,9 +95,9 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item) return passed_clipboard; } - std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : 0; + std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos; - BOOL passed = string_offset != std::string::npos; + BOOL passed = (mFilterSubString.size() == 0 || string_offset != std::string::npos); passed = passed && checkAgainstFilterType(listener); passed = passed && checkAgainstPermissions(listener); passed = passed && checkAgainstFilterLinks(listener); @@ -108,7 +108,7 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item) bool LLInventoryFilter::check(const LLInventoryItem* item) { - std::string::size_type string_offset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; + std::string::size_type string_offset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; const bool passed_filtertype = checkAgainstFilterType(item); const bool passed_permissions = checkAgainstPermissions(item); @@ -116,7 +116,7 @@ bool LLInventoryFilter::check(const LLInventoryItem* item) const bool passed = (passed_filtertype && passed_permissions && passed_clipboard - && (mFilterSubString.size() == 0 || string_offset != std::string::npos)); + && (mFilterSubString.size() == 0 || string_offset != std::string::npos)); return passed; } @@ -383,9 +383,10 @@ const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const return mFilterSubString; } -std::string::size_type LLInventoryFilter::getStringMatchOffset(LLFolderViewItem* item) const +std::string::size_type LLInventoryFilter::getStringMatchOffset(LLFolderViewModelItem* item) const { - return mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; + const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item); + return mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos; } bool LLInventoryFilter::isDefault() const @@ -1004,6 +1005,11 @@ bool LLInventoryFilter::hasFilterString() const return mFilterSubString.size() > 0; } +std::string::size_type LLInventoryFilter::getFilterStringSize() const +{ + return mFilterSubString.size(); +} + PermissionMask LLInventoryFilter::getFilterPermissions() const { return mFilterOps.mPermissions; diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index af245a9c3b..a8d39735f3 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -193,10 +193,8 @@ public: bool showAllResults() const; - - std::string::size_type getStringMatchOffset() const; - - std::string::size_type getStringMatchOffset(LLFolderViewItem* item) const; + std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const; + std::string::size_type getFilterStringSize() const; // +-------------------------------------------------------------------+ // + Presentation // +-------------------------------------------------------------------+ -- cgit v1.2.3 From a204059d2e69fb33cb1a3c8d2fbed35d3967297c Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 1 Aug 2012 01:14:27 -0700 Subject: CHUI-267 FIX Full inventory listing not always shown for test account changed LLFolderViewModelInterface::getFilter() to return a reference, since it is never NULL removed sort order from filter, which was causing unneeded filtering --- indra/llui/llfolderview.cpp | 12 ++-- indra/llui/llfolderview.h | 2 +- indra/llui/llfolderviewitem.cpp | 68 +++++++----------- indra/llui/llfolderviewitem.h | 20 +++--- indra/llui/llfolderviewmodel.cpp | 8 +-- indra/llui/llfolderviewmodel.h | 82 ++++++++++++++++------ indra/newview/llfloateroutbox.cpp | 2 +- indra/newview/llfolderviewmodelinventory.cpp | 40 ++++------- indra/newview/llfolderviewmodelinventory.h | 36 ++++++---- indra/newview/llinventorybridge.cpp | 2 +- indra/newview/llinventoryfilter.cpp | 17 ----- indra/newview/llinventoryfilter.h | 25 +++---- indra/newview/llinventorypanel.cpp | 53 +++++++------- indra/newview/llinventorypanel.h | 10 ++- indra/newview/llpanellandmarks.cpp | 24 ++----- indra/newview/llpanelmaininventory.cpp | 76 ++++++++++---------- indra/newview/llpanelmarketplaceinbox.cpp | 4 +- indra/newview/llpanelmarketplaceinboxinventory.cpp | 6 +- indra/newview/llpanelmarketplaceinboxinventory.h | 2 +- indra/newview/llpanelobjectinventory.cpp | 7 +- indra/newview/lltexturectrl.cpp | 10 +-- 21 files changed, 239 insertions(+), 267 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index e09026fc33..d714d4623d 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -274,7 +274,7 @@ BOOL LLFolderView::canFocusChildren() const return FALSE; } -BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) +void LLFolderView::addFolder( LLFolderViewFolder* folder) { LLFolderViewFolder::addFolder(folder); @@ -288,8 +288,6 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) //{ // mFolders.insert(mFolders.begin(), folder); //} - - return TRUE; } void LLFolderView::closeAllFolders() @@ -1769,14 +1767,14 @@ void LLFolderView::update() // until that inventory is loaded up. LLFastTimer t2(FTM_INVENTORY); - if (getFolderViewModel()->getFilter()->isModified() && getFolderViewModel()->getFilter()->isNotDefault()) + if (getFolderViewModel()->getFilter().isModified() && getFolderViewModel()->getFilter().isNotDefault()) { mNeedsAutoSelect = TRUE; } - getFolderViewModel()->getFilter()->clearModified(); + getFolderViewModel()->getFilter().clearModified(); // filter to determine visibility before arranging - filter(*(getFolderViewModel()->getFilter())); + filter(getFolderViewModel()->getFilter()); // automatically show matching items, and select first one if we had a selection if (mNeedsAutoSelect) @@ -1794,7 +1792,7 @@ void LLFolderView::update() // Open filtered folders for folder views with mAutoSelectOverride=TRUE. // Used by LLPlacesFolderView. - if (getFolderViewModel()->getFilter()->showAllResults()) + if (getFolderViewModel()->getFilter().showAllResults()) { // these are named variables to get around gcc not binding non-const references to rvalues // and functor application is inherently non-const to allow for stateful functors diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 5ebd8f73ac..05beff9bd8 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -121,7 +121,7 @@ public: void closeAllFolders(); void openTopLevelFolders(); - virtual BOOL addFolder( LLFolderViewFolder* folder); + virtual void addFolder( LLFolderViewFolder* folder); // Find width and height of this object and its children. Also // makes sure that this view and its children are the right size. diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 0f486d06c9..167c8123a1 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -221,11 +221,11 @@ void LLFolderViewItem::refresh() mIconOpen = vmi.getIconOpen(); mIconOverlay = vmi.getIconOverlay(); - if (mRoot->useLabelSuffix()) - { + if (mRoot->useLabelSuffix()) + { mLabelStyle = vmi.getLabelStyle(); mLabelSuffix = vmi.getLabelSuffix(); -} + } //TODO RN: make sure this logic still fires //std::string searchable_label(mLabel); @@ -255,7 +255,7 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection, LLFolderView* root = getRoot(); if (getParentFolder()) { - getParentFolder()->requestArrange(); + getParentFolder()->requestArrange(); } if(set_selection) { @@ -275,9 +275,9 @@ std::set<LLFolderViewItem*> LLFolderViewItem::getSelectionList() const } // addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) +void LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) { - return folder->addItem(this); + folder->addItem(this); } @@ -418,12 +418,12 @@ void LLFolderViewItem::rename(const std::string& new_name) { getViewModelItem()->renameItem(new_name); - if(mParentFolder) - { - mParentFolder->requestSort(); - } - } + //if(mParentFolder) + //{ + // mParentFolder->requestSort(); + //} } +} const std::string& LLFolderViewItem::getName( void ) const { @@ -839,9 +839,9 @@ LLFolderViewFolder::~LLFolderViewFolder( void ) } // addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) +void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) { - return folder->addFolder(this); + folder->addFolder(this); } static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); @@ -1008,11 +1008,6 @@ BOOL LLFolderViewFolder::needsArrange() return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); } -void LLFolderViewFolder::requestSort() -{ - getViewModelItem()->requestSort(); -} - //TODO RN: get height resetting working //void LLFolderViewFolder::setPassedFilter(BOOL passed, BOOL passed_folder, S32 filter_generation) //{ @@ -1417,7 +1412,6 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) } //item has been removed, need to update filter getViewModelItem()->removeChild(item->getViewModelItem()); - getViewModelItem()->dirtyFilter(); //because an item is going away regardless of filter status, force rearrange requestArrange(); removeChild(item); @@ -1483,7 +1477,7 @@ BOOL LLFolderViewFolder::isRemovable() } // this is an internal method used for adding items to folders. -BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) +void LLFolderViewFolder::addItem(LLFolderViewItem* item) { if (item->getParentFolder()) { @@ -1496,7 +1490,6 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); item->setVisible(FALSE); - addChild(item); // TODO RN - port creation date management to new code location #if 0 @@ -1504,10 +1497,7 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) setCreationDate(llmax<time_t>(mCreationDate, item->getCreationDate())); #endif - // Handle sorting - requestArrange(); - requestSort(); - + addChild(item); getViewModelItem()->addChild(item->getViewModelItem()); // TODO RN - port creation date management to new code location #if 0 @@ -1533,14 +1523,10 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) // parentp = parentp->getParentFolder(); //} - - item->getViewModelItem()->dirtyFilter(); - - return TRUE; } // this is an internal method used for adding items to folders. -BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) +void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) { if (folder->mParentFolder) { @@ -1551,30 +1537,26 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) folder->setOrigin(0, 0); folder->reshape(getRect().getWidth(), 0); folder->setVisible(FALSE); - addChild( folder ); // rearrange all descendants too, as our indentation level might have changed - folder->requestArrange(); - requestSort(); + //folder->requestArrange(); + //requestSort(); + addChild( folder ); getViewModelItem()->addChild(folder->getViewModelItem()); - //After addChild since addChild assigns parent to bubble up to when calling dirtyFilter - folder->getViewModelItem()->dirtyFilter(); - - return TRUE; } void LLFolderViewFolder::requestArrange() { //if ( mLastArrangeGeneration != -1) { - mLastArrangeGeneration = -1; - // flag all items up to root - if (mParentFolder) - { - mParentFolder->requestArrange(); - } + mLastArrangeGeneration = -1; + // flag all items up to root + if (mParentFolder) + { + mParentFolder->requestArrange(); } } +} void LLFolderViewFolder::toggleOpen() { diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index df007dd15d..baa12b38f3 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -116,8 +116,8 @@ protected: // this is an internal method used for adding items to folders. A // no-op at this level, but reimplemented in derived classes. - virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } - virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; } + virtual void addItem(LLFolderViewItem*) { } + virtual void addFolder(LLFolderViewFolder*) { } static LLFontGL* getLabelFontForStyle(U8 style); @@ -131,7 +131,7 @@ public: virtual ~LLFolderViewItem( void ); // addToFolder() returns TRUE if it succeeds. FALSE otherwise - virtual BOOL addToFolder(LLFolderViewFolder* folder); + virtual void addToFolder(LLFolderViewFolder* folder); // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. @@ -297,7 +297,7 @@ public: LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); // addToFolder() returns TRUE if it succeeds. FALSE otherwise - virtual BOOL addToFolder(LLFolderViewFolder* folder); + virtual void addToFolder(LLFolderViewFolder* folder); // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. @@ -356,8 +356,6 @@ public: // Called when a child is refreshed. virtual void requestArrange(); - virtual void requestSort(); - // internal method which doesn't update the entire view. This // method was written because the list iterators destroy the state // of other iterations, thus, we can't arrange while iterating @@ -381,8 +379,6 @@ public: void applyFunctorToChildren(LLFolderViewFunctor& functor); virtual void openItem( void ); - virtual BOOL addItem(LLFolderViewItem* item); - virtual BOOL addFolder( LLFolderViewFolder* folder); // LLView functionality virtual BOOL handleHover(S32 x, S32 y, MASK mask); @@ -412,6 +408,14 @@ public: LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items); +protected: + friend void LLFolderViewItem::addToFolder(LLFolderViewFolder*); + // internal functions for tracking folders and items separately + // use addToFolder() virtual method to ensure folders are always added to mFolders + // and not mItems + void addItem(LLFolderViewItem* item); + void addFolder( LLFolderViewFolder* folder); + public: //WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead template<typename SORT_FUNC> void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); } diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp index dc6e4d754b..6aa4a63edc 100644 --- a/indra/llui/llfolderviewmodel.cpp +++ b/indra/llui/llfolderviewmodel.cpp @@ -36,18 +36,18 @@ bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) std::string LLFolderViewModelCommon::getStatusText() { - if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter()->getCurrentGeneration()) + if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter().getCurrentGeneration()) { return LLTrans::getString("Searching"); } else { - return getFilter()->getEmptyLookupMessage(); + return getFilter().getEmptyLookupMessage(); } } void LLFolderViewModelCommon::filter() { - getFilter()->setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); - mFolderView->getViewModelItem()->filter(*getFilter()); + getFilter().setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); + mFolderView->getViewModelItem()->filter(getFilter()); } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index acdec53602..81de15923a 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -107,6 +107,24 @@ public: virtual S32 getFirstRequiredGeneration() const = 0; }; +class LLFolderViewModelInterface +{ +public: + virtual ~LLFolderViewModelInterface() {} + virtual void requestSortAll() = 0; + + virtual void sort(class LLFolderViewFolder*) = 0; + virtual void filter() = 0; + + virtual bool contentsReady() = 0; + virtual void setFolderView(LLFolderView* folder_view) = 0; + virtual LLFolderViewFilter& getFilter() = 0; + virtual const LLFolderViewFilter& getFilter() const = 0; + virtual std::string getStatusText() = 0; + + virtual bool startDrag(std::vector<LLFolderViewModelItem*>& items) = 0; +}; + // This is am abstract base class that users of the folderview classes // would use to bridge the folder view with the underlying data class LLFolderViewModelItem @@ -188,15 +206,15 @@ protected: class LLFolderViewModelItemCommon : public LLFolderViewModelItem { public: - LLFolderViewModelItemCommon() + LLFolderViewModelItemCommon(LLFolderViewModelInterface& root_view_model) : mSortVersion(-1), mPassedFilter(true), mPassedFolderFilter(true), - mPrevPassedAllFilters(false), mFolderViewItem(NULL), mLastFilterGeneration(-1), mMostFilteredDescendantGeneration(-1), - mParent(NULL) + mParent(NULL), + mRootViewModel(root_view_model) { std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); } @@ -220,20 +238,55 @@ public: { mChildren.push_back(child); child->setParent(this); + dirtyFilter(); + requestSort(); } virtual void removeChild(LLFolderViewModelItem* child) { mChildren.remove(child); child->setParent(NULL); + dirtyFilter(); + } + + void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) + { + mPassedFilter = passed; + mPassedFolderFilter = passed_folder; + mLastFilterGeneration = filter_generation; + } + + virtual bool potentiallyVisible() + { + return passedFilter() // we've passed the filter + || getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration() // or we don't know yet + || descendantsPassedFilter(); } + virtual bool passedFilter(S32 filter_generation = -1) + { + if (filter_generation < 0) + filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); + + bool passed_folder_filter = mPassedFolderFilter && mLastFilterGeneration >= filter_generation; + bool passed_filter = mPassedFilter && mLastFilterGeneration >= filter_generation; + return passed_folder_filter + && (descendantsPassedFilter(filter_generation) + || passed_filter); + } + + virtual bool descendantsPassedFilter(S32 filter_generation = -1) + { + if (filter_generation < 0) filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); + return mMostFilteredDescendantGeneration >= filter_generation; + } + + protected: virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } S32 mSortVersion; bool mPassedFilter; bool mPassedFolderFilter; - bool mPrevPassedAllFilters; S32 mLastFilterGeneration; S32 mMostFilteredDescendantGeneration; @@ -242,28 +295,13 @@ protected: typedef std::list<LLFolderViewModelItem*> child_list_t; child_list_t mChildren; LLFolderViewModelItem* mParent; + LLFolderViewModelInterface& mRootViewModel; void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} LLFolderViewItem* mFolderViewItem; }; -class LLFolderViewModelInterface -{ -public: - virtual ~LLFolderViewModelInterface() {} - virtual void requestSortAll() = 0; - - virtual void sort(class LLFolderViewFolder*) = 0; - virtual void filter() = 0; - - virtual bool contentsReady() = 0; - virtual void setFolderView(LLFolderView* folder_view) = 0; - virtual LLFolderViewFilter* getFilter() = 0; - virtual const LLFolderViewFilter* getFilter() const = 0; - virtual std::string getStatusText() = 0; - virtual bool startDrag(std::vector<LLFolderViewModelItem*>& items) = 0; -}; class LLFolderViewModelCommon : public LLFolderViewModelInterface { @@ -307,8 +345,8 @@ public: virtual const SortType& getSorter() const { return mSorter; } virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } - virtual FilterType* getFilter() { return &mFilter; } - virtual const FilterType* getFilter() const { return &mFilter; } + virtual FilterType& getFilter() { return mFilter; } + virtual const FilterType& getFilter() const { return mFilter; } virtual void setFilter(const FilterType& filter) { mFilter = filter; } // TODO RN: remove this and put all filtering logic in view model diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index e4ed97892e..18ed36d0f3 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -251,7 +251,7 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId) // Set the sort order newest to oldest mOutboxInventoryPanel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME); - mOutboxInventoryPanel->getFilter()->markDefault(); + mOutboxInventoryPanel->getFilter().markDefault(); fetchOutboxContents(); diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 13ca73917b..21218850a6 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -109,7 +109,12 @@ bool LLFolderViewModelInventory::contentsReady() void LLFolderViewModelItemInventory::requestSort() { LLFolderViewModelItemCommon::requestSort(); - if (mRootViewModel.getSorter().isByDate()) + LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(mFolderViewItem); + if (folderp) + { + folderp->requestArrange(); + } + if (static_cast<LLFolderViewModelInventory&>(mRootViewModel).getSorter().isByDate()) { // sort by date potentially affects parent folders which use a date // derived from newest item in them @@ -120,35 +125,9 @@ void LLFolderViewModelItemInventory::requestSort() } } -bool LLFolderViewModelItemInventory::potentiallyVisible() -{ - return passedFilter() // we've passed the filter - || getLastFilterGeneration() < mRootViewModel.getFilter()->getFirstSuccessGeneration() // or we don't know yet - || descendantsPassedFilter(); -} - -bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) -{ - if (filter_generation < 0) - filter_generation = mRootViewModel.getFilter()->getFirstSuccessGeneration(); - - return mPassedFolderFilter - && (descendantsPassedFilter(filter_generation) - || (mLastFilterGeneration >= filter_generation - && mPassedFilter)); -} - -bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) -{ - if (filter_generation < 0) filter_generation = mRootViewModel.getFilter()->getFirstSuccessGeneration(); - return mMostFilteredDescendantGeneration >= filter_generation; -} - void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) { - mPassedFilter = passed; - mPassedFolderFilter = passed_folder; - mLastFilterGeneration = filter_generation; + LLFolderViewModelItemCommon::setPassedFilter(passed, passed_folder, filter_generation); bool passed_filter_before = mPrevPassedAllFilters; mPrevPassedAllFilters = passedFilter(filter_generation); @@ -324,3 +303,8 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, } } +LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model ) + : LLFolderViewModelItemCommon(root_view_model), + mPrevPassedAllFilters(false) +{ +} diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index ab67c93897..5b0ad5e46e 100644 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -37,9 +37,7 @@ class LLFolderViewModelItemInventory : public LLFolderViewModelItemCommon { public: - LLFolderViewModelItemInventory(class LLFolderViewModelInventory& root_view_model) - : mRootViewModel(root_view_model) - {} + LLFolderViewModelItemInventory(class LLFolderViewModelInventory& root_view_model); virtual const LLUUID& getUUID() const = 0; virtual time_t getCreationDate() const = 0; // UTC seconds virtual void setCreationDate(time_t creation_date_utc) = 0; @@ -55,9 +53,6 @@ public: virtual EInventorySortGroup getSortGroup() const = 0; virtual LLInventoryObject* getInventoryObject() const = 0; virtual void requestSort(); - virtual bool potentiallyVisible(); - virtual bool passedFilter(S32 filter_generation = -1); - virtual bool descendantsPassedFilter(S32 filter_generation = -1); virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); virtual void filter( LLFolderViewFilter& filter); virtual void filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); @@ -66,25 +61,36 @@ public: virtual LLToolDragAndDrop::ESource getDragSource() const = 0; protected: - class LLFolderViewModelInventory& mRootViewModel; + bool mPrevPassedAllFilters; }; class LLInventorySort { public: - LLInventorySort(U32 order = 0) - : mSortOrder(order), - mByDate(false), - mSystemToTop(false), - mFoldersByName(false) + struct Params : public LLInitParam::Block<Params> { - mByDate = (order & LLInventoryFilter::SO_DATE); - mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); - mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); + Optional<S32> order; + + Params() + : order("order", 0) + {} + }; + + LLInventorySort(S32 order = 0) + { + fromParams(Params().order(order)); } bool isByDate() const { return mByDate; } U32 getSortOrder() const { return mSortOrder; } + void toParams(Params& p) { p.order(mSortOrder);} + void fromParams(Params& p) + { + mSortOrder = p.order; + mByDate = (mSortOrder & LLInventoryFilter::SO_DATE); + mSystemToTop = (mSortOrder & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); + mFoldersByName = (mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_NAME); + } bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const; private: diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 14616ca7ab..43c4ce1278 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -900,7 +900,7 @@ LLInventoryModel* LLInvFVBridge::getInventoryModel() const LLInventoryFilter* LLInvFVBridge::getInventoryFilter() const { LLInventoryPanel* panel = mInventoryPanel.get(); - return panel ? panel->getFilter() : NULL; + return panel ? &(panel->getFilter()) : NULL; } BOOL LLInvFVBridge::isItemInTrash() const diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index b4be927b09..7993dd04c5 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -69,7 +69,6 @@ LLInventoryFilter::LLInventoryFilter(const Params& p) mFilterModified(FILTER_NONE), mEmptyLookupMessage("InventoryNoMatchingItems"), mFilterOps(p.filter_ops), - mOrder(p.sort_order), mFilterSubString(p.substring), mCurrentGeneration(0), mFirstRequiredGeneration(0), @@ -703,15 +702,6 @@ void LLInventoryFilter::setShowFolderState(EFolderShow state) } } -void LLInventoryFilter::setSortOrder(U32 order) -{ - if (mOrder != order) - { - mOrder = order; - setModified(); - } -} - void LLInventoryFilter::markDefault() { mDefaultFilterOps = mFilterOps; @@ -944,7 +934,6 @@ LLInventoryFilter& LLInventoryFilter::operator=( const LLInventoryFilter& othe setShowFolderState(other.getShowFolderState()); setFilterPermissions(other.getFilterPermissions()); setFilterSubString(other.getFilterSubString()); - setSortOrder(other.getSortOrder()); setDateRangeLastLogoff(other.isSinceLogoff()); return *this; } @@ -961,7 +950,6 @@ void LLInventoryFilter::toParams(Params& params) const params.filter_ops.show_folder_state = getShowFolderState(); params.filter_ops.permissions = getFilterPermissions(); params.substring = getFilterSubString(); - params.sort_order = getSortOrder(); params.since_logoff = isSinceLogoff(); } @@ -980,7 +968,6 @@ void LLInventoryFilter::fromParams(const Params& params) setShowFolderState(params.filter_ops.show_folder_state); setFilterPermissions(params.filter_ops.permissions); setFilterSubString(params.substring); - setSortOrder(params.sort_order); setDateRangeLastLogoff(params.since_logoff); } @@ -1030,10 +1017,6 @@ LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const { return mFilterOps.mShowFolderState; } -U32 LLInventoryFilter::getSortOrder() const -{ - return mOrder; -} void LLInventoryFilter::setFilterCount(S32 count) { diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index af245a9c3b..b560730873 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -74,8 +74,8 @@ public: { struct DateRange : public LLInitParam::Block<DateRange> { - Optional<time_t> min_date; - Optional<time_t> max_date; + Optional<time_t> min_date, + max_date; DateRange() : min_date("min_date", time_min()), @@ -115,18 +115,18 @@ public: FilterOps(const Params& = Params()); U32 mFilterTypes; - - U64 mFilterObjectTypes; // For _OBJECT - U64 mFilterWearableTypes; - U64 mFilterCategoryTypes; // For _CATEGORY + U64 mFilterObjectTypes, // For _OBJECT + mFilterWearableTypes, + mFilterLinks, + mFilterCategoryTypes; // For _CATEGORY LLUUID mFilterUUID; // for UUID - time_t mMinDate; - time_t mMaxDate; + time_t mMinDate, + mMaxDate; U32 mHoursAgo; + EFolderShow mShowFolderState; PermissionMask mPermissions; - U64 mFilterLinks; }; struct Params : public LLInitParam::Block<Params> @@ -134,14 +134,12 @@ public: Optional<std::string> name; Optional<FilterOps::Params> filter_ops; Optional<std::string> substring; - Optional<U32> sort_order; Optional<bool> since_logoff; Params() : name("name"), filter_ops(""), substring("substring"), - sort_order("sort_order"), since_logoff("since_logoff") {} }; @@ -203,9 +201,6 @@ public: void setShowFolderState( EFolderShow state); EFolderShow getShowFolderState() const; - void setSortOrder(U32 order); - U32 getSortOrder() const; - void setEmptyLookupMessage(const std::string& message); std::string getEmptyLookupMessage() const; @@ -261,8 +256,6 @@ private: bool checkAgainstFilterLinks(const class LLFolderViewModelItemInventory* listener) const; bool checkAgainstClipboard(const LLUUID& object_id) const; - U32 mOrder; - FilterOps mFilterOps; FilterOps mDefaultFilterOps; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index e9b128e836..1b3391f7ee 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -239,13 +239,13 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) } // hide inbox - getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX)); - getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX)); + getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX)); + getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX)); // set the filter for the empty folder if the debug setting is on if (gSavedSettings.getBOOL("DebugHideEmptySystemFolders")) { - getFilter()->setFilterEmptySystemFolders(); + getFilter().setFilterEmptySystemFolders(); } // keep track of the clipboard state so that we avoid filtering too much @@ -285,18 +285,18 @@ void LLInventoryPanel::draw() if (mClipboardState != LLClipboard::instance().getGeneration()) { mClipboardState = LLClipboard::instance().getGeneration(); - getFilter()->setModified(LLClipboard::instance().isCutMode() ? LLInventoryFilter::FILTER_MORE_RESTRICTIVE : LLInventoryFilter::FILTER_LESS_RESTRICTIVE); + getFilter().setModified(LLClipboard::instance().isCutMode() ? LLInventoryFilter::FILTER_MORE_RESTRICTIVE : LLInventoryFilter::FILTER_LESS_RESTRICTIVE); } LLPanel::draw(); } -const LLInventoryFilter* LLInventoryPanel::getFilter() const +const LLInventoryFilter& LLInventoryPanel::getFilter() const { return getFolderViewModel()->getFilter(); } -LLInventoryFilter* LLInventoryPanel::getFilter() +LLInventoryFilter& LLInventoryPanel::getFilter() { return getFolderViewModel()->getFilter(); } @@ -304,50 +304,49 @@ LLInventoryFilter* LLInventoryPanel::getFilter() void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type) { if (filter_type == LLInventoryFilter::FILTERTYPE_OBJECT) - getFilter()->setFilterObjectTypes(types); + getFilter().setFilterObjectTypes(types); if (filter_type == LLInventoryFilter::FILTERTYPE_CATEGORY) - getFilter()->setFilterCategoryTypes(types); + getFilter().setFilterCategoryTypes(types); } U32 LLInventoryPanel::getFilterObjectTypes() const { - return getFilter()->getFilterObjectTypes(); + return getFilter().getFilterObjectTypes(); } U32 LLInventoryPanel::getFilterPermMask() const { - return getFilter()->getFilterPermissions(); + return getFilter().getFilterPermissions(); } void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask) { - getFilter()->setFilterPermissions(filter_perm_mask); + getFilter().setFilterPermissions(filter_perm_mask); } void LLInventoryPanel::setFilterWearableTypes(U64 types) { - getFilter()->setFilterWearableTypes(types); + getFilter().setFilterWearableTypes(types); } void LLInventoryPanel::setFilterSubString(const std::string& string) { - getFilter()->setFilterSubString(string); + getFilter().setFilterSubString(string); } const std::string LLInventoryPanel::getFilterSubString() { - return getFilter()->getFilterSubString(); + return getFilter().getFilterSubString(); } void LLInventoryPanel::setSortOrder(U32 order) { - LLInventorySort sorter(order); - getFilter()->setSortOrder(order); + LLInventorySort sorter(order); if (order != getFolderViewModel()->getSorter().getSortOrder()) { - getFolderViewModel()->setSorter(LLInventorySort(order)); + getFolderViewModel()->setSorter(sorter); // try to keep selection onscreen, even if it wasn't to start with mFolderRoot->scrollToShowSelection(); } @@ -360,27 +359,27 @@ U32 LLInventoryPanel::getSortOrder() const void LLInventoryPanel::setSinceLogoff(BOOL sl) { - getFilter()->setDateRangeLastLogoff(sl); + getFilter().setDateRangeLastLogoff(sl); } void LLInventoryPanel::setHoursAgo(U32 hours) { - getFilter()->setHoursAgo(hours); + getFilter().setHoursAgo(hours); } void LLInventoryPanel::setFilterLinks(U64 filter_links) { - getFilter()->setFilterLinks(filter_links); + getFilter().setFilterLinks(filter_links); } void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show) { - getFilter()->setShowFolderState(show); + getFilter().setShowFolderState(show); } LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState() { - return getFilter()->getShowFolderState(); + return getFilter().getShowFolderState(); } void LLInventoryPanel::modelChanged(U32 mask) @@ -473,7 +472,7 @@ void LLInventoryPanel::modelChanged(U32 mask) { if (view_folder) { - view_folder->requestSort(); + view_folder->getViewModelItem()->requestSort(); } } @@ -1088,7 +1087,7 @@ bool LLInventoryPanel::attachObject(const LLSD& userdata) BOOL LLInventoryPanel::getSinceLogoff() { - return getFilter()->isSinceLogoff(); + return getFilter().isSinceLogoff(); } // DEBUG ONLY @@ -1214,12 +1213,12 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L void LLInventoryPanel::addHideFolderType(LLFolderType::EType folder_type) { - getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << folder_type)); + getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << folder_type)); } BOOL LLInventoryPanel::getIsHiddenFolderType(LLFolderType::EType folder_type) const { - return !(getFilter()->getFilterCategoryTypes() & (1ULL << folder_type)); + return !(getFilter().getFilterCategoryTypes() & (1ULL << folder_type)); } void LLInventoryPanel::addItemID( const LLUUID& id, LLFolderViewItem* itemp ) @@ -1321,7 +1320,7 @@ public: { LLInventoryPanel::initFromParams(p); // turn on inbox for recent items - getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX)); + getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX)); } protected: diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index b66b53f642..e9bfcb0ccf 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -120,6 +120,12 @@ public: {} }; + struct InventoryState : public LLInitParam::Block<InventoryState> + { + Mandatory<LLInventoryFilter::Params> filter; + Mandatory<LLInventorySort::Params> sort; + }; + //-------------------------------------------------------------------- // Initialization //-------------------------------------------------------------------- @@ -155,8 +161,8 @@ public: void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus); void setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb); void clearSelection(); - LLInventoryFilter* getFilter(); - const LLInventoryFilter* getFilter() const; + LLInventoryFilter& getFilter(); + const LLInventoryFilter& getFilter() const; void setFilterTypes(U64 filter, LLInventoryFilter::EFilterType = LLInventoryFilter::FILTERTYPE_OBJECT); U32 getFilterObjectTypes() const; void setFilterPermMask(PermissionMask filter_perm_mask); diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 1a4f3708ac..9225ea3d53 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -247,10 +247,7 @@ void LLLandmarksPanel::onSearchEdit(const std::string& string) LLPlacesInventoryPanel* inventory_list = dynamic_cast<LLPlacesInventoryPanel*>(tab->getAccordionView()); if (NULL == inventory_list) continue; - if (inventory_list->getFilter()) - { - filter_list(inventory_list, string); - } + filter_list(inventory_list, string); } if (sFilterSubString != string) @@ -365,9 +362,6 @@ void LLLandmarksPanel::onSelectorButtonClicked() void LLLandmarksPanel::updateShowFolderState() { - if (!mLandmarksInventoryPanel->getFilter()) - return; - bool show_all_folders = mLandmarksInventoryPanel->getFilterSubString().empty(); if (show_all_folders) { @@ -547,7 +541,7 @@ void LLLandmarksPanel::initFavoritesInventoryPanel() mFavoritesInventoryPanel = getChild<LLPlacesInventoryPanel>("favorites_list"); initLandmarksPanel(mFavoritesInventoryPanel); - mFavoritesInventoryPanel->getFilter()->setEmptyLookupMessage("FavoritesNoMatchingItems"); + mFavoritesInventoryPanel->getFilter().setEmptyLookupMessage("FavoritesNoMatchingItems"); initAccordion("tab_favorites", mFavoritesInventoryPanel, true); } @@ -558,12 +552,7 @@ void LLLandmarksPanel::initLandmarksInventoryPanel() initLandmarksPanel(mLandmarksInventoryPanel); - // Check if mLandmarksInventoryPanel is properly initialized and has a Filter created. - // In case of a dummy widget getFilter() will return NULL. - if (mLandmarksInventoryPanel->getFilter()) - { - mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); - } + mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); // subscribe to have auto-rename functionality while creating New Folder mLandmarksInventoryPanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mLandmarksInventoryPanel, _1, _2)); @@ -599,12 +588,7 @@ void LLLandmarksPanel::initLibraryInventoryPanel() void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list) { - // In case of a dummy widget further we have no Folder View widget and no Filter, - // so further initialization leads to crash. - if (!inventory_list->getFilter()) - return; - - inventory_list->getFilter()->setEmptyLookupMessage("PlacesNoMatchingItems"); + inventory_list->getFilter().setEmptyLookupMessage("PlacesNoMatchingItems"); inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK); inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2)); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index fea27b37d3..e1aa70cc4a 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -89,9 +89,9 @@ public: static void selectNoTypes(void* user_data); private: LLPanelMainInventory* mPanelMainInventory; - LLSpinCtrl* mSpinSinceDays; - LLSpinCtrl* mSpinSinceHours; - LLInventoryFilter* mFilter; + LLSpinCtrl* mSpinSinceDays; + LLSpinCtrl* mSpinSinceHours; + LLInventoryFilter* mFilter; }; ///---------------------------------------------------------------------------- @@ -131,7 +131,7 @@ BOOL LLPanelMainInventory::postBuild() mFilterTabs = getChild<LLTabContainer>("inventory filter tabs"); mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this)); - //panel->getFilter()->markDefault(); + //panel->getFilter().markDefault(); // Set up the default inv. panel/filter settings. mActivePanel = getChild<LLInventoryPanel>("All Items"); @@ -139,7 +139,7 @@ BOOL LLPanelMainInventory::postBuild() { // "All Items" is the previous only view, so it gets the InventorySortOrder mActivePanel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER)); - mActivePanel->getFilter()->markDefault(); + mActivePanel->getFilter().markDefault(); mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); mActivePanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mActivePanel, _1, _2)); mResortActivePanel = true; @@ -150,7 +150,7 @@ BOOL LLPanelMainInventory::postBuild() recent_items_panel->setSinceLogoff(TRUE); recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE); recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - recent_items_panel->getFilter()->markDefault(); + recent_items_panel->getFilter().markDefault(); recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2)); } @@ -169,14 +169,14 @@ BOOL LLPanelMainInventory::postBuild() // Note that the "All Items" settings do not persist. if(recent_items_panel) { - if(savedFilterState.has(recent_items_panel->getFilter()->getName())) + if(savedFilterState.has(recent_items_panel->getFilter().getName())) { LLSD recent_items = savedFilterState.get( - recent_items_panel->getFilter()->getName()); + recent_items_panel->getFilter().getName()); LLInventoryFilter::Params p; LLParamSDParser parser; parser.readSD(recent_items, p); - recent_items_panel->getFilter()->fromParams(p); + recent_items_panel->getFilter().fromParams(p); } } @@ -213,29 +213,29 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items"); if (all_items_panel) { - LLInventoryFilter* filter = all_items_panel->getFilter(); - if (filter) + LLSD filterState; + LLInventoryPanel::InventoryState p; + all_items_panel->getFilter().toParams(p.filter); + all_items_panel->getRootViewModel().getSorter().toParams(p.sort); + if (p.validateBlock(false)) { - LLSD filterState; - LLInventoryFilter::Params p; - filter->toParams(p); - if (p.validateBlock(false)) - { - LLParamSDParser().writeSD(filterState, p); - filterRoot[filter->getName()] = filterState; - } + LLParamSDParser().writeSD(filterState, p); + filterRoot[all_items_panel->getName()] = filterState; } } - LLInventoryFilter* filter = findChild<LLInventoryPanel>("Recent Items")->getFilter(); - if (filter) + LLInventoryPanel* panel = findChild<LLInventoryPanel>("Recent Items"); + if (panel) { LLSD filterState; - LLInventoryFilter::Params p; - filter->toParams(p); - LLParamSDParser parser; - parser.writeSD(filterState, p); - filterRoot[filter->getName()] = filterState; + LLInventoryPanel::InventoryState p; + panel->getFilter().toParams(p.filter); + panel->getRootViewModel().getSorter().toParams(p.sort); + if (p.validateBlock(false)) + { + LLParamSDParser().writeSD(filterState, p); + filterRoot[panel->getName()] = filterState; + } } std::ostringstream filterSaveName; @@ -321,7 +321,7 @@ void LLPanelMainInventory::doCreate(const LLSD& userdata) void LLPanelMainInventory::resetFilters() { LLFloaterInventoryFinder *finder = getFinder(); - getActivePanel()->getFilter()->resetDefault(); + getActivePanel()->getFilter().resetDefault(); if (finder) { finder->updateElementsFromFilter(); @@ -426,7 +426,7 @@ void LLPanelMainInventory::onFilterEdit(const std::string& search_string ) } // save current folder open state if no filter currently applied - if (!mActivePanel->getFilter()->isNotDefault()) + if (!mActivePanel->getFilter().isNotDefault()) { mSavedFolderState->setApply(FALSE); mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -488,13 +488,13 @@ void LLPanelMainInventory::onFilterSelected() } setFilterSubString(mFilterSubString); - LLInventoryFilter* filter = mActivePanel->getFilter(); + LLInventoryFilter& filter = mActivePanel->getFilter(); LLFloaterInventoryFinder *finder = getFinder(); if (finder) { - finder->changeFilter(filter); + finder->changeFilter(&filter); } - if (filter->isActive()) + if (filter.isActive()) { // If our filter is active we may be the first thing requiring a fetch so we better start it here. LLInventoryModelBackgroundFetch::instance().start(); @@ -607,7 +607,7 @@ void LLPanelMainInventory::onFocusReceived() void LLPanelMainInventory::setFilterTextFromFilter() { - mFilterText = mActivePanel->getFilter()->getFilterText(); + mFilterText = mActivePanel->getFilter().getFilterText(); } void LLPanelMainInventory::toggleFindOptions() @@ -657,7 +657,7 @@ LLFloaterInventoryFinder* LLPanelMainInventory::getFinder() LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLPanelMainInventory* inventory_view) : LLFloater(LLSD()), mPanelMainInventory(inventory_view), - mFilter(inventory_view->getPanel()->getFilter()) + mFilter(&inventory_view->getPanel()->getFilter()) { buildFromFile("floater_inventory_view_finder.xml"); updateElementsFromFilter(); @@ -1082,14 +1082,14 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); const std::string &item_name = current_item->getViewModelItem()->getName(); mFilterSubString = item_name; - LLInventoryFilter *filter = mActivePanel->getFilter(); - filter->setFilterSubString(item_name); + LLInventoryFilter &filter = mActivePanel->getFilter(); + filter.setFilterSubString(item_name); mFilterEditor->setText(item_name); mFilterEditor->setFocus(TRUE); - filter->setFilterUUID(item_id); - filter->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - filter->setFilterLinks(LLInventoryFilter::FILTERLINK_ONLY_LINKS); + filter.setFilterUUID(item_id); + filter.setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + filter.setFilterLinks(LLInventoryFilter::FILTERLINK_ONLY_LINKS); } } diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index 3547156197..ea0521e3a7 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -95,13 +95,13 @@ LLInventoryPanel * LLPanelMarketplaceInbox::setupInventoryPanel() // Set the sort order newest to oldest mInventoryPanel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_DATE); - mInventoryPanel->getFilter()->markDefault(); + mInventoryPanel->getFilter().markDefault(); // Set selection callback for proper update of inventory status buttons mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceInbox::onSelectionChange, this)); // Set up the note to display when the inbox is empty - mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryInboxNoItems"); + mInventoryPanel->getFilter().setEmptyLookupMessage("InventoryInboxNoItems"); // Hide the placeholder text inbox_inventory_placeholder->setVisible(FALSE); diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index 8ad3929999..0d3fbe66d7 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -182,9 +182,9 @@ LLInboxFolderViewItem::LLInboxFolderViewItem(const Params& p) #endif } -BOOL LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder) +void LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder) { - BOOL retval = LLFolderViewItem::addToFolder(folder); + LLFolderViewItem::addToFolder(folder); #if SUPPORTING_FRESH_ITEM_COUNT // Compute freshness if our parent is the root folder for the inbox @@ -193,8 +193,6 @@ BOOL LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder) computeFreshness(); } #endif - - return retval; } BOOL LLInboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask) diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h index d8b8a2fe63..098969aca6 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.h +++ b/indra/newview/llpanelmarketplaceinboxinventory.h @@ -95,7 +95,7 @@ public: LLInboxFolderViewItem(const Params& p); - BOOL addToFolder(LLFolderViewFolder* folder); + void addToFolder(LLFolderViewFolder* folder); BOOL handleDoubleClick(S32 x, S32 y, MASK mask); void draw(); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 4f2c515bde..82956beb3d 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1567,11 +1567,8 @@ void LLPanelObjectInventory::reset() mFolders = LLUICtrlFactory::create<LLFolderView>(p); // this ensures that we never say "searching..." or "no items found" //TODO RN: make this happen by manipulating filter object directly - LLInventoryFilter* inventoryFilter = dynamic_cast<LLInventoryFilter*>(mFolders->getFolderViewModel()->getFilter()); - if(inventoryFilter) - { - inventoryFilter->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); - } + LLInventoryFilter& inventoryFilter = dynamic_cast<LLInventoryFilter&>(mFolders->getFolderViewModel()->getFilter()); + inventoryFilter.setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 2d3f144588..65f0290060 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -455,7 +455,7 @@ BOOL LLFloaterTexturePicker::postBuild() // Commented out to scroll to currently selected texture. See EXT-5403. // // store this filter as the default one - // mInventoryPanel->getRootFolder()->getFilter()->markDefault(); + // mInventoryPanel->getRootFolder()->getFilter().markDefault(); // Commented out to stop opening all folders with textures // mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_TEXTURE); @@ -638,10 +638,10 @@ void LLFloaterTexturePicker::draw() LLFolderView* folder_view = mInventoryPanel->getRootFolder(); if (!folder_view) return; - LLFolderViewFilter* filter = static_cast<LLFolderViewModelInventory*>(folder_view->getFolderViewModel())->getFilter(); + LLFolderViewFilter& filter = static_cast<LLFolderViewModelInventory*>(folder_view->getFolderViewModel())->getFilter(); - bool is_filter_active = folder_view->getViewModelItem()->getLastFilterGeneration() < filter->getCurrentGeneration() && - filter->isNotDefault(); + bool is_filter_active = folder_view->getViewModelItem()->getLastFilterGeneration() < filter.getCurrentGeneration() && + filter.isNotDefault(); // After inventory panel filter is applied we have to update // constraint rect for the selected item because of folder view @@ -1012,7 +1012,7 @@ void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string ) else if (mInventoryPanel->getFilterSubString().empty()) { // first letter in search term, save existing folder open state - if (!mInventoryPanel->getFilter()->isNotDefault()) + if (!mInventoryPanel->getFilter().isNotDefault()) { mSavedFolderState.setApply(FALSE); mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); -- cgit v1.2.3 From 8ccaa8b0b8e65d6022c6ad0d449cecdd8a72f81d Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 1 Aug 2012 01:48:39 -0700 Subject: build fix attempt --- indra/llui/llfolderviewmodel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 3f825a8670..c4d98657e2 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -259,7 +259,7 @@ public: dirtyFilter(); } - void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation, std::string::size_type string_offset, std::string::size_type string_size) + void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) { mPassedFilter = passed; mPassedFolderFilter = passed_folder; -- cgit v1.2.3 From c3bc6de8ba90216d3687f70e01e92accde956a85 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 1 Aug 2012 09:36:10 -0700 Subject: CHUI-218 FIX (Items and Item count is not show in Received Items folder in Inventory) forgot to check in --- indra/newview/skins/default/xui/en/panel_inbox_inventory.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml index 48d38d50e0..433a3181cd 100644 --- a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml @@ -2,7 +2,7 @@ <inbox_inventory_panel accepts_drag_and_drop="false" name="inventory_inbox" - start_folder.name="Received Items" + start_folder.type="inbox" follows="all" layout="topleft" top="0" left="0" height="165" width="308" top_pad="0" -- cgit v1.2.3 From 4256b54ee78a89dc5e790cc13556451e1a7c43fa Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 1 Aug 2012 10:45:11 -0700 Subject: build fix --- indra/llui/llfolderviewitem.h | 3 --- indra/newview/llimfloatercontainer.cpp | 8 +++++--- indra/newview/llimfloatercontainer.h | 3 ++- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 19caa7f020..4eda02f13f 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -406,15 +406,12 @@ public: LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items); -protected: - friend void LLFolderViewItem::addToFolder(LLFolderViewFolder*); // internal functions for tracking folders and items separately // use addToFolder() virtual method to ensure folders are always added to mFolders // and not mItems void addItem(LLFolderViewItem* item); void addFolder( LLFolderViewFolder* folder); -public: //WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead template<typename SORT_FUNC> void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); } template<typename SORT_FUNC> void sortItems(const SORT_FUNC& func) { mItems.sort(func); } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 405a2b3255..cc094fcaa1 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -100,7 +100,7 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsListPanel = getChild<LLPanel>("conversations_list_panel"); // CHUI-98 : View Model for conversations - LLConversationItem* base_item = new LLConversationItem(); + LLConversationItem* base_item = new LLConversationItem(this); LLFolderView::Params p; p.view_model = &mConversationViewModel; p.parent_panel = mConversationsListPanel; @@ -456,7 +456,7 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI mConversationsWidgets[floaterp] = widget; // Add a new conversation widget to the root folder of a folder view. - mConversationsRoot->addItem(widget); + widget->addToFolder(mConversationsRoot); // Add it to the UI widget->setVisible(TRUE); @@ -533,6 +533,7 @@ LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversat // Conversation items LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp) : + LLFolderViewModelItemCommon(containerp->getRootViewModel()), mName(name), mUUID(uuid), mFloater(floaterp), @@ -540,7 +541,8 @@ LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLF { } -LLConversationItem::LLConversationItem() : +LLConversationItem::LLConversationItem(LLIMFloaterContainer* containerp) : + LLFolderViewModelItemCommon(containerp->getRootViewModel()), mName(""), mUUID(), mFloater(NULL), diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 9b487dd652..b352e8a004 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -57,7 +57,7 @@ class LLConversationItem : public LLFolderViewModelItemCommon { public: LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp); - LLConversationItem(); + LLConversationItem(LLIMFloaterContainer* containerp); virtual ~LLConversationItem() {} // Stub those things we won't really be using in this conversation context @@ -241,6 +241,7 @@ public: /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id); /*virtual*/ void sessionRemoved(const LLUUID& session_id); /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {}; + LLConversationViewModel& getRootViewModel() { return mConversationViewModel; } private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; -- cgit v1.2.3 From 4cb1e766fcfcaba702c2638f4c7daa9dd17bcbd8 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 1 Aug 2012 21:08:42 +0300 Subject: CHUI-268 (Transfer the common functionality from LLNearbyChat and LLIMFloater to LLIMConversation): Remove duplication of functionality from LLNearbyChat; transfer mChatHistory, mInputEditor and some its settings and callbacks to the base class. --- indra/llui/llfloater.h | 2 +- indra/newview/llimconversation.cpp | 31 ++++++----- indra/newview/llimconversation.h | 8 +-- indra/newview/llimfloater.cpp | 18 ++---- indra/newview/llimfloater.h | 3 - indra/newview/llnearbychat.cpp | 109 +++++++++++-------------------------- indra/newview/llnearbychat.h | 8 +-- 7 files changed, 59 insertions(+), 120 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 17402b8d63..5be6e6d922 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -324,7 +324,7 @@ public: virtual void setDocked(bool docked, bool pop_on_undock = true); virtual void setTornOff(bool torn_off) { mTornOff = torn_off; } - bool getTornOff() {return mTornOff;} + bool isTornOff() {return mTornOff;} void setOpenPositioning(LLFloaterEnums::EOpenPositioning pos) {mPositioning = pos;} // Return a closeable floater, if any, given the current focus. diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index ec534b903d..3e23d75d28 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -94,12 +94,16 @@ BOOL LLIMConversation::postBuild() mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); mChatHistory = getChild<LLChatHistory>("chat_history"); - mInputEditor = getChild<LLChatEntry>("chat_editor"); + mInputEditor = getChild<LLChatEntry>("chat_editor"); mInputEditor->setTextExpandedCallback(boost::bind(&LLIMConversation::reshapeChatHistory, this)); + mInputEditor->setCommitOnFocusLost( FALSE ); + mInputEditor->setPassDelete(TRUE); + mInputEditor->setFont(LLViewerChat::getChatFont()); + mInputEditorTopPad = mChatHistory->getRect().mBottom - mInputEditor->getRect().mTop; - if (!getTornOff()) + if (!isTornOff()) { setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); } @@ -221,18 +225,16 @@ bool LLIMConversation::onIMShowModesMenuItemEnable(const LLSD& userdata) void LLIMConversation::hideOrShowTitle() { - bool is_hosted = getHost() != NULL; - const LLFloater::Params& default_params = LLFloater::getDefaultParams(); S32 floater_header_size = default_params.header_height; LLView* floater_contents = getChild<LLView>("contents_view"); LLRect floater_rect = getLocalRect(); - S32 top_border_of_contents = floater_rect.mTop - (is_hosted? 0 : floater_header_size); + S32 top_border_of_contents = floater_rect.mTop - (isTornOff()? floater_header_size : 0); LLRect handle_rect (0, floater_rect.mTop, floater_rect.mRight, top_border_of_contents); LLRect contents_rect (0, top_border_of_contents, floater_rect.mRight, floater_rect.mBottom); mDragHandle->setShape(handle_rect); - mDragHandle->setVisible(! is_hosted); + mDragHandle->setVisible(isTornOff()); floater_contents->setShape(contents_rect); } @@ -250,9 +252,8 @@ void LLIMConversation::hideAllStandardButtons() void LLIMConversation::updateHeaderAndToolbar() { - bool is_hosted = getHost() != NULL; - - if (is_hosted) + bool is_torn_off = isTornOff(); + if (!is_torn_off) { hideAllStandardButtons(); } @@ -261,7 +262,7 @@ void LLIMConversation::updateHeaderAndToolbar() // Participant list should be visible only in torn off floaters. bool is_participant_list_visible = - !is_hosted + is_torn_off && gSavedSettings.getBOOL("IMShowControlPanel") && !mIsP2PChat; @@ -269,21 +270,21 @@ void LLIMConversation::updateHeaderAndToolbar() // Display collapse image (<<) if the floater is hosted // or if it is torn off but has an open control panel. - bool is_expanded = is_hosted || is_participant_list_visible; + bool is_expanded = !is_torn_off || is_participant_list_visible; mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); // toggle floater's drag handle and title visibility if (mDragHandle) { - mDragHandle->setTitleVisible(!is_hosted); + mDragHandle->setTitleVisible(is_torn_off); } // The button (>>) should be disabled for torn off P2P conversations. - mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat); + mExpandCollapseBtn->setEnabled(!is_torn_off || !mIsP2PChat); - mTearOffBtn->setImageOverlay(getString(is_hosted ? "tear_off_icon" : "return_icon")); + mTearOffBtn->setImageOverlay(getString(is_torn_off? "return_icon" : "tear_off_icon")); - mCloseBtn->setVisible(is_hosted && !mIsNearbyChat); + mCloseBtn->setVisible(!is_torn_off && !mIsNearbyChat); enableDisableCallBtn(); diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index c3dff96d5d..649c200899 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -99,6 +99,10 @@ protected: LLParticipantList* mParticipantList; LLUUID mSessionID; + LLChatHistory* mChatHistory; + LLChatEntry* mInputEditor; + int mInputEditorTopPad; // padding between input field and chat history + LLButton* mExpandCollapseBtn; LLButton* mTearOffBtn; LLButton* mCloseBtn; @@ -117,10 +121,6 @@ private: */ void reshapeChatHistory(); - LLChatHistory* mChatHistory; - LLChatEntry* mInputEditor; - int mInputEditorTopPad; // padding between input field and chat history - LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. }; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 1b08c454b7..3399a88c9e 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -66,11 +66,9 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) : LLIMConversation(session_id), mLastMessageIndex(-1), mDialog(IM_NOTHING_SPECIAL), - mInputEditor(NULL), mSavedTitle(), mTypingStart(), mShouldSendTypingState(false), - mChatHistory(NULL), mMeTyping(false), mOtherTyping(false), mTypingTimer(), @@ -80,6 +78,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mStartConferenceInSameFloater(false) { mIsNearbyChat = false; + initIMSession(session_id); setOverlapsScreenChannel(true); @@ -313,9 +312,8 @@ void LLIMFloater::initIMFloater() //virtual BOOL LLIMFloater::postBuild() { - LLIMConversation::postBuild(); + BOOL result = LLIMConversation::postBuild(); - mInputEditor = getChild<LLChatEntry>("chat_editor"); mInputEditor->setMaxTextLength(1023); // enable line history support for instant message bar // XXX stinson TODO : resolve merge by adding autoreplace to text editors @@ -323,19 +321,11 @@ BOOL LLIMFloater::postBuild() // *TODO Establish LineEditor with autoreplace callback mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); #endif - - LLFontGL* font = LLViewerChat::getChatFont(); - mInputEditor->setFont(font); mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) ); mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) ); mInputEditor->setKeystrokeCallback( boost::bind(onInputEditorKeystroke, _1, this) ); - mInputEditor->setCommitOnFocusLost( FALSE ); - mInputEditor->setPassDelete( TRUE ); - mInputEditor->setCommitCallback(boost::bind(onSendMsg, _1, this)); - - mChatHistory = getChild<LLChatHistory>("chat_history"); setDocked(true); @@ -358,7 +348,7 @@ BOOL LLIMFloater::postBuild() LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); im_box->addConversationListItem(getTitle(), getKey(), this); - return TRUE; + return result; } void LLIMFloater::onAddButtonClicked() @@ -1004,7 +994,7 @@ void LLIMFloater::onInputEditorKeystroke(LLTextEditor* caller, void* userdata) // Deleting all text counts as stopping typing. self->setTyping(!text.empty()); - } +} void LLIMFloater::setTyping(bool typing) { diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 7e45cf42c2..434613ff43 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -184,11 +184,8 @@ private: LLIMModel::LLIMSession* mSession; S32 mLastMessageIndex; - LLChatHistory* mChatHistory; - EInstantMessage mDialog; LLUUID mOtherParticipantUUID; - LLChatEntry* mInputEditor; bool mPositioned; std::string mSavedTitle; diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 3bd5f96add..b628697bbc 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -125,30 +125,24 @@ static LLChatTypeTrigger sChatTypeTriggers[] = { LLNearbyChat::LLNearbyChat(const LLSD& key) : LLIMConversation(key), - mChatBox(NULL), - mChatHistory(NULL), //mOutputMonitor(NULL), mSpeakerMgr(NULL), mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) { + mIsNearbyChat = true; setIsChrome(TRUE); mKey = LLSD(); - mIsNearbyChat = true; mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); } //virtual BOOL LLNearbyChat::postBuild() { - mChatBox = getChild<LLChatEntry>("chat_editor"); - - mChatBox->setCommitCallback(boost::bind(&LLNearbyChat::onChatBoxCommit, this)); - mChatBox->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this)); - mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); - mChatBox->setFocusReceivedCallback(boost::bind(&LLNearbyChat::onChatBoxFocusReceived, this)); - mChatBox->setCommitOnFocusLost( FALSE ); - mChatBox->setPassDelete(TRUE); - mChatBox->setFont(LLViewerChat::getChatFont()); + BOOL result = LLIMConversation::postBuild(); + mInputEditor->setCommitCallback(boost::bind(&LLNearbyChat::onChatBoxCommit, this)); + mInputEditor->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this)); + mInputEditor->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); + mInputEditor->setFocusReceivedCallback(boost::bind(&LLNearbyChat::onChatBoxFocusReceived, this)); // mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); // mOutputMonitor->setVisible(FALSE); @@ -180,7 +174,6 @@ BOOL LLNearbyChat::postBuild() // obsolete, but may be needed for backward compatibility? gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); - mChatHistory = getChild<LLChatHistory>("chat_history"); if (gSavedPerAccountSettings.getBOOL("LogShowHistory")) { loadHistory(); @@ -190,7 +183,7 @@ BOOL LLNearbyChat::postBuild() LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); im_box->addConversationListItem(getTitle(), LLSD(), this); - return LLIMConversation::postBuild(); + return result; } // virtual @@ -227,10 +220,6 @@ bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata) return false; } -void LLNearbyChat::getAllowedRect(LLRect& rect) -{ - rect = gViewerWindow->getWorldViewRectScaled(); -} //////////////////////////////////////////////////////////////////////////////// // void LLNearbyChat::onFocusReceived() @@ -352,10 +341,8 @@ void LLNearbyChat::onTearOffClicked() { LLIMConversation::onTearOffClicked(); - LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); - // see CHUI-170: Save torn-off state of the nearby chat between sessions - BOOL in_the_multifloater = (getHost() == im_box); + BOOL in_the_multifloater = !isTornOff(); gSavedSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater); } @@ -389,18 +376,12 @@ void LLNearbyChat::onOpen(const LLSD& key) showTranslationCheckbox(LLTranslate::isTranslationConfigured()); } -bool LLNearbyChat::applyRectControl() -{ - setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); - return LLFloater::applyRectControl(); -} - void LLNearbyChat::onChatFontChange(LLFontGL* fontp) { // Update things with the new font whohoo - if (mChatBox) + if (mInputEditor) { - mChatBox->setFont(fontp); + mInputEditor->setFont(fontp); } } @@ -416,33 +397,20 @@ void LLNearbyChat::show() { openFloater(getKey()); } - setVisible(TRUE); } bool LLNearbyChat::isChatVisible() const { bool isVisible = false; - - if (isChatMultiTab()) - { - LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); - // Is the IM floater container ever null? - llassert(im_box != NULL); - if (im_box != NULL) - { - if (gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) - { - isVisible = (im_box->getVisible() && !im_box->isMinimized()); - } - else - { - isVisible = (getVisible() && !isMinimized()); - } - } - } - else + LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + // Is the IM floater container ever null? + llassert(im_box != NULL); + if (im_box != NULL) { - isVisible = (getVisible() && !isMinimized()); + isVisible = + isChatMultiTab() && gSavedSettings.getBOOL("NearbyChatIsNotTornOff")? + im_box->getVisible() && !im_box->isMinimized() : + getVisible() && !isMinimized(); } return isVisible; @@ -452,22 +420,11 @@ void LLNearbyChat::showHistory() { openFloater(); setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); - - bool is_torn_off = getHost() == NULL; - - // Reshape and enable resize controls only if it's a torn off floater. - // Otherwise all the size changes should be handled by LLIMFloaterContainer. - if (is_torn_off) - { - reshape(getRect().getWidth(), mExpandedHeight); - enableResizeCtrls(true); - storeRectControl(); - } } std::string LLNearbyChat::getCurrentChat() { - return mChatBox ? mChatBox->getText() : LLStringUtil::null; + return mInputEditor ? mInputEditor->getText() : LLStringUtil::null; } // virtual @@ -516,7 +473,7 @@ void LLNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userdata) LLNearbyChat* self = (LLNearbyChat *)userdata; - LLWString raw_text = self->mChatBox->getWText(); + LLWString raw_text = self->mInputEditor->getWText(); // Can't trim the end, because that will cause autocompletion // to eat trailing spaces that might be part of a gesture. @@ -563,17 +520,17 @@ void LLNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userdata) if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) { 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 + self->mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part // Select to end of line, starting from the character // after the last one the user typed. - self->mChatBox->selectNext(rest_of_match, false); + self->mInputEditor->selectNext(rest_of_match, false); } else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) { 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 - self->mChatBox->endOfDoc(); + self->mInputEditor->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part + self->mInputEditor->endOfDoc(); } //llinfos << "GESTUREDEBUG " << trigger @@ -592,7 +549,7 @@ void LLNearbyChat::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata void LLNearbyChat::onChatBoxFocusReceived() { - mChatBox->setEnabled(!gDisconnected); + mInputEditor->setEnabled(!gDisconnected); } EChatType LLNearbyChat::processChatTypeTriggers(EChatType type, std::string &str) @@ -629,9 +586,9 @@ EChatType LLNearbyChat::processChatTypeTriggers(EChatType type, std::string &str void LLNearbyChat::sendChat( EChatType type ) { - if (mChatBox) + if (mInputEditor) { - LLWString text = mChatBox->getWText(); + LLWString text = mInputEditor->getWText(); LLWStringUtil::trim(text); LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. if (!text.empty()) @@ -664,7 +621,7 @@ void LLNearbyChat::sendChat( EChatType type ) } } - mChatBox->setText(LLStringExplicit("")); + mInputEditor->setText(LLStringExplicit("")); } gAgent.stopTyping(); @@ -735,7 +692,7 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) void LLNearbyChat::onChatBoxCommit() { - if (mChatBox->getText().length() > 0) + if (mInputEditor->getText().length() > 0) { sendChat(CHAT_TYPE_NORMAL); } @@ -837,15 +794,15 @@ void LLNearbyChat::startChat(const char* line) cb->show(); cb->setVisible(TRUE); cb->setFocus(TRUE); - cb->mChatBox->setFocus(TRUE); + cb->mInputEditor->setFocus(TRUE); if (line) { std::string line_string(line); - cb->mChatBox->setText(line_string); + cb->mInputEditor->setText(line_string); } - cb->mChatBox->endOfDoc(); + cb->mInputEditor->endOfDoc(); } } @@ -857,7 +814,7 @@ void LLNearbyChat::stopChat() if (cb) { - cb->mChatBox->setFocus(FALSE); + cb->mInputEditor->setFocus(FALSE); // stop typing animation gAgent.stopTyping(); diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index a0928e67ef..7c58e3037e 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -39,7 +39,6 @@ #include "llpanel.h" class LLResizeBar; -class LLChatHistory; class LLNearbyChat : public LLIMConversation @@ -73,7 +72,7 @@ public: void onNearbyChatContextMenuItemClicked(const LLSD& userdata); bool onNearbyChatCheckContextMenuItem(const LLSD& userdata); - LLChatEntry* getChatBox() { return mChatBox; } + LLChatEntry* getChatBox() { return mInputEditor; } std::string getCurrentChat(); @@ -98,8 +97,6 @@ protected: void onChatBoxCommit(); void onChatFontChange(LLFontGL* fontp); - /* virtual */ bool applyRectControl(); - /*virtual*/ void onTearOffClicked(); static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); @@ -113,7 +110,6 @@ protected: // Which non-zero channel did we last chat on? static S32 sLastSpecialChatChannel; - LLChatEntry* mChatBox; LLOutputMonitorCtrl* mOutputMonitor; LLLocalSpeakerMgr* mSpeakerMgr; @@ -121,7 +117,6 @@ protected: private: - void getAllowedRect (LLRect& rect); // prepare chat's params and out one message to chatHistory void appendMessage(const LLChat& chat, const LLSD &args = 0); void onNearbySpeakers (); @@ -130,7 +125,6 @@ private: LLHandle<LLView> mPopupMenuHandle; std::vector<LLChat> mMessageArchive; - LLChatHistory* mChatHistory; }; -- cgit v1.2.3 From 898ec6cd362cd92ceef8dca8faf3fb8ed119b1be Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 1 Aug 2012 14:44:29 -0700 Subject: CHUI-254 FIX Fix Inventory filter and item draw() to highlight matching substrings in inventory made background highlighting sit behind label, so as not to obscure neighboring characters in label --- indra/llui/llfolderviewitem.cpp | 50 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 9b802157f2..480332ae70 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -747,15 +747,29 @@ void LLFolderViewItem::draw() return; } + std::string::size_type filter_string_length = mViewModelItem->hasFilterStringMatch() ? mViewModelItem->getFilterStringSize() : 0; + F32 right_x = 0; + F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); + std::string combined_string = mLabel + mLabelSuffix; + + if (filter_string_length > 0) + { + S32 left = llround(text_left) + font->getWidth(combined_string, 0, mViewModelItem->getFilterStringOffset()) - 2; + S32 right = left + font->getWidth(combined_string, mViewModelItem->getFilterStringOffset(), filter_string_length) + 2; + S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); + S32 top = getRect().getHeight() - TOP_PAD; + + LLUIImage* box_image = default_params.selection_image; + LLRect box_rect(left, top, right, bottom); + box_image->draw(box_rect, sFilterBGColor); + } + LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; //TODO RN: implement this in terms of getColor() //if (highlight_link) color = sLinkColor; //if (gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; - F32 right_x = 0; - F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; - F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); - //--------------------------------------------------------------------------------// // Draw the actual label text // @@ -776,27 +790,13 @@ void LLFolderViewItem::draw() //--------------------------------------------------------------------------------// // Highlight string match // - if (mViewModelItem->hasFilterStringMatch()) - { - // don't draw backgrounds for zero-length strings - std::string::size_type filter_string_length = mViewModelItem->getFilterStringSize(); - if (filter_string_length > 0) - { - std::string combined_string = mLabel + mLabelSuffix; - S32 left = llround(text_left) + font->getWidth(combined_string, 0, mViewModelItem->getFilterStringOffset()) - 1; - S32 right = left + font->getWidth(combined_string, mViewModelItem->getFilterStringOffset(), filter_string_length) + 2; - S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); - S32 top = getRect().getHeight() - TOP_PAD; - - LLUIImage* box_image = default_params.selection_image; - LLRect box_rect(left, top, right, bottom); - box_image->draw(box_rect, sFilterBGColor); - F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mViewModelItem->getFilterStringOffset()); - F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; - font->renderUTF8( combined_string, mViewModelItem->getFilterStringOffset(), match_string_left, yy, - sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - filter_string_length, S32_MAX, &right_x, FALSE ); - } + if (filter_string_length > 0) + { + F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mViewModelItem->getFilterStringOffset()); + F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + font->renderUTF8( combined_string, mViewModelItem->getFilterStringOffset(), match_string_left, yy, + sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + filter_string_length, S32_MAX, &right_x, FALSE ); } } -- cgit v1.2.3 From c6d981a8430f02a5a78afbeece9afeb7b2f108c8 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 1 Aug 2012 17:29:34 -0700 Subject: CHUI-214: Scrolling to offscreen content now works. Problem was due to the icon height/width not being computed before scrolling to the new item. There was also a problem with the computation that determines if the item being scrolled to is within the visible region. --- indra/llui/llfolderview.cpp | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index e09026fc33..bc286c1868 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1704,9 +1704,6 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr if(item) { LLRect local_rect = item->getLocalRect(); - LLRect item_scrolled_rect; // item position relative to display area of scroller - LLRect visible_doc_rect = mScrollContainer->getVisibleContentRect(); - S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight(); // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder @@ -1815,6 +1812,20 @@ void LLFolderView::update() mNeedsAutoSelect = FALSE; } + BOOL is_visible = isInVisibleChain(); + + //Puts folders/items in proper positions + if ( is_visible ) + { + sanitizeSelection(); + if( needsArrange() ) + { + S32 height = 0; + S32 width = 0; + S32 total_height = arrange( &width, &height ); + notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); + } + } // during filtering process, try to pin selected item's location on screen // this will happen when searching your inventory and when new items arrive @@ -1826,18 +1837,26 @@ void LLFolderView::update() // lets pin it! mPinningSelectedItem = TRUE; - LLRect visible_content_rect = (mScrollContainer ? mScrollContainer->getVisibleContentRect() : LLRect()); + //Computes visible area + const LLRect visible_content_rect = (mScrollContainer ? mScrollContainer->getVisibleContentRect() : LLRect()); LLFolderViewItem* selected_item = mSelectedItems.back(); + //Computes location of selected content, content outside visible area will be scrolled to using below code LLRect item_rect; selected_item->localRectToOtherView(selected_item->getLocalRect(), &item_rect, this); - // if item is visible in scrolled region - if (visible_content_rect.overlaps(item_rect)) + + //Computes intersected region of the selected content and visible area + LLRect overlap_rect(item_rect); + overlap_rect.intersectWith(visible_content_rect); + + //Don't scroll when the selected content exists within the visible area + if (overlap_rect.getHeight() >= selected_item->getItemHeight()) { // then attempt to keep it in same place on screen mScrollConstraintRect = item_rect; mScrollConstraintRect.translate(-visible_content_rect.mLeft, -visible_content_rect.mBottom); } + //Scroll because the selected content is outside the visible area else { // otherwise we just want it onscreen somewhere @@ -1868,20 +1887,6 @@ void LLFolderView::update() constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); } - BOOL is_visible = isInVisibleChain(); - - if ( is_visible ) - { - sanitizeSelection(); - if( needsArrange() ) - { - S32 height = 0; - S32 width = 0; - S32 total_height = arrange( &width, &height ); - notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); - } - } - if (mSelectedItems.size() && mNeedsScroll) { scrollToShowItem(mSelectedItems.back(), constraint_rect); -- cgit v1.2.3 From c009cf4f7656ec27347e1e9c740da26c12726c99 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 1 Aug 2012 19:42:22 -0700 Subject: CHUI-223 WIP Selecting to cut an inventory item causes all open inventory windows to refresh improved filtering behavior that should result in less flashes of emptiness --- indra/llui/llfolderviewitem.cpp | 6 ++-- indra/llui/llfolderviewmodel.h | 20 +++++++++---- indra/llui/lltooltip.cpp | 2 +- indra/newview/llfolderviewmodelinventory.cpp | 42 ++++++++++++++++++---------- indra/newview/llfolderviewmodelinventory.h | 6 ++-- indra/newview/llimfloatercontainer.h | 4 +-- 6 files changed, 52 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 480332ae70..5238bfd7e4 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -801,14 +801,14 @@ void LLFolderViewItem::draw() } const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const - { +{ return getRoot()->getFolderViewModel(); } LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) - { +{ return getRoot()->getFolderViewModel(); - } +} ///---------------------------------------------------------------------------- diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index c4d98657e2..9908e538a4 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -172,10 +172,11 @@ public: virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? - virtual void filter( LLFolderViewFilter& filter) = 0; + virtual bool filter( LLFolderViewFilter& filter) = 0; virtual bool passedFilter(S32 filter_generation = -1) = 0; virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; - virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) = 0; + virtual void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) = 0; + virtual void setPassedFolderFilter(bool passed, S32 filter_generation) = 0; virtual void dirtyFilter() = 0; virtual bool hasFilterStringMatch() = 0; virtual std::string::size_type getFilterStringOffset() = 0; @@ -219,6 +220,7 @@ public: mStringFilterSize(0), mFolderViewItem(NULL), mLastFilterGeneration(-1), + mLastFolderFilterGeneration(-1), mMostFilteredDescendantGeneration(-1), mParent(NULL), mRootViewModel(root_view_model) @@ -231,9 +233,11 @@ public: void setSortVersion(S32 version) { mSortVersion = version;} S32 getLastFilterGeneration() const { return mLastFilterGeneration; } + S32 getLastFolderFilterGeneration() const { return mLastFolderFilterGeneration; } void dirtyFilter() { mLastFilterGeneration = -1; + mLastFolderFilterGeneration = -1; // bubble up dirty flag all the way to root if (mParent) @@ -259,15 +263,20 @@ public: dirtyFilter(); } - void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) + void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) { mPassedFilter = passed; - mPassedFolderFilter = passed_folder; mLastFilterGeneration = filter_generation; mStringMatchOffsetFilter = string_offset; mStringFilterSize = string_size; } + void setPassedFolderFilter(bool passed, S32 filter_generation) + { + mPassedFolderFilter = passed; + mLastFolderFilterGeneration = filter_generation; + } + virtual bool potentiallyVisible() { return passedFilter() // we've passed the filter @@ -280,7 +289,7 @@ public: if (filter_generation < 0) filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration(); - bool passed_folder_filter = mPassedFolderFilter && mLastFilterGeneration >= filter_generation; + bool passed_folder_filter = mPassedFolderFilter && mLastFolderFilterGeneration >= filter_generation; bool passed_filter = mPassedFilter && mLastFilterGeneration >= filter_generation; return passed_folder_filter && (descendantsPassedFilter(filter_generation) @@ -304,6 +313,7 @@ protected: std::string::size_type mStringFilterSize; S32 mLastFilterGeneration; + S32 mLastFolderFilterGeneration; S32 mMostFilteredDescendantGeneration; diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index f737d48abf..d4670efedf 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -288,7 +288,7 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p) mTextBox->setText(p.message()); } - S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth()); + S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth() + 1); S32 text_height = mTextBox->getTextPixelHeight(); mTextBox->reshape(text_width, text_height); if (mInfoButton) diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index e2376b18d5..8a4b4bae84 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -125,9 +125,9 @@ void LLFolderViewModelItemInventory::requestSort() } } -void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_folder, S32 filter_generation, std::string::size_type string_offset, std::string::size_type string_size) +void LLFolderViewModelItemInventory::setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset, std::string::size_type string_size) { - LLFolderViewModelItemCommon::setPassedFilter(passed, passed_folder, filter_generation, string_offset, string_size); + LLFolderViewModelItemCommon::setPassedFilter(passed, filter_generation, string_offset, string_size); bool passed_filter_before = mPrevPassedAllFilters; mPrevPassedAllFilters = passedFilter(filter_generation); @@ -143,14 +143,15 @@ void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_fo } } -void LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) +bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) { S32 filter_generation = filter.getCurrentGeneration(); + bool continue_filtering = true; if (item->getLastFilterGeneration() < filter_generation) { // recursive application of the filter for child items - item->filter( filter ); + continue_filtering = item->filter( filter ); } // track latest generation to pass any child items, for each folder up to root @@ -164,22 +165,31 @@ void LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite view_model = static_cast<LLFolderViewModelItemInventory*>(view_model->mParent); } } + + return continue_filtering; } -void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) +bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) { const S32 filter_generation = filter.getCurrentGeneration(); const S32 must_pass_generation = filter.getFirstRequiredGeneration(); if (getLastFilterGeneration() >= must_pass_generation + && getLastFolderFilterGeneration() >= must_pass_generation && !passedFilter(must_pass_generation)) { // failed to pass an earlier filter that was a subset of the current one // go ahead and flag this item as done - setPassedFilter(false, false, filter_generation); - return; + setPassedFilter(false, filter_generation); + setPassedFolderFilter(false, filter_generation); + return true; } + const bool passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) + ? filter.checkFolder(this) + : true; + setPassedFolderFilter(passed_filter_folder, filter_generation); + if(!mChildren.empty() && (getLastFilterGeneration() < must_pass_generation // haven't checked descendants against minimum required generation to pass || descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement @@ -189,7 +199,10 @@ void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) iter != end_iter && filter.getFilterCount() > 0; ++iter) { - filterChildItem((*iter), filter); + if (!filterChildItem((*iter), filter)) + { + break; + } } } @@ -200,12 +213,13 @@ void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) { filter.decrementFilterCount(); - const BOOL passed_filter = filter.check(this); - const BOOL passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) - ? filter.checkFolder(this) - : true; - - setPassedFilter(passed_filter, passed_filter_folder, filter_generation, filter.getStringMatchOffset(this), filter.getFilterStringSize()); + const bool passed_filter = filter.check(this); + setPassedFilter(passed_filter, filter_generation, filter.getStringMatchOffset(this), filter.getFilterStringSize()); + return true; + } + else + { + return false; } } diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index 664addf336..890d03d1c9 100644 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -53,9 +53,9 @@ public: virtual EInventorySortGroup getSortGroup() const = 0; virtual LLInventoryObject* getInventoryObject() const = 0; virtual void requestSort(); - virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0); - virtual void filter( LLFolderViewFilter& filter); - virtual void filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); + virtual void setPassedFilter(bool filtered, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0); + virtual bool filter( LLFolderViewFilter& filter); + virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; virtual LLToolDragAndDrop::ESource getDragSource() const = 0; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index b352e8a004..5154b02dd6 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -89,9 +89,9 @@ public: virtual bool hasChildren() const { return FALSE; } virtual bool potentiallyVisible() { return true; } - virtual void filter( LLFolderViewFilter& filter) { } + virtual bool filter( LLFolderViewFilter& filter) { return false; } virtual bool descendantsPassedFilter(S32 filter_generation = -1) { return true; } - virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) { } + virtual void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) { } virtual bool passedFilter(S32 filter_generation = -1) { return true; } // The action callbacks -- cgit v1.2.3 From 88e81f99293c992944787289699bf885568bf327 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Wed, 1 Aug 2012 20:07:42 -0700 Subject: CHUI-223 WIP Selecting to cut an inventory item causes all open inventory windows to refresh avoid moving selection when cutting --- indra/llui/llfolderview.cpp | 57 +++++++++++++++++++------------------- indra/llui/llfolderviewitem.cpp | 6 ++++ indra/llui/llfolderviewitem.h | 1 + indra/newview/llinventorypanel.cpp | 17 ++++++------ 4 files changed, 44 insertions(+), 37 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index d714d4623d..5d98dc9663 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -717,33 +717,6 @@ void LLFolderView::closeRenamer( void ) } } -bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector<LLFolderViewItem*>& selectedItems) -{ - LLFolderViewItem* item_parent = dynamic_cast<LLFolderViewItem*>(item->getParent()); - - if (item_parent) - { - for(std::vector<LLFolderViewItem*>::const_iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) - { - const LLFolderViewItem* const selected_item = (*it); - - LLFolderViewItem* parent = item_parent; - - while (parent) - { - if (selected_item == parent) - { - return true; - } - - parent = dynamic_cast<LLFolderViewItem*>(parent->getParent()); - } - } - } - - return false; -} - void LLFolderView::removeSelectedItems() { if(getVisible() && getEnabled()) @@ -815,7 +788,7 @@ void LLFolderView::removeSelectedItems() if (!new_selection) { new_selection = last_item->getPreviousOpenNode(FALSE); - while (new_selection && (new_selection->isSelected() || isDescendantOfASelectedItem(new_selection, items))) + while (new_selection && (new_selection->isInSelection())) { new_selection = new_selection->getPreviousOpenNode(FALSE); } @@ -1060,16 +1033,42 @@ void LLFolderView::cut() if(getVisible() && getEnabled() && (count > 0)) { LLFolderViewModelItem* listener = NULL; + + LLFolderViewItem* last_item = *mSelectedItems.rbegin();; + LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); + while(new_selection && new_selection->isSelected()) + { + new_selection = new_selection->getNextOpenNode(FALSE); + } + if (!new_selection) + { + new_selection = last_item->getPreviousOpenNode(FALSE); + while (new_selection && (new_selection->isInSelection())) + { + new_selection = new_selection->getPreviousOpenNode(FALSE); + } + } + selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - listener = (*item_it)->getViewModelItem(); + LLFolderViewItem* item_to_cut = *item_it; + listener = item_to_cut->getViewModelItem(); if(listener) { listener->cutToClipboard(); listener->removeItem(); } } + + if (new_selection) + { + setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); + } + else + { + setSelection(NULL, mParentPanel->hasFocus()); + } } mSearchString.clear(); } diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 5238bfd7e4..68b442dd9a 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -810,6 +810,12 @@ LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) return getRoot()->getFolderViewModel(); } +bool LLFolderViewItem::isInSelection() const +{ + return mIsSelected || (mParentFolder && mParentFolder->isInSelection()); +} + + ///---------------------------------------------------------------------------- /// Class LLFolderViewFolder diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 4eda02f13f..e75059bc01 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -164,6 +164,7 @@ public: virtual void destroyView(); BOOL isSelected() const { return mIsSelected; } + bool isInSelection() const; void setUnselected() { mIsSelected = FALSE; } diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 1b3391f7ee..9403ccdabe 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -281,13 +281,6 @@ void LLInventoryPanel::draw() // Select the desired item (in case it wasn't loaded when the selection was requested) updateSelection(); - // Nudge the filter if the clipboard state changed - if (mClipboardState != LLClipboard::instance().getGeneration()) - { - mClipboardState = LLClipboard::instance().getGeneration(); - getFilter().setModified(LLClipboard::instance().isCutMode() ? LLInventoryFilter::FILTER_MORE_RESTRICTIVE : LLInventoryFilter::FILTER_LESS_RESTRICTIVE); - } - LLPanel::draw(); } @@ -586,7 +579,6 @@ LLUUID LLInventoryPanel::getRootFolderID() } } - // static void LLInventoryPanel::onIdle(void *userdata) { @@ -608,6 +600,15 @@ void LLInventoryPanel::onIdle(void *userdata) void LLInventoryPanel::idle(void* user_data) { LLInventoryPanel* panel = (LLInventoryPanel*)user_data; + // Nudge the filter if the clipboard state changed + if (panel->mClipboardState != LLClipboard::instance().getGeneration()) + { + panel->mClipboardState = LLClipboard::instance().getGeneration(); + panel->getFilter().setModified(LLClipboard::instance().isCutMode() + ? LLInventoryFilter::FILTER_MORE_RESTRICTIVE + : LLInventoryFilter::FILTER_LESS_RESTRICTIVE); + } + panel->mFolderRoot->update(); // while dragging, update selection rendering to reflect single/multi drag status if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) -- cgit v1.2.3 From 0fa1e2b9ae41bb06e5c7db90900d4f469f44b8d3 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 2 Aug 2012 18:43:44 +0300 Subject: CHUI-230, CHUI-232, CHUI-261 Forced resize of a conversation's floater in the IM-container; support of the rectControls for IM-conversations; fixed LLFloater and LLMultiFloater for the correct hosting of floaters with mSaveRect --- indra/llui/llfloater.cpp | 61 +++++++++++++--------- indra/llui/llfloater.h | 1 + indra/llui/llmultifloater.cpp | 3 ++ indra/llui/llmultifloater.h | 9 ++-- indra/newview/llimconversation.cpp | 15 ++++-- indra/newview/llimfloatercontainer.cpp | 5 ++ indra/newview/llnearbychat.cpp | 2 - .../skins/default/xui/en/floater_im_session.xml | 3 +- 8 files changed, 61 insertions(+), 38 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index a1c902d562..8145d6d347 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1175,7 +1175,6 @@ void LLFloater::setMinimized(BOOL minimize) { // minimized flag should be turned on before release focus mMinimized = TRUE; - mExpandedRect = getRect(); // If the floater has been dragged while minimized in the @@ -1248,7 +1247,6 @@ void LLFloater::setMinimized(BOOL minimize) } setOrigin( mExpandedRect.mLeft, mExpandedRect.mBottom ); - if (mButtonsEnabled[BUTTON_RESTORE]) { mButtonsEnabled[BUTTON_MINIMIZE] = TRUE; @@ -1284,7 +1282,6 @@ void LLFloater::setMinimized(BOOL minimize) // Reshape *after* setting mMinimized reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE ); - applyPositioning(NULL, false); } make_ui_sound("UISndWindowClose"); @@ -1658,10 +1655,12 @@ void LLFloater::onClickTearOff(LLFloater* self) gFloaterView->addChild(self); self->openFloater(self->getKey()); - - // only force position for floaters that don't have that data saved - if (self->mRectControl.empty()) + if (self->mSaveRect && !self->mRectControl.empty()) { + self->applyRectControl(); + } + else + { // only force position for floaters that don't have that data saved new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - floater_header_size - 5, self->getRect().getWidth(), self->getRect().getHeight()); self->setRect(new_rect); } @@ -1675,6 +1674,10 @@ void LLFloater::onClickTearOff(LLFloater* self) LLMultiFloater* new_host = (LLMultiFloater*)self->mLastHostHandle.get(); if (new_host) { + if (self->mSaveRect) + { + self->storeRectControl(); + } self->setMinimized(FALSE); // to reenable minimize button if it was minimized new_host->showFloater(self); // make sure host is visible @@ -1709,6 +1712,18 @@ void LLFloater::onClickHelp( LLFloater* self ) } } +void LLFloater::initRectControl() +{ + // save_rect and save_visibility only apply to registered floaters + if (mSaveRect) + { + std::string ctrl_name = getControlName(mInstanceName, mKey); + mRectControl = LLFloaterReg::declareRectControl(ctrl_name); + mPosXControl = LLFloaterReg::declarePosXControl(ctrl_name); + mPosYControl = LLFloaterReg::declarePosYControl(ctrl_name); + } +} + // static LLFloater* LLFloater::getClosableFloaterFromFocus() { @@ -2940,28 +2955,22 @@ void LLFloaterView::popVisibleAll(const skip_list_t& skip_list) void LLFloater::setInstanceName(const std::string& name) { - if (name == mInstanceName) - return; - llassert_always(mInstanceName.empty()); - mInstanceName = name; - if (!mInstanceName.empty()) + if (name != mInstanceName) { - std::string ctrl_name = getControlName(mInstanceName, mKey); - - // save_rect and save_visibility only apply to registered floaters - if (mSaveRect) - { - mRectControl = LLFloaterReg::declareRectControl(ctrl_name); - mPosXControl = LLFloaterReg::declarePosXControl(ctrl_name); - mPosYControl = LLFloaterReg::declarePosYControl(ctrl_name); - } - if (!mVisibilityControl.empty()) + llassert_always(mInstanceName.empty()); + mInstanceName = name; + if (!mInstanceName.empty()) { - mVisibilityControl = LLFloaterReg::declareVisibilityControl(ctrl_name); - } - if(!mDocStateControl.empty()) - { - mDocStateControl = LLFloaterReg::declareDockStateControl(ctrl_name); + std::string ctrl_name = getControlName(mInstanceName, mKey); + initRectControl(); + if (!mVisibilityControl.empty()) + { + mVisibilityControl = LLFloaterReg::declareVisibilityControl(ctrl_name); + } + if(!mDocStateControl.empty()) + { + mDocStateControl = LLFloaterReg::declareDockStateControl(ctrl_name); + } } } } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 5be6e6d922..a1cac64a4a 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -358,6 +358,7 @@ protected: void stackWith(LLFloater& other); + virtual void initRectControl(); virtual bool applyRectControl(); bool applyDockState(); void applyPositioning(LLFloater* other, bool on_open); diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index e80799b16d..02ff64dbc6 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -188,11 +188,13 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, floater_data.mHeight = floaterp->getRect().getHeight(); floater_data.mCanMinimize = floaterp->isMinimizeable(); floater_data.mCanResize = floaterp->isResizable(); + floater_data.mSaveRect = floaterp->mSaveRect; // remove minimize and close buttons floaterp->setCanMinimize(FALSE); floaterp->setCanResize(FALSE); floaterp->setCanDrag(FALSE); + floaterp->mSaveRect = FALSE; floaterp->storeRectControl(); // avoid double rendering of floater background (makes it more opaque) floaterp->setBackgroundVisible(FALSE); @@ -291,6 +293,7 @@ void LLMultiFloater::removeFloater(LLFloater* floaterp) { LLFloaterData& floater_data = found_data_it->second; floaterp->setCanMinimize(floater_data.mCanMinimize); + floaterp->mSaveRect = floater_data.mSaveRect; if (!floater_data.mCanResize) { // restore original size diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h index 44514a6246..d992212650 100644 --- a/indra/llui/llmultifloater.h +++ b/indra/llui/llmultifloater.h @@ -79,10 +79,11 @@ public: protected: struct LLFloaterData { - S32 mWidth; - S32 mHeight; - BOOL mCanMinimize; - BOOL mCanResize; + S32 mWidth; + S32 mHeight; + BOOL mCanMinimize; + BOOL mCanResize; + BOOL mSaveRect; }; LLTabContainer* mTabContainer; diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 3e23d75d28..b56f30312a 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -103,15 +103,15 @@ BOOL LLIMConversation::postBuild() mInputEditorTopPad = mChatHistory->getRect().mBottom - mInputEditor->getRect().mTop; - if (!isTornOff()) - { - setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); - } + setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); buildParticipantList(); updateHeaderAndToolbar(); + mSaveRect = isTornOff(); + initRectControl(); + if (isChatMultiTab()) { if (mIsNearbyChat) @@ -364,12 +364,14 @@ void LLIMConversation::onSlide(LLIMConversation* self) void LLIMConversation::onOpen(const LLSD& key) { LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); - if (host_floater) + bool is_hosted = !!host_floater; + if (is_hosted) { // Show the messages pane when opening a floater hosted in the Conversations host_floater->collapseMessagesPane(false); } + setTornOff(!is_hosted); updateHeaderAndToolbar(); } @@ -389,6 +391,9 @@ void LLIMConversation::onClose(bool app_quitting) void LLIMConversation::onTearOffClicked() { + setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); + mSaveRect = isTornOff(); + initRectControl(); LLFloater::onClickTearOff(this); updateHeaderAndToolbar(); } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index cc094fcaa1..d618e7491a 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -174,6 +174,11 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, mSessions[session_id] = floaterp; floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, session_id)); } + + // forced resize of the floater + LLRect wrapper_rect = this->mTabContainer->getLocalRect(); + floaterp->setRect(wrapper_rect); + mTabContainer->setTabImage(floaterp, icon); } diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index b628697bbc..8f0e6b4c83 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -150,8 +150,6 @@ BOOL LLNearbyChat::postBuild() // Register for font change notifications LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChat::onChatFontChange, this, _1)); - enableResizeCtrls(true, true, false); - // title must be defined BEFORE call addConversationListItem() because // it is used for show the item's name in the conversations list setTitle(getString("NearbyChatTitle")); diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 09c1510004..675967035f 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -15,7 +15,8 @@ can_resize="true" can_tear_off="false" min_width="250" - min_height="190"> + min_height="190" + positioning="relative"> <floater.string name="NearbyChatTitle" value="Nearby Chat"/> -- cgit v1.2.3 From 4e7c2c6942b6169812459f19cb13c9f4101dcaf1 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Thu, 2 Aug 2012 22:49:42 +0300 Subject: CHUI-228 FIX Inventory object creation date initialized with 0 to avoid some folders reporting wrong creation date. --- indra/llinventory/llinventory.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 6e54f9d78a..a80ae73dca 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -75,13 +75,15 @@ LLInventoryObject::LLInventoryObject(const LLUUID& uuid, mUUID(uuid), mParentUUID(parent_uuid), mType(type), - mName(name) + mName(name), + mCreationDate(0) { correctInventoryName(mName); } LLInventoryObject::LLInventoryObject() : - mType(LLAssetType::AT_NONE) + mType(LLAssetType::AT_NONE), + mCreationDate(0) { } -- cgit v1.2.3 From c44aa1c96655bc762f74583f92eedc155cf23a45 Mon Sep 17 00:00:00 2001 From: Todd Stinson <stinson@lindenlab.com> Date: Thu, 2 Aug 2012 17:26:09 -0700 Subject: CHUI-262: Reordering the steps to remove a view item and view item model during the deletion process to avoid a crash. --- indra/newview/llinventorypanel.cpp | 5 ++++- indra/newview/llvopartgroup.cpp | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 9403ccdabe..e67b59ddcc 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -514,10 +514,13 @@ void LLInventoryPanel::modelChanged(U32 mask) } else { + // Remove the item ID before destroying the view because the view-model-item gets + // destroyed when the view is destroyed + removeItemID(viewmodel_item->getUUID()); + // Item is to be moved outside the panel's directory (e.g. moved to trash for a panel that // doesn't include trash). Just remove the item's UI. view_item->destroyView(); - removeItemID(viewmodel_item->getUUID()); } } } diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index e21358b65a..a2794bec56 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -149,8 +149,8 @@ bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end) void LLVOPartGroup::freeVBSlot(S32 idx) { llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); - llassert(sVBSlotCursor > sVBSlotFree); - llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT)); + //llassert(sVBSlotCursor > sVBSlotFree); + //llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT)); if (sVBSlotCursor > sVBSlotFree) { -- cgit v1.2.3 From ae2de6bdcfa5ed40f820652193753b29bceaef80 Mon Sep 17 00:00:00 2001 From: Todd Stinson <stinson@lindenlab.com> Date: Thu, 2 Aug 2012 18:38:38 -0700 Subject: Re-enabling the voice-dot until I have more time to invest in the new CHUI version. --- indra/newview/llhudobject.h | 2 + indra/newview/llvoavatar.cpp | 2 + indra/newview/llvoicevisualizer.cpp | 1285 ++++++++++++++++++----------------- indra/newview/llvoicevisualizer.h | 1 + 4 files changed, 648 insertions(+), 642 deletions(-) (limited to 'indra') diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h index 21cf5fe17c..32cffe6839 100644 --- a/indra/newview/llhudobject.h +++ b/indra/newview/llhudobject.h @@ -39,6 +39,8 @@ #include "lldrawpool.h" // TODO: eliminate, unused below #include <list> +#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot + class LLViewerCamera; class LLFontGL; class LLFace; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 2871b7b018..20b33b5bea 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -34,6 +34,8 @@ #include "llvoavatar.h" +#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot + #include <stdio.h> #include <ctype.h> diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index dcf33bce10..d380a8672f 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -1,642 +1,643 @@ -/** - * @file llvoicevisualizer.cpp - * @brief Draws in-world speaking indicators. - * - * $LicenseInfo:firstyear=2000&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -//---------------------------------------------------------------------- -// Voice Visualizer -// author: JJ Ventrella -// (information about this stuff can be found in "llvoicevisualizer.h") -//---------------------------------------------------------------------- -#include "llviewerprecompiledheaders.h" -#include "llviewercontrol.h" -#include "llglheaders.h" -#include "llsphere.h" -#include "llvoicevisualizer.h" -#include "llviewercamera.h" -#include "llviewerobject.h" -#include "llviewertexture.h" -#include "llviewertexturelist.h" -#include "llvoiceclient.h" -#include "llrender.h" - -//brent's wave image -//29de489d-0491-fb00-7dab-f9e686d31e83 - - -#ifdef XXX_STINSON_CHUI_REWORK -//-------------------------------------------------------------------------------------- -// sound symbol constants -//-------------------------------------------------------------------------------------- -const F32 HEIGHT_ABOVE_HEAD = 0.3f; // how many meters vertically above the av's head the voice symbol will appear -const F32 RED_THRESHOLD = LLVoiceClient::OVERDRIVEN_POWER_LEVEL; // value above which speaking amplitude causes the voice symbol to turn red -const F32 GREEN_THRESHOLD = 0.2f; // value above which speaking amplitude causes the voice symbol to turn green -const F32 FADE_OUT_DURATION = 0.4f; // how many seconds it takes for a pair of waves to fade away -const F32 EXPANSION_RATE = 1.0f; // how many seconds it takes for the waves to expand to twice their original size -const F32 EXPANSION_MAX = 1.5f; // maximum size scale to which the waves can expand before popping back to 1.0 -const F32 WAVE_WIDTH_SCALE = 0.03f; // base width of the waves -const F32 WAVE_HEIGHT_SCALE = 0.02f; // base height of the waves -const F32 BASE_BRIGHTNESS = 0.7f; // gray level of the voice indicator when quiet (below green threshold) -const F32 DOT_SIZE = 0.05f; // size of the dot billboard texture -const F32 DOT_OPACITY = 0.7f; // how opaque the dot is -const F32 WAVE_MOTION_RATE = 1.5f; // scalar applied to consecutive waves as a function of speaking amplitude -#endif // XXX_STINSON_CHUI_REWORK - -//-------------------------------------------------------------------------------------- -// gesticulation constants -//-------------------------------------------------------------------------------------- -const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE = 0.2f; -const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE = 1.0f; - -#ifdef XXX_STINSON_CHUI_REWORK -//-------------------------------------------------------------------------------------- -// other constants -//-------------------------------------------------------------------------------------- -const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code. -const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL -#endif // XXX_STINSON_CHUI_REWORK - -//------------------------------------------------------------------ -// Initialize the statics -//------------------------------------------------------------------ -bool LLVoiceVisualizer::sPrefsInitialized = false; -BOOL LLVoiceVisualizer::sLipSyncEnabled = FALSE; -F32* LLVoiceVisualizer::sOoh = NULL; -F32* LLVoiceVisualizer::sAah = NULL; -U32 LLVoiceVisualizer::sOohs = 0; -U32 LLVoiceVisualizer::sAahs = 0; -F32 LLVoiceVisualizer::sOohAahRate = 0.0f; -F32* LLVoiceVisualizer::sOohPowerTransfer = NULL; -U32 LLVoiceVisualizer::sOohPowerTransfers = 0; -F32 LLVoiceVisualizer::sOohPowerTransfersf = 0.0f; -F32* LLVoiceVisualizer::sAahPowerTransfer = NULL; -U32 LLVoiceVisualizer::sAahPowerTransfers = 0; -F32 LLVoiceVisualizer::sAahPowerTransfersf = 0.0f; - - -//----------------------------------------------- -// constructor -//----------------------------------------------- -#ifdef XXX_STINSON_CHUI_REWORK -LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) -#else // XXX_STINSON_CHUI_REWORK -LLVoiceVisualizer::LLVoiceVisualizer() - : LLRefCount(), - mTimer(), - mStartTime(0.0), - mCurrentlySpeaking(false), - mSpeakingAmplitude(0.0f), - mMaxGesticulationAmplitude(DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE), - mMinGesticulationAmplitude(DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE) -#endif // XXX_STINSON_CHUI_REWORK -{ -#ifdef XXX_STINSON_CHUI_REWORK - mCurrentTime = mTimer.getTotalSeconds(); - mPreviousTime = mCurrentTime; - mStartTime = mCurrentTime; -#else // XXX_STINSON_CHUI_REWORK - mStartTime = mTimer.getTotalSeconds(); -#endif // XXX_STINSON_CHUI_REWORK -#ifdef XXX_STINSON_CHUI_REWORK - mVoiceSourceWorldPosition = LLVector3( 0.0f, 0.0f, 0.0f ); - mSpeakingAmplitude = 0.0f; - mCurrentlySpeaking = false; - mVoiceEnabled = false; - mMinGesticulationAmplitude = DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE; - mMaxGesticulationAmplitude = DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE; - mSoundSymbol.mActive = true; - mSoundSymbol.mPosition = LLVector3( 0.0f, 0.0f, 0.0f ); -#endif // XXX_STINSON_CHUI_REWORK - - mTimer.reset(); - -#ifdef XXX_STINSON_CHUI_REWORK - const char* sound_level_img[] = - { - "voice_meter_dot.j2c", - "voice_meter_rings.j2c", - "voice_meter_rings.j2c", - "voice_meter_rings.j2c", - "voice_meter_rings.j2c", - "voice_meter_rings.j2c", - "voice_meter_rings.j2c" - }; - - for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) - { - mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; - mSoundSymbol.mTexture [i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FALSE, LLViewerTexture::BOOST_UI); - mSoundSymbol.mWaveActive [i] = false; - mSoundSymbol.mWaveOpacity [i] = 1.0f; - mSoundSymbol.mWaveExpansion [i] = 1.0f; - } - - mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); -#endif // XXX_STINSON_CHUI_REWORK - - // The first instance loads the initial state from prefs. - if (!sPrefsInitialized) - { - setPreferences(); - - // Set up our listener to get updates on all prefs values we care about. - gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); - gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); - gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); - gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); - gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); - gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); - - sPrefsInitialized = true; - } - -}//--------------------------------------------------- - -#ifdef XXX_STINSON_CHUI_REWORK -//--------------------------------------------------- -void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m ) -{ - mMinGesticulationAmplitude = m; - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setMaxGesticulationAmplitude( F32 m ) -{ - mMaxGesticulationAmplitude = m; - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setVoiceEnabled( bool v ) -{ - mVoiceEnabled = v; - -}//--------------------------------------------------- -#endif // XXX_STINSON_CHUI_REWORK - -//--------------------------------------------------- -void LLVoiceVisualizer::setStartSpeaking() -{ - mStartTime = mTimer.getTotalSeconds(); - mCurrentlySpeaking = true; -#ifdef XXX_STINSON_CHUI_REWORK - mSoundSymbol.mActive = true; -#endif // XXX_STINSON_CHUI_REWORK - -}//--------------------------------------------------- - - -//--------------------------------------------------- -bool LLVoiceVisualizer::getCurrentlySpeaking() -{ - return mCurrentlySpeaking; - -}//--------------------------------------------------- - - -//--------------------------------------------------- -void LLVoiceVisualizer::setStopSpeaking() -{ - mCurrentlySpeaking = false; - mSpeakingAmplitude = 0.0f; - -}//--------------------------------------------------- - - -//--------------------------------------------------- -void LLVoiceVisualizer::setSpeakingAmplitude( F32 a ) -{ - mSpeakingAmplitude = a; - -}//--------------------------------------------------- - -//------------------------------------------------------------------ -// handles parameter updates -//------------------------------------------------------------------ -bool LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged(const LLSD& newvalue) -{ - // Note: Ignore the specific event value, we look up the ones we want - LLVoiceVisualizer::setPreferences(); - return true; -} - -//--------------------------------------------------- -void LLVoiceVisualizer::setPreferences( ) -{ - sLipSyncEnabled = gSavedSettings.getBOOL("LipSyncEnabled"); - sOohAahRate = gSavedSettings.getF32("LipSyncOohAahRate"); - - std::string oohString = gSavedSettings.getString("LipSyncOoh"); - lipStringToF32s (oohString, sOoh, sOohs); - - std::string aahString = gSavedSettings.getString("LipSyncAah"); - lipStringToF32s (aahString, sAah, sAahs); - - std::string oohPowerString = gSavedSettings.getString("LipSyncOohPowerTransfer"); - lipStringToF32s (oohPowerString, sOohPowerTransfer, sOohPowerTransfers); - sOohPowerTransfersf = (F32) sOohPowerTransfers; - - std::string aahPowerString = gSavedSettings.getString("LipSyncAahPowerTransfer"); - lipStringToF32s (aahPowerString, sAahPowerTransfer, sAahPowerTransfers); - sAahPowerTransfersf = (F32) sAahPowerTransfers; - -}//--------------------------------------------------- - - -//--------------------------------------------------- -// convert a string of digits to an array of floats. -// the result for each digit is the value of the -// digit multiplied by 0.11 -//--------------------------------------------------- -void LLVoiceVisualizer::lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ) -{ - delete[] out_F32s; // get rid of the current array - - count_F32s = in_string.length(); - if (count_F32s == 0) - { - // we don't like zero length arrays - - count_F32s = 1; - out_F32s = new F32[1]; - out_F32s[0] = 0.0f; - } - else - { - out_F32s = new F32[count_F32s]; - - for (U32 i=0; i<count_F32s; i++) - { - // we convert the characters 0 to 9 to their numeric value - // anything else we take the low order four bits with a ceiling of 9 - - U8 digit = in_string[i]; - U8 four_bits = digit % 16; - if (four_bits > 9) - { - four_bits = 9; - } - out_F32s[i] = 0.11f * (F32) four_bits; - } - } - -}//--------------------------------------------------- - - -//-------------------------------------------------------------------------- -// find the amount to blend the ooh and aah mouth morphs -//-------------------------------------------------------------------------- -void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah ) -{ - if( ( sLipSyncEnabled == TRUE ) && mCurrentlySpeaking ) - { - U32 transfer_index = (U32) (sOohPowerTransfersf * mSpeakingAmplitude); - if (transfer_index >= sOohPowerTransfers) - { - transfer_index = sOohPowerTransfers - 1; - } - F32 transfer_ooh = sOohPowerTransfer[transfer_index]; - - transfer_index = (U32) (sAahPowerTransfersf * mSpeakingAmplitude); - if (transfer_index >= sAahPowerTransfers) - { - transfer_index = sAahPowerTransfers - 1; - } - F32 transfer_aah = sAahPowerTransfer[transfer_index]; - - F64 current_time = mTimer.getTotalSeconds(); - F64 elapsed_time = current_time - mStartTime; - U32 elapsed_frames = (U32) (elapsed_time * sOohAahRate); - U32 elapsed_oohs = elapsed_frames % sOohs; - U32 elapsed_aahs = elapsed_frames % sAahs; - - ooh = transfer_ooh * sOoh[elapsed_oohs]; - aah = transfer_aah * sAah[elapsed_aahs]; - - /* - llinfos << " elapsed frames " << elapsed_frames - << " ooh " << ooh - << " aah " << aah - << " transfer ooh" << transfer_ooh - << " transfer aah" << transfer_aah - << " start time " << mStartTime - << " current time " << current_time - << " elapsed time " << elapsed_time - << " elapsed oohs " << elapsed_oohs - << " elapsed aahs " << elapsed_aahs - << llendl; - */ - } - else - { - ooh = 0.0f; - aah = 0.0f; - } - -}//--------------------------------------------------- - - -#ifdef XXX_STINSON_CHUI_REWORK -//--------------------------------------------------- -// this method is inherited from HUD Effect -//--------------------------------------------------- -void LLVoiceVisualizer::render() -{ - if ( ! mVoiceEnabled ) - { - return; - } - - if ( mSoundSymbol.mActive ) - { - mPreviousTime = mCurrentTime; - mCurrentTime = mTimer.getTotalSeconds(); - - //--------------------------------------------------------------- - // set the sound symbol position over the source (avatar's head) - //--------------------------------------------------------------- - mSoundSymbol.mPosition = mVoiceSourceWorldPosition + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD; - - //--------------------------------------------------------------- - // some gl state - //--------------------------------------------------------------- - LLGLSPipelineAlpha alpha_blend; - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - - //------------------------------------------------------------- - // create coordinates of the geometry for the dot - //------------------------------------------------------------- - LLViewerCamera* camera = LLViewerCamera::getInstance(); - LLVector3 l = camera->getLeftAxis() * DOT_SIZE; - LLVector3 u = camera->getUpAxis() * DOT_SIZE; - - LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u; - LLVector3 bottomRight = mSoundSymbol.mPosition - l - u; - LLVector3 topLeft = mSoundSymbol.mPosition + l + u; - LLVector3 topRight = mSoundSymbol.mPosition - l + u; - - //----------------------------- - // bind texture 0 (the dot) - //----------------------------- - gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[0]); - - //------------------------------------------------------------- - // now render the dot - //------------------------------------------------------------- - gGL.color4fv( LLColor4( 1.0f, 1.0f, 1.0f, DOT_OPACITY ).mV ); - - gGL.begin( LLRender::TRIANGLE_STRIP ); - gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV ); - gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); - gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); - gGL.end(); - - gGL.begin( LLRender::TRIANGLE_STRIP ); - gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); - gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV ); - gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); - gGL.end(); - - - - //-------------------------------------------------------------------------------------- - // if currently speaking, trigger waves (1 through 6) based on speaking amplitude - //-------------------------------------------------------------------------------------- - if ( mCurrentlySpeaking ) - { - F32 min = 0.2f; - F32 max = 0.7f; - F32 fraction = ( mSpeakingAmplitude - min ) / ( max - min ); - - // in case mSpeakingAmplitude > max.... - if ( fraction > 1.0f ) - { - fraction = 1.0f; - } - - S32 level = 1 + (int)( fraction * ( NUM_VOICE_SYMBOL_WAVES - 2 ) ); - - for (int i=0; i<level+1; i++) - { - mSoundSymbol.mWaveActive [i] = true; - mSoundSymbol.mWaveOpacity [i] = 1.0f; - mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; - } - - } // if currently speaking - - //--------------------------------------------------- - // determine color - //--------------------------------------------------- - F32 red = 0.0f; - F32 green = 0.0f; - F32 blue = 0.0f; - if ( mSpeakingAmplitude < RED_THRESHOLD ) - { - if ( mSpeakingAmplitude < GREEN_THRESHOLD ) - { - red = BASE_BRIGHTNESS; - green = BASE_BRIGHTNESS; - blue = BASE_BRIGHTNESS; - } - else - { - //--------------------------------------------------- - // fade from gray to bright green - //--------------------------------------------------- - F32 fraction = ( mSpeakingAmplitude - GREEN_THRESHOLD ) / ( 1.0f - GREEN_THRESHOLD ); - red = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS ); - green = BASE_BRIGHTNESS + fraction * ( 1.0f - BASE_BRIGHTNESS ); - blue = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS ); - } - } - else - { - //--------------------------------------------------- - // redish - //--------------------------------------------------- - red = 1.0f; - green = 0.2f; - blue = 0.2f; - } - - for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) - { - if ( mSoundSymbol.mWaveActive[i] ) - { - F32 fadeOutFraction = (F32)( mCurrentTime - mSoundSymbol.mWaveFadeOutStartTime[i] ) / FADE_OUT_DURATION; - - mSoundSymbol.mWaveOpacity[i] = 1.0f - fadeOutFraction; - - if ( mSoundSymbol.mWaveOpacity[i] < 0.0f ) - { - mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; - mSoundSymbol.mWaveOpacity [i] = 0.0f; - mSoundSymbol.mWaveActive [i] = false; - } - - //---------------------------------------------------------------------------------- - // This is where we calculate the expansion of the waves - that is, the - // rate at which they are scaled greater than 1.0 so that they grow over time. - //---------------------------------------------------------------------------------- - F32 timeSlice = (F32)( mCurrentTime - mPreviousTime ); - F32 waveSpeed = mSpeakingAmplitude * WAVE_MOTION_RATE; - mSoundSymbol.mWaveExpansion[i] *= ( 1.0f + EXPANSION_RATE * timeSlice * waveSpeed ); - - if ( mSoundSymbol.mWaveExpansion[i] > EXPANSION_MAX ) - { - mSoundSymbol.mWaveExpansion[i] = 1.0f; - } - - //---------------------------------------------------------------------------------- - // create geometry for the wave billboard textures - //---------------------------------------------------------------------------------- - F32 width = i * WAVE_WIDTH_SCALE * mSoundSymbol.mWaveExpansion[i]; - F32 height = i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i]; - - LLVector3 l = camera->getLeftAxis() * width; - LLVector3 u = camera->getUpAxis() * height; - - LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u; - LLVector3 bottomRight = mSoundSymbol.mPosition - l - u; - LLVector3 topLeft = mSoundSymbol.mPosition + l + u; - LLVector3 topRight = mSoundSymbol.mPosition - l + u; - - gGL.color4fv( LLColor4( red, green, blue, mSoundSymbol.mWaveOpacity[i] ).mV ); - gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[i]); - - - //--------------------------------------------------- - // now, render the mofo - //--------------------------------------------------- - gGL.begin( LLRender::TRIANGLE_STRIP ); - gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV ); - gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); - gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); - gGL.end(); - - gGL.begin( LLRender::TRIANGLE_STRIP ); - gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); - gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV ); - gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); - gGL.end(); - - } //if ( mSoundSymbol.mWaveActive[i] ) - - }// for loop - - }//if ( mSoundSymbol.mActive ) - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p ) -{ - mVoiceSourceWorldPosition = p; - -}//--------------------------------------------------- -#endif // XXX_STINSON_CHUI_REWORK - -//--------------------------------------------------- -VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel() -{ - VoiceGesticulationLevel gesticulationLevel = VOICE_GESTICULATION_LEVEL_OFF; //default - - //----------------------------------------------------------------------------------------- - // Within the range of gesticulation amplitudes, the sound signal is split into - // three equal amplitude regimes, each specifying one of three gesticulation levels. - //----------------------------------------------------------------------------------------- - F32 range = mMaxGesticulationAmplitude - mMinGesticulationAmplitude; - - if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.5f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_HIGH; } - else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.25f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_MEDIUM; } - else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.00000f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_LOW; } - - return gesticulationLevel; - -}//--------------------------------------------------- - - - -//------------------------------------ -// Destructor -//------------------------------------ -LLVoiceVisualizer::~LLVoiceVisualizer() -{ -}//---------------------------------------------- - - -#ifdef XXX_STINSON_CHUI_REWORK -//--------------------------------------------------- -// "packData" is inherited from HUDEffect -//--------------------------------------------------- -void LLVoiceVisualizer::packData(LLMessageSystem *mesgsys) -{ - // Pack the default data - LLHUDEffect::packData(mesgsys); - - // TODO -- pack the relevant data for voice effects - // we'll come up with some cool configurations....TBD - //U8 packed_data[41]; - //mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41); - U8 packed_data = 0; - mesgsys->addBinaryDataFast(_PREHASH_TypeData, &packed_data, 1); -} - - -//--------------------------------------------------- -// "unpackData" is inherited from HUDEffect -//--------------------------------------------------- -void LLVoiceVisualizer::unpackData(LLMessageSystem *mesgsys, S32 blocknum) -{ - // TODO -- find the speaker, unpack binary data, set the properties of this effect - /* - LLHUDEffect::unpackData(mesgsys, blocknum); - LLUUID source_id; - LLUUID target_id; - S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); - if (size != 1) - { - llwarns << "Voice effect with bad size " << size << llendl; - return; - } - mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 1, blocknum); - */ -} - - -//------------------------------------------------------------------ -// this method is inherited from HUD Effect -//------------------------------------------------------------------ -void LLVoiceVisualizer::markDead() -{ - mCurrentlySpeaking = false; - mVoiceEnabled = false; - mSoundSymbol.mActive = false; - - LLHUDEffect::markDead(); -}//------------------------------------------------------------------ - -#endif // XXX_STINSON_CHUI_REWORK +/** + * @file llvoicevisualizer.cpp + * @brief Draws in-world speaking indicators. + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//---------------------------------------------------------------------- +// Voice Visualizer +// author: JJ Ventrella +// (information about this stuff can be found in "llvoicevisualizer.h") +//---------------------------------------------------------------------- +#include "llviewerprecompiledheaders.h" +#include "llviewercontrol.h" +#include "llglheaders.h" +#include "llsphere.h" +#include "llvoicevisualizer.h" +#include "llviewercamera.h" +#include "llviewerobject.h" +#include "llviewertexture.h" +#include "llviewertexturelist.h" +#include "llvoiceclient.h" +#include "llrender.h" + +//brent's wave image +//29de489d-0491-fb00-7dab-f9e686d31e83 + + +#ifdef XXX_STINSON_CHUI_REWORK +//-------------------------------------------------------------------------------------- +// sound symbol constants +//-------------------------------------------------------------------------------------- +const F32 HEIGHT_ABOVE_HEAD = 0.3f; // how many meters vertically above the av's head the voice symbol will appear +const F32 RED_THRESHOLD = LLVoiceClient::OVERDRIVEN_POWER_LEVEL; // value above which speaking amplitude causes the voice symbol to turn red +const F32 GREEN_THRESHOLD = 0.2f; // value above which speaking amplitude causes the voice symbol to turn green +const F32 FADE_OUT_DURATION = 0.4f; // how many seconds it takes for a pair of waves to fade away +const F32 EXPANSION_RATE = 1.0f; // how many seconds it takes for the waves to expand to twice their original size +const F32 EXPANSION_MAX = 1.5f; // maximum size scale to which the waves can expand before popping back to 1.0 +const F32 WAVE_WIDTH_SCALE = 0.03f; // base width of the waves +const F32 WAVE_HEIGHT_SCALE = 0.02f; // base height of the waves +const F32 BASE_BRIGHTNESS = 0.7f; // gray level of the voice indicator when quiet (below green threshold) +const F32 DOT_SIZE = 0.05f; // size of the dot billboard texture +const F32 DOT_OPACITY = 0.7f; // how opaque the dot is +const F32 WAVE_MOTION_RATE = 1.5f; // scalar applied to consecutive waves as a function of speaking amplitude +#endif // XXX_STINSON_CHUI_REWORK + +//-------------------------------------------------------------------------------------- +// gesticulation constants +//-------------------------------------------------------------------------------------- +const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE = 0.2f; +const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE = 1.0f; + +#ifdef XXX_STINSON_CHUI_REWORK +//-------------------------------------------------------------------------------------- +// other constants +//-------------------------------------------------------------------------------------- +const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code. +const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL +#endif // XXX_STINSON_CHUI_REWORK + +//------------------------------------------------------------------ +// Initialize the statics +//------------------------------------------------------------------ +bool LLVoiceVisualizer::sPrefsInitialized = false; +BOOL LLVoiceVisualizer::sLipSyncEnabled = FALSE; +F32* LLVoiceVisualizer::sOoh = NULL; +F32* LLVoiceVisualizer::sAah = NULL; +U32 LLVoiceVisualizer::sOohs = 0; +U32 LLVoiceVisualizer::sAahs = 0; +F32 LLVoiceVisualizer::sOohAahRate = 0.0f; +F32* LLVoiceVisualizer::sOohPowerTransfer = NULL; +U32 LLVoiceVisualizer::sOohPowerTransfers = 0; +F32 LLVoiceVisualizer::sOohPowerTransfersf = 0.0f; +F32* LLVoiceVisualizer::sAahPowerTransfer = NULL; +U32 LLVoiceVisualizer::sAahPowerTransfers = 0; +F32 LLVoiceVisualizer::sAahPowerTransfersf = 0.0f; + + +//----------------------------------------------- +// constructor +//----------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK +LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) + : LLHUDEffect(type) +#else // XXX_STINSON_CHUI_REWORK +LLVoiceVisualizer::LLVoiceVisualizer() + : LLRefCount(), + mTimer(), + mStartTime(0.0), + mCurrentlySpeaking(false), + mSpeakingAmplitude(0.0f), + mMaxGesticulationAmplitude(DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE), + mMinGesticulationAmplitude(DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE) +#endif // XXX_STINSON_CHUI_REWORK +{ +#ifdef XXX_STINSON_CHUI_REWORK + mCurrentTime = mTimer.getTotalSeconds(); + mPreviousTime = mCurrentTime; + mStartTime = mCurrentTime; +#else // XXX_STINSON_CHUI_REWORK + mStartTime = mTimer.getTotalSeconds(); +#endif // XXX_STINSON_CHUI_REWORK +#ifdef XXX_STINSON_CHUI_REWORK + mVoiceSourceWorldPosition = LLVector3( 0.0f, 0.0f, 0.0f ); + mSpeakingAmplitude = 0.0f; + mCurrentlySpeaking = false; + mVoiceEnabled = false; + mMinGesticulationAmplitude = DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE; + mMaxGesticulationAmplitude = DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE; + mSoundSymbol.mActive = true; + mSoundSymbol.mPosition = LLVector3( 0.0f, 0.0f, 0.0f ); +#endif // XXX_STINSON_CHUI_REWORK + + mTimer.reset(); + +#ifdef XXX_STINSON_CHUI_REWORK + const char* sound_level_img[] = + { + "voice_meter_dot.j2c", + "voice_meter_rings.j2c", + "voice_meter_rings.j2c", + "voice_meter_rings.j2c", + "voice_meter_rings.j2c", + "voice_meter_rings.j2c", + "voice_meter_rings.j2c" + }; + + for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) + { + mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; + mSoundSymbol.mTexture [i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FALSE, LLViewerTexture::BOOST_UI); + mSoundSymbol.mWaveActive [i] = false; + mSoundSymbol.mWaveOpacity [i] = 1.0f; + mSoundSymbol.mWaveExpansion [i] = 1.0f; + } + + mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); +#endif // XXX_STINSON_CHUI_REWORK + + // The first instance loads the initial state from prefs. + if (!sPrefsInitialized) + { + setPreferences(); + + // Set up our listener to get updates on all prefs values we care about. + gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); + gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); + gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); + gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); + gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); + gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); + + sPrefsInitialized = true; + } + +}//--------------------------------------------------- + +#ifdef XXX_STINSON_CHUI_REWORK +//--------------------------------------------------- +void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m ) +{ + mMinGesticulationAmplitude = m; + +}//--------------------------------------------------- + +//--------------------------------------------------- +void LLVoiceVisualizer::setMaxGesticulationAmplitude( F32 m ) +{ + mMaxGesticulationAmplitude = m; + +}//--------------------------------------------------- + +//--------------------------------------------------- +void LLVoiceVisualizer::setVoiceEnabled( bool v ) +{ + mVoiceEnabled = v; + +}//--------------------------------------------------- +#endif // XXX_STINSON_CHUI_REWORK + +//--------------------------------------------------- +void LLVoiceVisualizer::setStartSpeaking() +{ + mStartTime = mTimer.getTotalSeconds(); + mCurrentlySpeaking = true; +#ifdef XXX_STINSON_CHUI_REWORK + mSoundSymbol.mActive = true; +#endif // XXX_STINSON_CHUI_REWORK + +}//--------------------------------------------------- + + +//--------------------------------------------------- +bool LLVoiceVisualizer::getCurrentlySpeaking() +{ + return mCurrentlySpeaking; + +}//--------------------------------------------------- + + +//--------------------------------------------------- +void LLVoiceVisualizer::setStopSpeaking() +{ + mCurrentlySpeaking = false; + mSpeakingAmplitude = 0.0f; + +}//--------------------------------------------------- + + +//--------------------------------------------------- +void LLVoiceVisualizer::setSpeakingAmplitude( F32 a ) +{ + mSpeakingAmplitude = a; + +}//--------------------------------------------------- + +//------------------------------------------------------------------ +// handles parameter updates +//------------------------------------------------------------------ +bool LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged(const LLSD& newvalue) +{ + // Note: Ignore the specific event value, we look up the ones we want + LLVoiceVisualizer::setPreferences(); + return true; +} + +//--------------------------------------------------- +void LLVoiceVisualizer::setPreferences( ) +{ + sLipSyncEnabled = gSavedSettings.getBOOL("LipSyncEnabled"); + sOohAahRate = gSavedSettings.getF32("LipSyncOohAahRate"); + + std::string oohString = gSavedSettings.getString("LipSyncOoh"); + lipStringToF32s (oohString, sOoh, sOohs); + + std::string aahString = gSavedSettings.getString("LipSyncAah"); + lipStringToF32s (aahString, sAah, sAahs); + + std::string oohPowerString = gSavedSettings.getString("LipSyncOohPowerTransfer"); + lipStringToF32s (oohPowerString, sOohPowerTransfer, sOohPowerTransfers); + sOohPowerTransfersf = (F32) sOohPowerTransfers; + + std::string aahPowerString = gSavedSettings.getString("LipSyncAahPowerTransfer"); + lipStringToF32s (aahPowerString, sAahPowerTransfer, sAahPowerTransfers); + sAahPowerTransfersf = (F32) sAahPowerTransfers; + +}//--------------------------------------------------- + + +//--------------------------------------------------- +// convert a string of digits to an array of floats. +// the result for each digit is the value of the +// digit multiplied by 0.11 +//--------------------------------------------------- +void LLVoiceVisualizer::lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ) +{ + delete[] out_F32s; // get rid of the current array + + count_F32s = in_string.length(); + if (count_F32s == 0) + { + // we don't like zero length arrays + + count_F32s = 1; + out_F32s = new F32[1]; + out_F32s[0] = 0.0f; + } + else + { + out_F32s = new F32[count_F32s]; + + for (U32 i=0; i<count_F32s; i++) + { + // we convert the characters 0 to 9 to their numeric value + // anything else we take the low order four bits with a ceiling of 9 + + U8 digit = in_string[i]; + U8 four_bits = digit % 16; + if (four_bits > 9) + { + four_bits = 9; + } + out_F32s[i] = 0.11f * (F32) four_bits; + } + } + +}//--------------------------------------------------- + + +//-------------------------------------------------------------------------- +// find the amount to blend the ooh and aah mouth morphs +//-------------------------------------------------------------------------- +void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah ) +{ + if( ( sLipSyncEnabled == TRUE ) && mCurrentlySpeaking ) + { + U32 transfer_index = (U32) (sOohPowerTransfersf * mSpeakingAmplitude); + if (transfer_index >= sOohPowerTransfers) + { + transfer_index = sOohPowerTransfers - 1; + } + F32 transfer_ooh = sOohPowerTransfer[transfer_index]; + + transfer_index = (U32) (sAahPowerTransfersf * mSpeakingAmplitude); + if (transfer_index >= sAahPowerTransfers) + { + transfer_index = sAahPowerTransfers - 1; + } + F32 transfer_aah = sAahPowerTransfer[transfer_index]; + + F64 current_time = mTimer.getTotalSeconds(); + F64 elapsed_time = current_time - mStartTime; + U32 elapsed_frames = (U32) (elapsed_time * sOohAahRate); + U32 elapsed_oohs = elapsed_frames % sOohs; + U32 elapsed_aahs = elapsed_frames % sAahs; + + ooh = transfer_ooh * sOoh[elapsed_oohs]; + aah = transfer_aah * sAah[elapsed_aahs]; + + /* + llinfos << " elapsed frames " << elapsed_frames + << " ooh " << ooh + << " aah " << aah + << " transfer ooh" << transfer_ooh + << " transfer aah" << transfer_aah + << " start time " << mStartTime + << " current time " << current_time + << " elapsed time " << elapsed_time + << " elapsed oohs " << elapsed_oohs + << " elapsed aahs " << elapsed_aahs + << llendl; + */ + } + else + { + ooh = 0.0f; + aah = 0.0f; + } + +}//--------------------------------------------------- + + +#ifdef XXX_STINSON_CHUI_REWORK +//--------------------------------------------------- +// this method is inherited from HUD Effect +//--------------------------------------------------- +void LLVoiceVisualizer::render() +{ + if ( ! mVoiceEnabled ) + { + return; + } + + if ( mSoundSymbol.mActive ) + { + mPreviousTime = mCurrentTime; + mCurrentTime = mTimer.getTotalSeconds(); + + //--------------------------------------------------------------- + // set the sound symbol position over the source (avatar's head) + //--------------------------------------------------------------- + mSoundSymbol.mPosition = mVoiceSourceWorldPosition + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD; + + //--------------------------------------------------------------- + // some gl state + //--------------------------------------------------------------- + LLGLSPipelineAlpha alpha_blend; + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + + //------------------------------------------------------------- + // create coordinates of the geometry for the dot + //------------------------------------------------------------- + LLViewerCamera* camera = LLViewerCamera::getInstance(); + LLVector3 l = camera->getLeftAxis() * DOT_SIZE; + LLVector3 u = camera->getUpAxis() * DOT_SIZE; + + LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u; + LLVector3 bottomRight = mSoundSymbol.mPosition - l - u; + LLVector3 topLeft = mSoundSymbol.mPosition + l + u; + LLVector3 topRight = mSoundSymbol.mPosition - l + u; + + //----------------------------- + // bind texture 0 (the dot) + //----------------------------- + gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[0]); + + //------------------------------------------------------------- + // now render the dot + //------------------------------------------------------------- + gGL.color4fv( LLColor4( 1.0f, 1.0f, 1.0f, DOT_OPACITY ).mV ); + + gGL.begin( LLRender::TRIANGLE_STRIP ); + gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV ); + gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); + gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); + gGL.end(); + + gGL.begin( LLRender::TRIANGLE_STRIP ); + gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); + gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV ); + gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); + gGL.end(); + + + + //-------------------------------------------------------------------------------------- + // if currently speaking, trigger waves (1 through 6) based on speaking amplitude + //-------------------------------------------------------------------------------------- + if ( mCurrentlySpeaking ) + { + F32 min = 0.2f; + F32 max = 0.7f; + F32 fraction = ( mSpeakingAmplitude - min ) / ( max - min ); + + // in case mSpeakingAmplitude > max.... + if ( fraction > 1.0f ) + { + fraction = 1.0f; + } + + S32 level = 1 + (int)( fraction * ( NUM_VOICE_SYMBOL_WAVES - 2 ) ); + + for (int i=0; i<level+1; i++) + { + mSoundSymbol.mWaveActive [i] = true; + mSoundSymbol.mWaveOpacity [i] = 1.0f; + mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; + } + + } // if currently speaking + + //--------------------------------------------------- + // determine color + //--------------------------------------------------- + F32 red = 0.0f; + F32 green = 0.0f; + F32 blue = 0.0f; + if ( mSpeakingAmplitude < RED_THRESHOLD ) + { + if ( mSpeakingAmplitude < GREEN_THRESHOLD ) + { + red = BASE_BRIGHTNESS; + green = BASE_BRIGHTNESS; + blue = BASE_BRIGHTNESS; + } + else + { + //--------------------------------------------------- + // fade from gray to bright green + //--------------------------------------------------- + F32 fraction = ( mSpeakingAmplitude - GREEN_THRESHOLD ) / ( 1.0f - GREEN_THRESHOLD ); + red = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS ); + green = BASE_BRIGHTNESS + fraction * ( 1.0f - BASE_BRIGHTNESS ); + blue = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS ); + } + } + else + { + //--------------------------------------------------- + // redish + //--------------------------------------------------- + red = 1.0f; + green = 0.2f; + blue = 0.2f; + } + + for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) + { + if ( mSoundSymbol.mWaveActive[i] ) + { + F32 fadeOutFraction = (F32)( mCurrentTime - mSoundSymbol.mWaveFadeOutStartTime[i] ) / FADE_OUT_DURATION; + + mSoundSymbol.mWaveOpacity[i] = 1.0f - fadeOutFraction; + + if ( mSoundSymbol.mWaveOpacity[i] < 0.0f ) + { + mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; + mSoundSymbol.mWaveOpacity [i] = 0.0f; + mSoundSymbol.mWaveActive [i] = false; + } + + //---------------------------------------------------------------------------------- + // This is where we calculate the expansion of the waves - that is, the + // rate at which they are scaled greater than 1.0 so that they grow over time. + //---------------------------------------------------------------------------------- + F32 timeSlice = (F32)( mCurrentTime - mPreviousTime ); + F32 waveSpeed = mSpeakingAmplitude * WAVE_MOTION_RATE; + mSoundSymbol.mWaveExpansion[i] *= ( 1.0f + EXPANSION_RATE * timeSlice * waveSpeed ); + + if ( mSoundSymbol.mWaveExpansion[i] > EXPANSION_MAX ) + { + mSoundSymbol.mWaveExpansion[i] = 1.0f; + } + + //---------------------------------------------------------------------------------- + // create geometry for the wave billboard textures + //---------------------------------------------------------------------------------- + F32 width = i * WAVE_WIDTH_SCALE * mSoundSymbol.mWaveExpansion[i]; + F32 height = i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i]; + + LLVector3 l = camera->getLeftAxis() * width; + LLVector3 u = camera->getUpAxis() * height; + + LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u; + LLVector3 bottomRight = mSoundSymbol.mPosition - l - u; + LLVector3 topLeft = mSoundSymbol.mPosition + l + u; + LLVector3 topRight = mSoundSymbol.mPosition - l + u; + + gGL.color4fv( LLColor4( red, green, blue, mSoundSymbol.mWaveOpacity[i] ).mV ); + gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[i]); + + + //--------------------------------------------------- + // now, render the mofo + //--------------------------------------------------- + gGL.begin( LLRender::TRIANGLE_STRIP ); + gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV ); + gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); + gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); + gGL.end(); + + gGL.begin( LLRender::TRIANGLE_STRIP ); + gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); + gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV ); + gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); + gGL.end(); + + } //if ( mSoundSymbol.mWaveActive[i] ) + + }// for loop + + }//if ( mSoundSymbol.mActive ) + +}//--------------------------------------------------- + +//--------------------------------------------------- +void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p ) +{ + mVoiceSourceWorldPosition = p; + +}//--------------------------------------------------- +#endif // XXX_STINSON_CHUI_REWORK + +//--------------------------------------------------- +VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel() +{ + VoiceGesticulationLevel gesticulationLevel = VOICE_GESTICULATION_LEVEL_OFF; //default + + //----------------------------------------------------------------------------------------- + // Within the range of gesticulation amplitudes, the sound signal is split into + // three equal amplitude regimes, each specifying one of three gesticulation levels. + //----------------------------------------------------------------------------------------- + F32 range = mMaxGesticulationAmplitude - mMinGesticulationAmplitude; + + if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.5f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_HIGH; } + else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.25f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_MEDIUM; } + else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.00000f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_LOW; } + + return gesticulationLevel; + +}//--------------------------------------------------- + + + +//------------------------------------ +// Destructor +//------------------------------------ +LLVoiceVisualizer::~LLVoiceVisualizer() +{ +}//---------------------------------------------- + + +#ifdef XXX_STINSON_CHUI_REWORK +//--------------------------------------------------- +// "packData" is inherited from HUDEffect +//--------------------------------------------------- +void LLVoiceVisualizer::packData(LLMessageSystem *mesgsys) +{ + // Pack the default data + LLHUDEffect::packData(mesgsys); + + // TODO -- pack the relevant data for voice effects + // we'll come up with some cool configurations....TBD + //U8 packed_data[41]; + //mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41); + U8 packed_data = 0; + mesgsys->addBinaryDataFast(_PREHASH_TypeData, &packed_data, 1); +} + + +//--------------------------------------------------- +// "unpackData" is inherited from HUDEffect +//--------------------------------------------------- +void LLVoiceVisualizer::unpackData(LLMessageSystem *mesgsys, S32 blocknum) +{ + // TODO -- find the speaker, unpack binary data, set the properties of this effect + /* + LLHUDEffect::unpackData(mesgsys, blocknum); + LLUUID source_id; + LLUUID target_id; + S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); + if (size != 1) + { + llwarns << "Voice effect with bad size " << size << llendl; + return; + } + mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 1, blocknum); + */ +} + + +//------------------------------------------------------------------ +// this method is inherited from HUD Effect +//------------------------------------------------------------------ +void LLVoiceVisualizer::markDead() +{ + mCurrentlySpeaking = false; + mVoiceEnabled = false; + mSoundSymbol.mActive = false; + + LLHUDEffect::markDead(); +}//------------------------------------------------------------------ + +#endif // XXX_STINSON_CHUI_REWORK diff --git a/indra/newview/llvoicevisualizer.h b/indra/newview/llvoicevisualizer.h index 6258de163d..5da592c48e 100644 --- a/indra/newview/llvoicevisualizer.h +++ b/indra/newview/llvoicevisualizer.h @@ -42,6 +42,7 @@ #ifndef LL_VOICE_VISUALIZER_H #define LL_VOICE_VISUALIZER_H +#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot #ifdef XXX_STINSON_CHUI_REWORK #include "llhudeffect.h" #else // XXX_STINSON_CHUI_REWORK -- cgit v1.2.3 From faac868b682360df1bf461624667cc6e0bbdd8c6 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Thu, 2 Aug 2012 20:45:52 -0700 Subject: CHUI-223 FIX Selecting to cut an inventory item causes all open inventory windows to refresh --- indra/llui/llfolderview.cpp | 95 +++++++++++++------------------------- indra/llui/llfolderview.h | 10 ++-- indra/newview/llinventorypanel.cpp | 22 +++++++-- 3 files changed, 56 insertions(+), 71 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 5d98dc9663..fb09f7f0aa 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -749,28 +749,18 @@ void LLFolderView::removeSelectedItems() // iterate through the new container. count = items.size(); LLUUID new_selection_id; + LLFolderViewItem* item_to_select = getNextUnselectedItem(); + if(count == 1) { LLFolderViewItem* item_to_delete = items[0]; LLFolderViewFolder* parent = item_to_delete->getParentFolder(); - LLFolderViewItem* new_selection = item_to_delete->getNextOpenNode(FALSE); - if (!new_selection) - { - new_selection = item_to_delete->getPreviousOpenNode(FALSE); - } if(parent) { if (item_to_delete->remove()) { // change selection on successful delete - if (new_selection) - { - getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); - } - else - { - getRoot()->setSelection(NULL, mParentPanel->hasFocus()); - } + setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel->hasFocus()); } } arrangeAll(); @@ -779,28 +769,8 @@ void LLFolderView::removeSelectedItems() { LLDynamicArray<LLFolderViewModelItem*> listeners; LLFolderViewModelItem* listener; - LLFolderViewItem* last_item = items[count - 1]; - LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); - while(new_selection && new_selection->isSelected()) - { - new_selection = new_selection->getNextOpenNode(FALSE); - } - if (!new_selection) - { - new_selection = last_item->getPreviousOpenNode(FALSE); - while (new_selection && (new_selection->isInSelection())) - { - new_selection = new_selection->getPreviousOpenNode(FALSE); - } - } - if (new_selection) - { - getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); - } - else - { - getRoot()->setSelection(NULL, mParentPanel->hasFocus()); - } + + setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel->hasFocus()); for(S32 i = 0; i < count; ++i) { @@ -1032,28 +1002,13 @@ void LLFolderView::cut() S32 count = mSelectedItems.size(); if(getVisible() && getEnabled() && (count > 0)) { - LLFolderViewModelItem* listener = NULL; - - LLFolderViewItem* last_item = *mSelectedItems.rbegin();; - LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); - while(new_selection && new_selection->isSelected()) - { - new_selection = new_selection->getNextOpenNode(FALSE); - } - if (!new_selection) - { - new_selection = last_item->getPreviousOpenNode(FALSE); - while (new_selection && (new_selection->isInSelection())) - { - new_selection = new_selection->getPreviousOpenNode(FALSE); - } - } + LLFolderViewItem* item_to_select = getNextUnselectedItem(); selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { LLFolderViewItem* item_to_cut = *item_it; - listener = item_to_cut->getViewModelItem(); + LLFolderViewModelItem* listener = item_to_cut->getViewModelItem(); if(listener) { listener->cutToClipboard(); @@ -1061,14 +1016,7 @@ void LLFolderView::cut() } } - if (new_selection) - { - setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); - } - else - { - setSelection(NULL, mParentPanel->hasFocus()); - } + setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel->hasFocus()); } mSearchString.clear(); } @@ -1274,12 +1222,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if (next->isSelected()) { // shrink selection - getRoot()->changeSelection(last_selected, FALSE); + changeSelection(last_selected, FALSE); } else if (last_selected->getParentFolder() == next->getParentFolder()) { // grow selection - getRoot()->changeSelection(next, TRUE); + changeSelection(next, TRUE); } } } @@ -1338,12 +1286,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if (prev->isSelected()) { // shrink selection - getRoot()->changeSelection(last_selected, FALSE); + changeSelection(last_selected, FALSE); } else if (last_selected->getParentFolder() == prev->getParentFolder()) { // grow selection - getRoot()->changeSelection(prev, TRUE); + changeSelection(prev, TRUE); } } } @@ -2083,3 +2031,22 @@ S32 LLFolderView::getItemHeight() } return 0; } + +LLFolderViewItem* LLFolderView::getNextUnselectedItem() +{ + LLFolderViewItem* last_item = *mSelectedItems.rbegin(); + LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); + while(new_selection && new_selection->isSelected()) + { + new_selection = new_selection->getNextOpenNode(FALSE); + } + if (!new_selection) + { + new_selection = last_item->getPreviousOpenNode(FALSE); + while (new_selection && (new_selection->isInSelection())) + { + new_selection = new_selection->getPreviousOpenNode(FALSE); + } + } + return new_selection; +} diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 05beff9bd8..81b0f087e8 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -172,17 +172,19 @@ public: BOOL isOpen() const { return TRUE; } // root folder always open // Copy & paste - virtual void copy(); virtual BOOL canCopy() const; + virtual void copy(); - virtual void cut(); virtual BOOL canCut() const; + virtual void cut(); - virtual void paste(); virtual BOOL canPaste() const; + virtual void paste(); - virtual void doDelete(); virtual BOOL canDoDelete() const; + virtual void doDelete(); + + LLFolderViewItem* getNextUnselectedItem(); // Public rename functionality - can only start the process void startRenamingSelectedItem( void ); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 9403ccdabe..b02d08955f 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -604,9 +604,25 @@ void LLInventoryPanel::idle(void* user_data) if (panel->mClipboardState != LLClipboard::instance().getGeneration()) { panel->mClipboardState = LLClipboard::instance().getGeneration(); - panel->getFilter().setModified(LLClipboard::instance().isCutMode() - ? LLInventoryFilter::FILTER_MORE_RESTRICTIVE - : LLInventoryFilter::FILTER_LESS_RESTRICTIVE); + if (LLClipboard::instance().isCutMode()) + { + LLDynamicArray<LLUUID> objects; + LLClipboard::instance().pasteFromClipboard(objects); + + for (LLDynamicArray<LLUUID>::iterator it = objects.begin(), end_it = objects.end(); + it != end_it; + ++it) + { + LLFolderViewItem* item = panel->getItemByID(*it); + if (item) + { + item->getViewModelItem()->dirtyFilter(); + } + } + /*panel->getFilter().setModified(LLClipboard::instance().isCutMode() + ? LLInventoryFilter::FILTER_MORE_RESTRICTIVE + : LLInventoryFilter::FILTER_LESS_RESTRICTIVE);*/ + } } panel->mFolderRoot->update(); -- cgit v1.2.3 From 291e78732374f428e43bb6bf5967ed3a114d0f18 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 3 Aug 2012 11:56:19 -0700 Subject: CHUI-265: Problem was that the each accordian tab was using the llinvetorypanel object to display contents. The llinventorypanel was designed by default to use a scrollbar horizontally/vertically, just like in the inventory floater. Resolution: Now set a flag to hide the scrollbar for each accordian tab. --- indra/newview/skins/default/xui/en/panel_landmarks.xml | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index 39805637a0..ebd4c6a805 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -35,6 +35,7 @@ left="0" mouse_opaque="true" name="favorites_list" + scroll.hide_scrollbar="true" start_folder.name="Favorites" width="307"/> </accordion_tab> @@ -51,6 +52,7 @@ left="0" mouse_opaque="true" name="landmarks_list" + scroll.hide_scrollbar="true" start_folder.name="Landmarks" width="307"/> </accordion_tab> @@ -67,6 +69,7 @@ left="0" mouse_opaque="true" name="my_inventory_list" + scroll.hide_scrollbar="true" start_folder.name="My Inventory" width="307"/> </accordion_tab> @@ -83,6 +86,7 @@ left="0" mouse_opaque="true" name="library_list" + scroll.hide_scrollbar="true" start_folder.name="LIBRARY" width="313"/> </accordion_tab> -- cgit v1.2.3 From d6d35d970f3a7b4db7e29f7d2eddb0c078cba4a5 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 3 Aug 2012 13:54:35 -0700 Subject: CHUI-263 : Fix crash on exit. LLSingleton like LLConversationLog cannot be an LLFriendObserver at the same time. --- indra/newview/llconversationlog.cpp | 38 +++++++++++++++++++++++++++---------- indra/newview/llconversationlog.h | 9 +++++---- 2 files changed, 33 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index df9350407d..137b97326c 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -139,6 +139,31 @@ void LLConversation::setListenIMFloaterOpened() mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1)); } } +/************************************************************************/ +/* LLConversationLogFriendObserver implementation */ +/************************************************************************/ + +// Note : An LLSingleton like LLConversationLog cannot be an LLFriendObserver +// at the same time. +// This is because avatar observers are deleted by the observed object which +// conflicts with the way LLSingleton are deleted. + +class LLConversationLogFriendObserver : public LLFriendObserver +{ +public: + LLConversationLogFriendObserver() {} + virtual ~LLConversationLogFriendObserver() {} + virtual void changed(U32 mask); +}; + +void LLConversationLogFriendObserver::changed(U32 mask) +{ + if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE)) + { + LLConversationLog::instance().notifyObservers(); + } +} + /************************************************************************/ /* LLConversationLog implementation */ /************************************************************************/ @@ -148,7 +173,9 @@ LLConversationLog::LLConversationLog() loadFromFile(getFileName()); LLIMMgr::instance().addSessionObserver(this); - LLAvatarTracker::instance().addObserver(this); + + mFriendObserver = new LLConversationLogFriendObserver; + LLAvatarTracker::instance().addObserver(mFriendObserver); } void LLConversationLog::logConversation(const LLConversation& conversation) { @@ -204,15 +231,6 @@ void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string } } -// LLFriendObserver -void LLConversationLog::changed(U32 mask) -{ - if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE)) - { - notifyObservers(); - } -} - void LLConversationLog::cache() { saveToFile(getFileName()); diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 18865bb80e..a7457d55e3 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -99,7 +99,7 @@ private: * To distinguish two conversations with the same sessionID it's also needed to compare their creation date. */ -class LLConversationLog : public LLSingleton<LLConversationLog>, LLIMSessionObserver, LLFriendObserver +class LLConversationLog : public LLSingleton<LLConversationLog>, LLIMSessionObserver { friend class LLSingleton<LLConversationLog>; public: @@ -126,8 +126,8 @@ public: virtual void sessionRemoved(const LLUUID& session_id){} // Stub virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){} // Stub - // LLFriendObserver trigger - virtual void changed(U32 mask); + // Triggered by LLFriendObserver change + void notifyObservers(); /** * public method which is called on viewer exit to save conversation log @@ -137,7 +137,6 @@ public: private: LLConversationLog(); - void notifyObservers(); /** * constructs file name in which conversations log will be saved @@ -152,6 +151,8 @@ private: typedef std::vector<LLConversation> conversations_vec_t; std::vector<LLConversation> mConversations; std::set<LLConversationLogObserver*> mObservers; + + LLFriendObserver* mFriendObserver; // Observer of the LLAvatarTracker instance }; class LLConversationLogObserver -- cgit v1.2.3 From af8d113557105075af0e010c560ba9846d812aa0 Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 3 Aug 2012 15:23:08 -0700 Subject: CHUI-271 FIX Items that are cut and then removed from the clipboard without paste do not show in Trash until relog --- indra/llui/llfolderviewitem.h | 96 ++++++++++++++++++-------------------- indra/llui/llfolderviewmodel.cpp | 15 ++++++ indra/llui/llfolderviewmodel.h | 6 +-- indra/newview/llinventorypanel.cpp | 34 +++++++------- 4 files changed, 80 insertions(+), 71 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index e75059bc01..6eacbe8bd0 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -46,9 +46,6 @@ class LLFolderViewModelInterface; class LLFolderViewItem : public LLView { public: - static void initClass(); - static void cleanupClass(); - struct Params : public LLInitParam::Block<Params, LLView::Params> { Optional<LLUIImage*> folder_arrow_image, @@ -67,20 +64,17 @@ public: }; // layout constants - static const S32 LEFT_PAD = 5; - // LEFT_INDENTATION is set via folder_indentation above - static const S32 ICON_PAD = 2; - static const S32 ICON_WIDTH = 16; - static const S32 TEXT_PAD = 1; - static const S32 TEXT_PAD_RIGHT = 4; - static const S32 ARROW_SIZE = 12; - static const S32 MAX_FOLDER_ITEM_OVERLAP = 2; + static const S32 LEFT_PAD = 5, + ICON_PAD = 2, + ICON_WIDTH = 16, + TEXT_PAD = 1, + TEXT_PAD_RIGHT = 4, + ARROW_SIZE = 12, + MAX_FOLDER_ITEM_OVERLAP = 2; + // animation parameters - static const F32 FOLDER_CLOSE_TIME_CONSTANT; - static const F32 FOLDER_OPEN_TIME_CONSTANT; - -private: - BOOL mIsSelected; + static const F32 FOLDER_CLOSE_TIME_CONSTANT, + FOLDER_OPEN_TIME_CONSTANT; protected: friend class LLUICtrlFactory; @@ -95,9 +89,9 @@ protected: LLFolderViewModelItem* mViewModelItem; LLFontGL::StyleFlags mLabelStyle; std::string mLabelSuffix; - LLUIImagePtr mIcon; - LLUIImagePtr mIconOpen; - LLUIImagePtr mIconOverlay; + LLUIImagePtr mIcon, + mIconOpen, + mIconOverlay; S32 mIndentation; S32 mItemHeight; S32 mDragStartX, @@ -105,12 +99,12 @@ protected: F32 mControlLabelRotation; LLFolderView* mRoot; - bool mHasVisibleChildren; - bool mIsCurSelection; - bool mDragAndDropTarget; - bool mIsMouseOverTitle; - bool mAllowOpen; - bool mSelectPending; + bool mHasVisibleChildren, + mIsCurSelection, + mDragAndDropTarget, + mIsMouseOverTitle, + mAllowOpen, + mSelectPending; // this is an internal method used for adding items to folders. A // no-op at this level, but reimplemented in derived classes. @@ -119,7 +113,13 @@ protected: static LLFontGL* getLabelFontForStyle(U8 style); +private: + BOOL mIsSelected; + public: + static void initClass(); + static void cleanupClass(); + BOOL postBuild(); virtual void openItem( void ); @@ -191,7 +191,6 @@ public: // contents possible before the entire view has been constructed. const std::string& getLabel() const { return mLabel; } - LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } @@ -209,8 +208,7 @@ public: // just rename the object. void rename(const std::string& new_name); - - // Show children (unfortunate that this is called "open") + // Show children virtual void setOpen(BOOL open = TRUE) {}; virtual BOOL isOpen() const { return FALSE; } @@ -238,10 +236,10 @@ public: // virtual void handleDropped(); virtual void draw(); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); private: static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts @@ -262,7 +260,6 @@ protected: friend class LLUICtrlFactory; public: - typedef std::list<LLFolderViewItem*> items_t; typedef std::list<LLFolderViewFolder*> folders_t; @@ -330,12 +327,6 @@ public: // destroys this folder, and all children virtual void destroyView(); - // If this folder can be removed, remove all children that can be - // removed, return TRUE if this is empty after the operation and - // it's viewed folder object can be removed. - //virtual BOOL removeRecursively(BOOL single_item); - //virtual BOOL remove(); - // extractItem() removes the specified item from the folder, but // doesn't delete it. virtual void extractItem( LLFolderViewItem* item ); @@ -366,16 +357,17 @@ public: // special case if an object is dropped on the child. BOOL handleDragAndDropFromChild(MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); - void applyFunctorRecursively(LLFolderViewFunctor& functor); // Just apply this functor to the folder's immediate children. void applyFunctorToChildren(LLFolderViewFunctor& functor); + // apply this functor to the folder's descendants. + void applyFunctorRecursively(LLFolderViewFunctor& functor); virtual void openItem( void ); @@ -384,12 +376,14 @@ public: virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - BOOL handleDragAndDropToThisFolder(MASK mask, BOOL drop, + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + BOOL handleDragAndDropToThisFolder(MASK mask, + BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp index 6aa4a63edc..3593804554 100644 --- a/indra/llui/llfolderviewmodel.cpp +++ b/indra/llui/llfolderviewmodel.cpp @@ -51,3 +51,18 @@ void LLFolderViewModelCommon::filter() getFilter().setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); mFolderView->getViewModelItem()->filter(getFilter()); } + +bool LLFolderViewModelItemCommon::hasFilterStringMatch() +{ + return mStringMatchOffsetFilter != std::string::npos; +} + +std::string::size_type LLFolderViewModelItemCommon::getFilterStringOffset() +{ + return mStringMatchOffsetFilter; +} + +std::string::size_type LLFolderViewModelItemCommon::getFilterStringSize() +{ + return mRootViewModel.getFilter().getFilterStringSize(); +} diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 9908e538a4..41660c6e1e 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -245,9 +245,9 @@ public: mParent->dirtyFilter(); } } - bool hasFilterStringMatch() { return mStringMatchOffsetFilter != std::string::npos; } - std::string::size_type getFilterStringOffset() { return mStringMatchOffsetFilter; } - std::string::size_type getFilterStringSize() { return mStringFilterSize; } + bool hasFilterStringMatch(); + std::string::size_type getFilterStringOffset(); + std::string::size_type getFilterStringSize(); virtual void addChild(LLFolderViewModelItem* child) { diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index d6a685541f..49bc3aae0b 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -600,6 +600,18 @@ void LLInventoryPanel::onIdle(void *userdata) } } +struct DirtyFilterFunctor : public LLFolderViewFunctor +{ + /*virtual*/ void doFolder(LLFolderViewFolder* folder) + { + folder->getViewModelItem()->dirtyFilter(); + } + /*virtual*/ void doItem(LLFolderViewItem* item) + { + item->getViewModelItem()->dirtyFilter(); + } +}; + void LLInventoryPanel::idle(void* user_data) { LLInventoryPanel* panel = (LLInventoryPanel*)user_data; @@ -607,25 +619,13 @@ void LLInventoryPanel::idle(void* user_data) if (panel->mClipboardState != LLClipboard::instance().getGeneration()) { panel->mClipboardState = LLClipboard::instance().getGeneration(); - if (LLClipboard::instance().isCutMode()) + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + LLFolderViewFolder* trash_folder = panel->getFolderByID(trash_id); + if (trash_folder) { - LLDynamicArray<LLUUID> objects; - LLClipboard::instance().pasteFromClipboard(objects); - - for (LLDynamicArray<LLUUID>::iterator it = objects.begin(), end_it = objects.end(); - it != end_it; - ++it) - { - LLFolderViewItem* item = panel->getItemByID(*it); - if (item) - { - item->getViewModelItem()->dirtyFilter(); - } - } - /*panel->getFilter().setModified(LLClipboard::instance().isCutMode() - ? LLInventoryFilter::FILTER_MORE_RESTRICTIVE - : LLInventoryFilter::FILTER_LESS_RESTRICTIVE);*/ + trash_folder->applyFunctorToChildren(DirtyFilterFunctor()); } + } panel->mFolderRoot->update(); -- cgit v1.2.3 From a831cb5bee19357e4d71a7408492fcb58a9042ac Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 3 Aug 2012 15:56:12 -0700 Subject: CHUI-273 FIX Inventory filtering changes not showing when changes are selected --- indra/newview/llinventorypanel.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 49bc3aae0b..b217612ee7 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -340,6 +340,7 @@ void LLInventoryPanel::setSortOrder(U32 order) if (order != getFolderViewModel()->getSorter().getSortOrder()) { getFolderViewModel()->setSorter(sorter); + mFolderRoot->arrangeAll(); // try to keep selection onscreen, even if it wasn't to start with mFolderRoot->scrollToShowSelection(); } -- cgit v1.2.3 From 118e3b33bd417331397f89770d46b1b3eeeffc8e Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Fri, 3 Aug 2012 17:43:48 -0700 Subject: CHUI-270 FIX Progress spinner not visible in merchant outbox --- indra/llcommon/llinitparam.cpp | 7 ++----- indra/llcommon/llinitparam.h | 10 +++++++--- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp index 451b638a3f..89c831d296 100644 --- a/indra/llcommon/llinitparam.cpp +++ b/indra/llcommon/llinitparam.cpp @@ -335,15 +335,12 @@ namespace LLInitParam { const std::string& top_name = name_stack_range.first->first; - ParamDescriptor::deserialize_func_t deserialize_func = NULL; - Param* paramp = NULL; - BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name); if (found_it != block_data.mNamedParams.end()) { // find pointer to member parameter from offset table - paramp = getParamFromHandle(found_it->second->mParamHandle); - deserialize_func = found_it->second->mDeserializeFunc; + Param* paramp = getParamFromHandle(found_it->second->mParamHandle); + ParamDescriptor::deserialize_func_t deserialize_func = found_it->second->mDeserializeFunc; Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second); ++new_name_stack.first; diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index 2f767c234e..14ba8e0b43 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -2194,7 +2194,7 @@ namespace LLInitParam resetToDefault(); } return mValue.deserializeBlock(p, name_stack_range, new_name); - } + } void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const { @@ -2211,12 +2211,16 @@ namespace LLInitParam bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) { - if (overwrite) + if ((overwrite && source_provided) // new values coming in on top or... + || (!overwrite && !dst_provided)) // values being pushed under with nothing already there { + // clear away what is there and take the new stuff as a whole resetToDefault(); return mValue.mergeBlock(block_data, source.getValue(), overwrite); } - return false; + + + return mValue.mergeBlock(block_data, source.getValue(), overwrite); } bool validateBlock(bool emit_errors = true) const -- cgit v1.2.3 From 3b525b788da802c8847bb2b5881c45519109ac11 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 3 Aug 2012 18:02:28 +0300 Subject: CHUI-241 (Add drag handle in UI to resize width of conversations list): implemented drag handle via predefined params of layout panels --- .../skins/default/xui/en/floater_im_container.xml | 12 ++++--- .../skins/default/xui/en/floater_im_session.xml | 39 +++++++++++----------- 2 files changed, 28 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e8ef3c1df9..ea6fd65b95 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -31,10 +31,12 @@ width="680"> <layout_panel auto_resize="true" + user_resize="true" height="430" name="conversations_layout_panel" min_dim="51" - width="268"> + width="268" + min_width="120"> <layout_stack animate="false" follows="left|top|right" @@ -107,17 +109,19 @@ </layout_panel> <layout_panel auto_resize="true" + user_resize="true" height="430" name="messages_layout_panel" - width="412"> + width="412" + min_width="205"> <panel_container follows="all" height="430" layout="topleft" - left="10" + left="0" name="im_box_tab_container" top="0" - width="402"/> + width="412"/> </layout_panel> </layout_stack> </multi_floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 675967035f..4abe4d6941 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -213,8 +213,8 @@ </layout_panel> <layout_panel height="248" - width="234" - layout="topleft" + width="230" + layout="topleft" follows="all" left_delta="0" top_delta="0" @@ -231,28 +231,29 @@ name="chat_history" parse_highlights="true" parse_urls="true" - left="1" - width="229"> + width="230" + left="0"> </chat_history> </layout_panel> </layout_stack> </panel> <chat_editor - bottom="0" - expand_lines_count="5" - follows="left|right|bottom" - font="SansSerifSmall" - visible="true" - height="20" - is_expandable="true" - label="To" - layout="bottomleft" - name="chat_editor" - max_length="1023" - spellcheck="true" - tab_group="3" - width="240" - wrap="true"> + bottom="0" + expand_lines_count="5" + follows="left|right|bottom" + font="SansSerifSmall" + visible="true" + height="20" + is_expandable="true" + label="To" + layout="bottomleft" + name="chat_editor" + max_length="1023" + spellcheck="true" + tab_group="3" + width="220" + left="10" + wrap="true"> </chat_editor> </layout_panel> </layout_stack> -- cgit v1.2.3 From aa011b98e39d9669c0bb06a25c18b092122d9252 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 6 Aug 2012 11:59:54 -0700 Subject: CHUI-276: Problem was that the flag to use ellipses was not turned on for the folderview's inside the Places folder. Resolution was to turn on the flag inside the panel_landmarks.xml file for each folder displayed (favorites bar, my landmarks and etc.) --- indra/newview/skins/default/xui/en/panel_landmarks.xml | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index ebd4c6a805..67a09949ce 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -36,6 +36,7 @@ mouse_opaque="true" name="favorites_list" scroll.hide_scrollbar="true" + folder_view.use_ellipses="true" start_folder.name="Favorites" width="307"/> </accordion_tab> @@ -53,6 +54,7 @@ mouse_opaque="true" name="landmarks_list" scroll.hide_scrollbar="true" + folder_view.use_ellipses="true" start_folder.name="Landmarks" width="307"/> </accordion_tab> @@ -70,6 +72,7 @@ mouse_opaque="true" name="my_inventory_list" scroll.hide_scrollbar="true" + folder_view.use_ellipses="true" start_folder.name="My Inventory" width="307"/> </accordion_tab> @@ -87,6 +90,7 @@ mouse_opaque="true" name="library_list" scroll.hide_scrollbar="true" + folder_view.use_ellipses="true" start_folder.name="LIBRARY" width="313"/> </accordion_tab> -- cgit v1.2.3 From 02bdceb5808b670fdb16784f11488c12c09e1b4b Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 6 Aug 2012 14:08:14 -0700 Subject: Linux compiliation fix, needed to create DirtyFilterFunctor outside of function parameter so that it can be legally passed as a reference. --- indra/newview/llinventorypanel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index b217612ee7..7fba52d47f 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -624,7 +624,8 @@ void LLInventoryPanel::idle(void* user_data) LLFolderViewFolder* trash_folder = panel->getFolderByID(trash_id); if (trash_folder) { - trash_folder->applyFunctorToChildren(DirtyFilterFunctor()); + DirtyFilterFunctor dirtyFilterFunctor; + trash_folder->applyFunctorToChildren(dirtyFilterFunctor); } } -- cgit v1.2.3 From 25855962a86331a337c4baff2754c63850605aea Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 6 Aug 2012 18:07:56 -0700 Subject: CHUI-98 : Isolate LLConversationItem and LLConversationViewModel in their own file --- indra/newview/CMakeLists.txt | 2 + indra/newview/llconversationmodel.cpp | 106 +++++++++++++++++ indra/newview/llconversationmodel.h | 202 +++++++++++++++++++++++++++++++++ indra/newview/llimfloatercontainer.cpp | 73 ------------ indra/newview/llimfloatercontainer.h | 164 +------------------------- 5 files changed, 311 insertions(+), 236 deletions(-) create mode 100644 indra/newview/llconversationmodel.cpp create mode 100644 indra/newview/llconversationmodel.h (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 626fb8caa5..08325daaab 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -134,6 +134,7 @@ set(viewer_SOURCE_FILES llconversationlog.cpp llconversationloglist.cpp llconversationloglistitem.cpp + llconversationmodel.cpp llcurrencyuimanager.cpp llcylinder.cpp lldateutil.cpp @@ -699,6 +700,7 @@ set(viewer_HEADER_FILES llconversationlog.h llconversationloglist.h llconversationloglistitem.h + llconversationmodel.h llcurrencyuimanager.h llcylinder.h lldateutil.h diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp new file mode 100644 index 0000000000..bd314588a0 --- /dev/null +++ b/indra/newview/llconversationmodel.cpp @@ -0,0 +1,106 @@ +/** + * @file llconversationmodel.cpp + * @brief Implementation of conversations list + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" + +#include "llconversationmodel.h" +#include "llimfloatercontainer.h" + +// Conversation items +LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp) : + LLFolderViewModelItemCommon(containerp->getRootViewModel()), + mName(name), + mUUID(uuid), + mFloater(floaterp), + mContainer(containerp) +{ +} + +LLConversationItem::LLConversationItem(LLIMFloaterContainer* containerp) : + LLFolderViewModelItemCommon(containerp->getRootViewModel()), + mName(""), + mUUID(), + mFloater(NULL), + mContainer(NULL) +{ +} + + +// Virtual action callbacks +void LLConversationItem::selectItem(void) +{ + LLMultiFloater* host_floater = mFloater->getHost(); + if (host_floater == mContainer) + { + // Always expand the message pane if the panel is hosted by the container + mContainer->collapseMessagesPane(false); + // Switch to the conversation floater that is being selected + mContainer->selectFloater(mFloater); + } + // Set the focus on the selected floater + mFloater->setFocus(TRUE); +} + +void LLConversationItem::setVisibleIfDetached(BOOL visible) +{ + // Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized + // Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here + if (!mFloater->getHost() && !mFloater->isMinimized()) + { + mFloater->setVisible(visible); + } +} + +void LLConversationItem::performAction(LLInventoryModel* model, std::string action) +{ +} + +void LLConversationItem::openItem( void ) +{ +} + +void LLConversationItem::closeItem( void ) +{ +} + +void LLConversationItem::previewItem( void ) +{ +} + +void LLConversationItem::showProperties(void) +{ +} + +bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const +{ + // We compare only by name for the moment + // *TODO : Implement the sorting by date + S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); + return (compare < 0); +} + +// EOF diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h new file mode 100644 index 0000000000..85760eb1a8 --- /dev/null +++ b/indra/newview/llconversationmodel.h @@ -0,0 +1,202 @@ +/** + * @file llconversationmodel.h + * @brief Implementation of conversations list + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLCONVERSATIONMODEL_H +#define LL_LLCONVERSATIONMODEL_H + +//#include <map> +//#include <vector> + +#include "llfolderviewitem.h" +#include "llfolderviewmodel.h" + +class LLButton; +class LLFloater; +class LLLayoutPanel; +class LLLayoutStack; +class LLTabContainer; +class LLIMFloaterContainer; + +// Implementation of conversations list + +class LLConversationItem; + +typedef std::map<LLFloater*, LLConversationItem*> conversations_items_map; +typedef std::map<LLFloater*, LLFolderViewItem*> conversations_widgets_map; + +// Conversation items: we hold a list of those and create an LLFolderViewItem widget for each +// that we tuck into the mConversationsListPanel. +class LLConversationItem : public LLFolderViewModelItemCommon +{ +public: + LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp); + LLConversationItem(LLIMFloaterContainer* containerp); + virtual ~LLConversationItem() {} + + // Stub those things we won't really be using in this conversation context + virtual const std::string& getName() const { return mName; } + virtual const std::string& getDisplayName() const { return mName; } + virtual const std::string& getSearchableName() const { return mName; } + virtual const LLUUID& getUUID() const { return mUUID; } + virtual time_t getCreationDate() const { return 0; } + virtual LLPointer<LLUIImage> getIcon() const { return NULL; } + virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } + virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } + virtual std::string getLabelSuffix() const { return LLStringUtil::null; } + virtual BOOL isItemRenameable() const { return FALSE; } + virtual BOOL renameItem(const std::string& new_name) { return FALSE; } + virtual BOOL isItemMovable( void ) const { return FALSE; } + virtual BOOL isItemRemovable( void ) const { return FALSE; } + virtual BOOL isItemInTrash( void) const { return FALSE; } + virtual BOOL removeItem() { return FALSE; } + virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) { } + virtual void move( LLFolderViewModelItem* parent_listener ) { } + virtual BOOL isItemCopyable() const { return FALSE; } + virtual BOOL copyToClipboard() const { return FALSE; } + virtual BOOL cutToClipboard() const { return FALSE; } + virtual BOOL isClipboardPasteable() const { return FALSE; } + virtual void pasteFromClipboard() { } + virtual void pasteLinkFromClipboard() { } + virtual void buildContextMenu(LLMenuGL& menu, U32 flags) { } + virtual BOOL isUpToDate() const { return TRUE; } + virtual bool hasChildren() const { return FALSE; } + + virtual bool potentiallyVisible() { return true; } + virtual bool filter( LLFolderViewFilter& filter) { return false; } + virtual bool descendantsPassedFilter(S32 filter_generation = -1) { return true; } + virtual void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) { } + virtual bool passedFilter(S32 filter_generation = -1) { return true; } + + // The action callbacks + virtual void performAction(LLInventoryModel* model, std::string action); + virtual void openItem( void ); + virtual void closeItem( void ); + virtual void previewItem( void ); + virtual void selectItem(void); + virtual void showProperties(void); + + void setVisibleIfDetached(BOOL visible); + + // This method will be called to determine if a drop can be + // performed, and will set drop to TRUE if a drop is + // requested. + // Returns TRUE if a drop is possible/happened, FALSE otherwise. + virtual BOOL dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + std::string& tooltip_msg) { return FALSE; } + + bool hasSameValues(std::string name, const LLUUID& uuid) { return ((name == mName) && (uuid == mUUID)); } + bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } +private: + std::string mName; + const LLUUID mUUID; + LLFloater* mFloater; + LLIMFloaterContainer* mContainer; +}; + +// We don't want to ever filter conversations but we need to declare that class to create a conversation view model. +// We just stubb everything for the moment. +class LLConversationFilter : public LLFolderViewFilter +{ +public: + + enum ESortOrderType + { + SO_NAME = 0, // Sort inventory by name + SO_DATE = 0x1, // Sort inventory by date + }; + + LLConversationFilter() { mEmpty = ""; } + ~LLConversationFilter() {} + + bool check(const LLFolderViewModelItem* item) { return true; } + bool checkFolder(const LLFolderViewModelItem* folder) const { return true; } + void setEmptyLookupMessage(const std::string& message) { } + std::string getEmptyLookupMessage() const { return mEmpty; } + bool showAllResults() const { return true; } + std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const { return std::string::npos; } + std::string::size_type getFilterStringSize() const { return 0; } + + bool isActive() const { return false; } + bool isModified() const { return false; } + void clearModified() { } + const std::string& getName() const { return mEmpty; } + const std::string& getFilterText() { return mEmpty; } + void setModified(EFilterModified behavior = FILTER_RESTART) { } + + void setFilterCount(S32 count) { } + S32 getFilterCount() const { return 0; } + void decrementFilterCount() { } + + bool isDefault() const { return true; } + bool isNotDefault() const { return false; } + void markDefault() { } + void resetDefault() { } + + S32 getCurrentGeneration() const { return 0; } + S32 getFirstSuccessGeneration() const { return 0; } + S32 getFirstRequiredGeneration() const { return 0; } +private: + std::string mEmpty; +}; + +class LLConversationSort +{ +public: + LLConversationSort(U32 order = 0) + : mSortOrder(order), + mByDate(false), + mByName(false) + { + mByDate = (order & LLConversationFilter::SO_DATE); + mByName = (order & LLConversationFilter::SO_NAME); + } + + bool isByDate() const { return mByDate; } + U32 getSortOrder() const { return mSortOrder; } + + bool operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const; +private: + U32 mSortOrder; + bool mByDate; + bool mByName; +}; + +class LLConversationViewModel +: public LLFolderViewModel<LLConversationSort, LLConversationItem, LLConversationItem, LLConversationFilter> +{ +public: + typedef LLFolderViewModel<LLConversationSort, LLConversationItem, LLConversationItem, LLConversationFilter> base_t; + + void sort(LLFolderViewFolder* folder) { } // *TODO : implement conversation sort + bool contentsReady() { return true; } // *TODO : we need to check that participants names are available somewhat + bool startDrag(std::vector<LLFolderViewModelItem*>& items) { return false; } // We do not allow drag of conversation items + +private: +}; + +#endif // LL_LLCONVERSATIONMODEL_H diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index d618e7491a..c2c0ddddea 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -536,77 +536,4 @@ LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversat return LLUICtrlFactory::create<LLFolderViewItem>(params); } -// Conversation items -LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp) : - LLFolderViewModelItemCommon(containerp->getRootViewModel()), - mName(name), - mUUID(uuid), - mFloater(floaterp), - mContainer(containerp) -{ -} - -LLConversationItem::LLConversationItem(LLIMFloaterContainer* containerp) : - LLFolderViewModelItemCommon(containerp->getRootViewModel()), - mName(""), - mUUID(), - mFloater(NULL), - mContainer(NULL) -{ -} - - -// Virtual action callbacks -void LLConversationItem::selectItem(void) -{ - LLMultiFloater* host_floater = mFloater->getHost(); - if (host_floater == mContainer) - { - // Always expand the message pane if the panel is hosted by the container - mContainer->collapseMessagesPane(false); - // Switch to the conversation floater that is being selected - mContainer->selectFloater(mFloater); - } - // Set the focus on the selected floater - mFloater->setFocus(TRUE); -} - -void LLConversationItem::setVisibleIfDetached(BOOL visible) -{ - // Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized - // Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here - if (!mFloater->getHost() && !mFloater->isMinimized()) - { - mFloater->setVisible(visible); - } -} - -void LLConversationItem::performAction(LLInventoryModel* model, std::string action) -{ -} - -void LLConversationItem::openItem( void ) -{ -} - -void LLConversationItem::closeItem( void ) -{ -} - -void LLConversationItem::previewItem( void ) -{ -} - -void LLConversationItem::showProperties(void) -{ -} - -bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const -{ - // We compare only by name for the moment - // *TODO : Implement the sorting by date - S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); - return (compare < 0); -} - // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 5154b02dd6..161c6d9806 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -35,9 +35,7 @@ #include "llmultifloater.h" #include "llavatarpropertiesprocessor.h" #include "llgroupmgr.h" - -#include "llfolderviewitem.h" -#include "llfolderviewmodel.h" +#include "llconversationmodel.h" class LLButton; class LLLayoutPanel; @@ -45,166 +43,6 @@ class LLLayoutStack; class LLTabContainer; class LLIMFloaterContainer; -// CHUI-137 : Temporary implementation of conversations list -class LLConversationItem; - -typedef std::map<LLFloater*, LLConversationItem*> conversations_items_map; -typedef std::map<LLFloater*, LLFolderViewItem*> conversations_widgets_map; - -// Conversation items: we hold a list of those and create an LLFolderViewItem widget for each -// that we tuck into the mConversationsListPanel. -class LLConversationItem : public LLFolderViewModelItemCommon -{ -public: - LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp); - LLConversationItem(LLIMFloaterContainer* containerp); - virtual ~LLConversationItem() {} - - // Stub those things we won't really be using in this conversation context - virtual const std::string& getName() const { return mName; } - virtual const std::string& getDisplayName() const { return mName; } - virtual const std::string& getSearchableName() const { return mName; } - virtual const LLUUID& getUUID() const { return mUUID; } - virtual time_t getCreationDate() const { return 0; } - virtual LLPointer<LLUIImage> getIcon() const { return NULL; } - virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } - virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } - virtual std::string getLabelSuffix() const { return LLStringUtil::null; } - virtual BOOL isItemRenameable() const { return FALSE; } - virtual BOOL renameItem(const std::string& new_name) { return FALSE; } - virtual BOOL isItemMovable( void ) const { return FALSE; } - virtual BOOL isItemRemovable( void ) const { return FALSE; } - virtual BOOL isItemInTrash( void) const { return FALSE; } - virtual BOOL removeItem() { return FALSE; } - virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) { } - virtual void move( LLFolderViewModelItem* parent_listener ) { } - virtual BOOL isItemCopyable() const { return FALSE; } - virtual BOOL copyToClipboard() const { return FALSE; } - virtual BOOL cutToClipboard() const { return FALSE; } - virtual BOOL isClipboardPasteable() const { return FALSE; } - virtual void pasteFromClipboard() { } - virtual void pasteLinkFromClipboard() { } - virtual void buildContextMenu(LLMenuGL& menu, U32 flags) { } - virtual BOOL isUpToDate() const { return TRUE; } - virtual bool hasChildren() const { return FALSE; } - - virtual bool potentiallyVisible() { return true; } - virtual bool filter( LLFolderViewFilter& filter) { return false; } - virtual bool descendantsPassedFilter(S32 filter_generation = -1) { return true; } - virtual void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) { } - virtual bool passedFilter(S32 filter_generation = -1) { return true; } - - // The action callbacks - virtual void performAction(LLInventoryModel* model, std::string action); - virtual void openItem( void ); - virtual void closeItem( void ); - virtual void previewItem( void ); - virtual void selectItem(void); - virtual void showProperties(void); - - void setVisibleIfDetached(BOOL visible); - - // This method will be called to determine if a drop can be - // performed, and will set drop to TRUE if a drop is - // requested. - // Returns TRUE if a drop is possible/happened, FALSE otherwise. - virtual BOOL dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - std::string& tooltip_msg) { return FALSE; } - - bool hasSameValues(std::string name, const LLUUID& uuid) { return ((name == mName) && (uuid == mUUID)); } - bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } -private: - std::string mName; - const LLUUID mUUID; - LLFloater* mFloater; - LLIMFloaterContainer* mContainer; -}; - -// We don't want to ever filter conversations but we need to declare that class to create a conversation view model. -// We just stubb everything for the moment. -class LLConversationFilter : public LLFolderViewFilter -{ -public: - - enum ESortOrderType - { - SO_NAME = 0, // Sort inventory by name - SO_DATE = 0x1, // Sort inventory by date - }; - - LLConversationFilter() { mEmpty = ""; } - ~LLConversationFilter() {} - - bool check(const LLFolderViewModelItem* item) { return true; } - bool checkFolder(const LLFolderViewModelItem* folder) const { return true; } - void setEmptyLookupMessage(const std::string& message) { } - std::string getEmptyLookupMessage() const { return mEmpty; } - bool showAllResults() const { return true; } - std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const { return std::string::npos; } - std::string::size_type getFilterStringSize() const { return 0; } - - bool isActive() const { return false; } - bool isModified() const { return false; } - void clearModified() { } - const std::string& getName() const { return mEmpty; } - const std::string& getFilterText() { return mEmpty; } - void setModified(EFilterModified behavior = FILTER_RESTART) { } - - void setFilterCount(S32 count) { } - S32 getFilterCount() const { return 0; } - void decrementFilterCount() { } - - bool isDefault() const { return true; } - bool isNotDefault() const { return false; } - void markDefault() { } - void resetDefault() { } - - S32 getCurrentGeneration() const { return 0; } - S32 getFirstSuccessGeneration() const { return 0; } - S32 getFirstRequiredGeneration() const { return 0; } -private: - std::string mEmpty; -}; - -class LLConversationSort -{ -public: - LLConversationSort(U32 order = 0) - : mSortOrder(order), - mByDate(false), - mByName(false) - { - mByDate = (order & LLConversationFilter::SO_DATE); - mByName = (order & LLConversationFilter::SO_NAME); - } - - bool isByDate() const { return mByDate; } - U32 getSortOrder() const { return mSortOrder; } - - bool operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const; -private: - U32 mSortOrder; - bool mByDate; - bool mByName; -}; - -class LLConversationViewModel -: public LLFolderViewModel<LLConversationSort, LLConversationItem, LLConversationItem, LLConversationFilter> -{ -public: - typedef LLFolderViewModel<LLConversationSort, LLConversationItem, LLConversationItem, LLConversationFilter> base_t; - - void sort(LLFolderViewFolder* folder) { } // *TODO : implement conversation sort - bool contentsReady() { return true; } // *TODO : we need to check that participants names are available somewhat - bool startDrag(std::vector<LLFolderViewModelItem*>& items) { return false; } // We do not allow drag of conversation items - -private: -}; - -// CHUI-137 : End - class LLIMFloaterContainer : public LLMultiFloater , public LLIMSessionObserver -- cgit v1.2.3 From 324200dfd7d70324fe15329100140d98bb1f9b17 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Thu, 9 Aug 2012 00:00:25 +0300 Subject: CHUI-120 WIP Added notifications about newly invited chat participants. --- indra/newview/llimfloater.cpp | 124 ++++++++++++++++----- indra/newview/llimfloater.h | 3 +- .../skins/default/xui/en/floater_im_session.xml | 6 + .../newview/skins/default/xui/en/notifications.xml | 14 +++ 4 files changed, 120 insertions(+), 27 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 3399a88c9e..a2989375ea 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -352,19 +352,19 @@ BOOL LLIMFloater::postBuild() } void LLIMFloater::onAddButtonClicked() +{ + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::onAddSessionParticipants, this, _1), TRUE, TRUE); + if (!picker) { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE); - if (!picker) - { - return; + return; } - // Need to disable 'ok' button when selected users are already in conversation. - picker->setOkBtnEnableCb(boost::bind(&LLIMFloater::canAddSelectedToChat, this, _1)); - LLFloater* root_floater = gFloaterView->getParentFloater(this); - if (root_floater) + // Need to disable 'ok' button when selected users are already in conversation. + picker->setOkBtnEnableCb(boost::bind(&LLIMFloater::canAddSelectedToChat, this, _1)); + LLFloater* root_floater = gFloaterView->getParentFloater(this); + if (root_floater) { - root_floater->addDependentFloater(picker); + root_floater->addDependentFloater(picker); } } @@ -420,8 +420,54 @@ bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) return true; } -void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) +void LLIMFloater::onAddSessionParticipants(const uuid_vec_t& uuids) +{ + LLSD payload; + LLSD args; + for (uuid_vec_t::const_iterator iter = uuids.begin(); iter != uuids.end(); ++iter) + { + payload["participant_ids"].append(*iter); + } + + LLNotificationsUtil::add("ConfirmAddingChatParticipants", args, payload, + boost::bind(&LLIMFloater::addSessionParticipants, this, _1, _2)); +} + +void LLIMFloater::addSessionParticipants(const LLSD& notification, const LLSD& response) +{ + uuid_vec_t uuids; + LLSD::array_const_iterator list_it = notification["payload"]["participant_ids"].beginArray(); + LLSD::array_const_iterator list_end = notification["payload"]["participant_ids"].endArray(); + for (; list_it != list_end; ++list_it) + { + uuids.push_back(list_it->asUUID()); + } + + std::vector<LLAvatarName> avatar_names; + uuid_vec_t::const_iterator it = uuids.begin(); + for (; it != uuids.end(); ++it) { + const LLUUID& id = *it; + LLAvatarName av_name; + if (LLAvatarNameCache::get(id, &av_name)) + { + avatar_names.push_back(av_name); + } + } + + std::string added_participants; + + // We should check whether the vector is not empty to pass the assertion + // that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. + if (!avatar_names.empty()) + { + LLAvatarActions::buildResidentsString(avatar_names, added_participants); + } + + LLStringUtil::format_map_t args; + args["[NAMES]"] = added_participants; + std::string participants_added_notification; + if (mIsP2PChat) { mStartConferenceInSameFloater = true; @@ -440,19 +486,45 @@ void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) // then we can close the current session onClose(false); + participants_added_notification = getString("participants_added_new_window", args); + participants_added_notification = utf8str_truncate(participants_added_notification, MAX_MSG_BUF_SIZE - 1); + + if (mSessionInitialized) + { + LLIMModel::sendMessage(participants_added_notification, mSessionID, mOtherParticipantUUID, mDialog); + } + else + { + //queue up the message to send once the session is initialized + mQueuedMsgsForInit.append(participants_added_notification); + } + // Start a new ad hoc voice call if we invite new participants to a P2P call, // or start a text chat otherwise. if (is_voice_call) { LLAvatarActions::startAdhocCall(temp_ids, mSessionID); - } - else - { + } + else + { LLAvatarActions::startConference(temp_ids, mSessionID); + } } -} else { + participants_added_notification = getString("participants_added", args); + participants_added_notification = utf8str_truncate(participants_added_notification, MAX_MSG_BUF_SIZE - 1); + + if (mSessionInitialized) + { + LLIMModel::sendMessage(participants_added_notification, mSessionID, mOtherParticipantUUID, mDialog); + } + else + { + //queue up the message to send once the session is initialized + mQueuedMsgsForInit.append(participants_added_notification); + } + inviteToSession(uuids); } } @@ -1115,19 +1187,19 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, if (cargo_type == DAD_PERSON) { if (dropPerson(static_cast<LLUUID*>(cargo_data), drop)) - { + { *accept = ACCEPT_YES_MULTI; - } + } else - { - *accept = ACCEPT_NO; - } + { + *accept = ACCEPT_NO; } + } else if (mDialog == IM_NOTHING_SPECIAL) - { + { LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, cargo_type, cargo_data, accept); - } + } return TRUE; } @@ -1137,18 +1209,18 @@ bool LLIMFloater::dropPerson(LLUUID* person_id, bool drop) bool res = person_id && person_id->notNull(); if(res) { - uuid_vec_t ids; + uuid_vec_t ids; ids.push_back(*person_id); res = canAddSelectedToChat(ids); if(res && drop) - { - addSessionParticipants(ids); + { + onAddSessionParticipants(ids); + } } -} return res; - } +} BOOL LLIMFloater::isInviteAllowed() const { diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 434613ff43..d98213b54c 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -160,7 +160,8 @@ private: static void onInputEditorKeystroke(LLTextEditor* caller, void* userdata); void setTyping(bool typing); void onAddButtonClicked(); - void addSessionParticipants(const uuid_vec_t& uuids); + void onAddSessionParticipants(const uuid_vec_t& uuids); + void addSessionParticipants(const LLSD& notification, const LLSD& response); bool canAddSelectedToChat(const uuid_vec_t& uuids); void onCallButtonClicked(); diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 4abe4d6941..2b63430106 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -34,6 +34,12 @@ <floater.string name="return_icon" value="Conv_toolbar_arrow_sw"/> + <floater.string + name="participants_added" + value="New participant(s) were invited to the conversation: [NAMES]."/> + <floater.string + name="participants_added_new_window" + value="New participant(s) were invited to the conversation: [NAMES]. The conversation will be started in a new window."/> <view follows="all" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index e85637826d..2ffa2cfb22 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4946,6 +4946,20 @@ Go to your [http://secondlife.com/account/ Dashboard] to see your account histor yestext="Go to page"/> </notification> + <notification + icon="alertmodal.tga" + name="ConfirmAddingChatParticipants" + type="alertmodal"> + <unique/> +When you add a person to an existing conversation, a new conversation will be created. All participants will receive new conversation notifications. + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm adding chat paticipants" + name="okcancelignore" + notext="Cancel" + yestext="Ok"/> + </notification> + <notification icon="alertmodal.tga" name="ConfirmQuit" -- cgit v1.2.3 From 2b026a806617532a0b2c8a796e9530273c110cf4 Mon Sep 17 00:00:00 2001 From: Todd Stinson <stinson@lindenlab.com> Date: Wed, 8 Aug 2012 18:17:01 -0700 Subject: CHUI-272: BUGFIX Correcting the inventory filtering so that a large number of items in the inventory are completely processed before the filter's modified flag is cleared. --- indra/llui/llfolderview.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index fedb8bc014..1a8ab63388 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1715,11 +1715,17 @@ void LLFolderView::update() { mNeedsAutoSelect = TRUE; } - getFolderViewModel()->getFilter().clearModified(); // filter to determine visibility before arranging filter(getFolderViewModel()->getFilter()); + // Clear the modified setting on the filter only if the filter count is non-zero after running the filter process + // Note: if the filter count is zero, then the filter most likely halted before completing the entire set of items + if (getFolderViewModel()->getFilter().isModified() && (getFolderViewModel()->getFilter().getFilterCount() > 0)) + { + getFolderViewModel()->getFilter().clearModified(); + } + // automatically show matching items, and select first one if we had a selection if (mNeedsAutoSelect) { -- cgit v1.2.3 From 6cf49a4a715c9f498d4b063f8d74e295be1f418c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 9 Aug 2012 16:48:33 +0300 Subject: CHUI-171 WIP (Conversation not automatically readded to conversation window listing when open) - removal of the dependence between items of the conversations list and conversation's floaters. --- indra/newview/llconversationmodel.cpp | 22 +++++--- indra/newview/llconversationmodel.h | 9 ++- indra/newview/llimconversation.cpp | 15 ++++- indra/newview/llimconversation.h | 3 + indra/newview/llimfloater.cpp | 28 ++++------ indra/newview/llimfloatercontainer.cpp | 64 ++++++++++------------ indra/newview/llimfloatercontainer.h | 12 ++-- indra/newview/llnearbychat.cpp | 9 +-- indra/newview/llsyswellwindow.h | 2 + .../skins/default/xui/en/floater_im_session.xml | 3 - indra/newview/skins/default/xui/en/strings.xml | 3 +- 11 files changed, 88 insertions(+), 82 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index bd314588a0..0c23e2654e 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -28,14 +28,14 @@ #include "llviewerprecompiledheaders.h" #include "llconversationmodel.h" +#include "llimconversation.h" #include "llimfloatercontainer.h" // Conversation items -LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp) : +LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& uuid, LLIMFloaterContainer* containerp) : LLFolderViewModelItemCommon(containerp->getRootViewModel()), - mName(name), + mName(display_name), mUUID(uuid), - mFloater(floaterp), mContainer(containerp) { } @@ -44,7 +44,6 @@ LLConversationItem::LLConversationItem(LLIMFloaterContainer* containerp) : LLFolderViewModelItemCommon(containerp->getRootViewModel()), mName(""), mUUID(), - mFloater(NULL), mContainer(NULL) { } @@ -53,25 +52,30 @@ LLConversationItem::LLConversationItem(LLIMFloaterContainer* containerp) : // Virtual action callbacks void LLConversationItem::selectItem(void) { - LLMultiFloater* host_floater = mFloater->getHost(); + LLFloater* session_floater = LLIMConversation::getConversation(mUUID); + LLMultiFloater* host_floater = session_floater->getHost(); + +// LLIMFloater::show(mUUID); if (host_floater == mContainer) { // Always expand the message pane if the panel is hosted by the container mContainer->collapseMessagesPane(false); // Switch to the conversation floater that is being selected - mContainer->selectFloater(mFloater); + mContainer->selectFloater(session_floater); } // Set the focus on the selected floater - mFloater->setFocus(TRUE); + session_floater->setFocus(TRUE); } void LLConversationItem::setVisibleIfDetached(BOOL visible) { // Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized // Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here - if (!mFloater->getHost() && !mFloater->isMinimized()) + LLFloater* session_floater = LLIMConversation::getConversation(mUUID); + + if (session_floater && !session_floater->getHost() && !session_floater->isMinimized()) { - mFloater->setVisible(visible); + session_floater->setVisible(visible); } } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 85760eb1a8..56a5b73c15 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -44,15 +44,15 @@ class LLIMFloaterContainer; class LLConversationItem; -typedef std::map<LLFloater*, LLConversationItem*> conversations_items_map; -typedef std::map<LLFloater*, LLFolderViewItem*> conversations_widgets_map; +typedef std::map<LLUUID, LLConversationItem*> conversations_items_map; +typedef std::map<LLUUID, LLFolderViewItem*> conversations_widgets_map; // Conversation items: we hold a list of those and create an LLFolderViewItem widget for each // that we tuck into the mConversationsListPanel. class LLConversationItem : public LLFolderViewModelItemCommon { public: - LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp); + LLConversationItem(std::string display_name, const LLUUID& uuid, LLIMFloaterContainer* containerp); LLConversationItem(LLIMFloaterContainer* containerp); virtual ~LLConversationItem() {} @@ -109,12 +109,11 @@ public: void* cargo_data, std::string& tooltip_msg) { return FALSE; } - bool hasSameValues(std::string name, const LLUUID& uuid) { return ((name == mName) && (uuid == mUUID)); } +// bool hasSameValues(std::string name, const LLUUID& uuid) { return ((name == mName) && (uuid == mUUID)); } bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } private: std::string mName; const LLUUID mUUID; - LLFloater* mFloater; LLIMFloaterContainer* mContainer; }; diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index b56f30312a..ec25583c8f 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -78,6 +78,19 @@ LLIMConversation::~LLIMConversation() delete mRefreshTimer; } +//static +LLIMConversation* LLIMConversation::findConversation(const LLUUID& uuid) +{ + return LLFloaterReg::findTypedInstance<LLIMConversation>(uuid.isNull()? "chat_bar" : "impanel", LLSD(uuid)); +}; + +//static +LLIMConversation* LLIMConversation::getConversation(const LLUUID& uuid) +{ + return LLFloaterReg::getTypedInstance<LLIMConversation>(uuid.isNull()? "chat_bar" : "impanel", LLSD(uuid)); +}; + + BOOL LLIMConversation::postBuild() { BOOL result; @@ -384,7 +397,7 @@ void LLIMConversation::onClose(bool app_quitting) LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); if (im_box) { - im_box->removeConversationListItem(this); + im_box->removeConversationListItem(mKey); } } } diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 649c200899..94a3a7781b 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -57,6 +57,9 @@ public: */ static bool isChatMultiTab(); + static LLIMConversation* findConversation(const LLUUID& uuid); + static LLIMConversation* getConversation(const LLUUID& uuid); + // show/hide the translation check box void showTranslationCheckbox(const BOOL visible = FALSE); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 3399a88c9e..6a1437f318 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -344,10 +344,6 @@ BOOL LLIMFloater::postBuild() initIMFloater(); - // Add a conversation list item in the left pane - LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); - im_box->addConversationListItem(getTitle(), getKey(), this); - return result; } @@ -547,7 +543,7 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) if (!avatar_list) { return; - } + } bool all_names_resolved = true; std::vector<LLSD> participants_uuids; @@ -555,12 +551,12 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) avatar_list->getValues(participants_uuids); // Check whether we have all participants names in LLAvatarNameCache - for (std::vector<LLSD>::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it) -{ + for (std::vector<LLSD>::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it) + { const LLUUID& id = it->asUUID(); LLAvatarName av_name; - if (!LLAvatarNameCache::get(id, &av_name)) - { + if (!LLAvatarNameCache::get(id, &av_name)) + { all_names_resolved = false; // If a name is not found in cache, request it and continue the process recursively @@ -568,8 +564,8 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) LLAvatarNameCache::get(id, boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list)); break; - } -} + } + } if (all_names_resolved) { @@ -580,20 +576,20 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) const LLUUID& id = it->asUUID(); LLAvatarName av_name; if (LLAvatarNameCache::get(id, &av_name)) -{ + { avatar_names.push_back(av_name); - } -} + } + } // We should check whether the vector is not empty to pass the assertion // that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. if (!avatar_names.empty()) -{ + { std::string ui_title; LLAvatarActions::buildResidentsString(avatar_names, ui_title); updateSessionName(ui_title, ui_title); } -} + } } //static diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index c2c0ddddea..1896ed65f3 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -76,13 +76,20 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { LLIMFloater::show(session_id); + addConversationListItem(session_id); +} + +void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) +{ + removeConversationListItem(old_session_id); + addConversationListItem(new_session_id); } void LLIMFloaterContainer::sessionRemoved(const LLUUID& session_id) { LLIMFloater* floaterp = LLIMFloater::findInstance(session_id); LLFloater::onClickClose(floaterp); - removeConversationListItem(floaterp); + removeConversationListItem(session_id); } BOOL LLIMFloaterContainer::postBuild() @@ -112,6 +119,10 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); mConversationsListPanel->addChild(mConversationsRoot); + addConversationListItem(LLUUID()); // manually add nearby chat + + addConversationListItem(LLUUID()); // manually add nearby chat + mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this)); @@ -301,13 +312,13 @@ void LLIMFloaterContainer::setVisible(BOOL visible) if (visible) { // Make sure we have the Nearby Chat present when showing the conversation container - LLFloater* nearby_chat = LLFloaterReg::findInstance("chat_bar"); + LLIMConversation* nearby_chat = LLIMConversation::getConversation(LLUUID::null); if (nearby_chat == NULL) { // If not found, force the creation of the nearby chat conversation panel // *TODO: find a way to move this to XML as a default panel or something like that LLSD name("chat_bar"); - LLFloaterReg::toggleInstanceOrBringToFront(name); + LLFloaterReg::toggleInstanceOrBringToFront(name, LLSD(LLUUID::null)); } } @@ -432,33 +443,29 @@ void LLIMFloaterContainer::repositioningWidgets() } // CHUI-137 : Temporary implementation of conversations list -void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp) +void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) { + std::string display_name = uuid.isNull()? LLTrans::getString("NearbyChatTitle") : LLIMModel::instance().getName(uuid); + // Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do) // Note: this happens often, when reattaching a torn off conversation for instance - conversations_items_map::iterator item_it = mConversationsItems.find(floaterp); + conversations_items_map::iterator item_it = mConversationsItems.find(uuid); if (item_it != mConversationsItems.end()) { - LLConversationItem* item = item_it->second; - // Check if the item has changed - if (item->hasSameValues(name,uuid)) - { - // If it hasn't changed, nothing to do -> exit - return; - } + return; } - + // Remove the conversation item that might exist already: it'll be recreated anew further down anyway // and nothing wrong will happen removing it if it doesn't exist - removeConversationListItem(floaterp,false); + removeConversationListItem(uuid,false); // Create a conversation item - LLConversationItem* item = new LLConversationItem(name, uuid, floaterp, this); - mConversationsItems[floaterp] = item; + LLConversationItem* item = new LLConversationItem(display_name, uuid, this); + mConversationsItems[uuid] = item; // Create a widget from it LLFolderViewItem* widget = createConversationItemWidget(item); - mConversationsWidgets[floaterp] = widget; + mConversationsWidgets[uuid] = widget; // Add a new conversation widget to the root folder of a folder view. widget->addToFolder(mConversationsRoot); @@ -473,12 +480,12 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI return; } -void LLIMFloaterContainer::removeConversationListItem(LLFloater* floaterp, bool change_focus) +void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) { // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener - conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(floaterp); + conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(uuid); if (widget_it != mConversationsWidgets.end()) { LLFolderViewItem* widget = widget_it->second; @@ -486,8 +493,8 @@ void LLIMFloaterContainer::removeConversationListItem(LLFloater* floaterp, bool } // Suppress the conversation items and widgets from their respective maps - mConversationsItems.erase(floaterp); - mConversationsWidgets.erase(floaterp); + mConversationsItems.erase(uuid); + mConversationsWidgets.erase(uuid); repositioningWidgets(); @@ -505,21 +512,6 @@ void LLIMFloaterContainer::removeConversationListItem(LLFloater* floaterp, bool return; } -LLFloater* LLIMFloaterContainer::findConversationItem(LLUUID& uuid) -{ - LLFloater* floaterp = NULL; - for (conversations_items_map::iterator item_it = mConversationsItems.begin(); item_it != mConversationsItems.end(); ++item_it) - { - LLConversationItem* item = item_it->second; - if (item->hasSameValue(uuid)) - { - floaterp = item_it->first; - break; - } - } - return floaterp; -} - LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) { LLFolderViewItem::Params params; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 161c6d9806..d6dda8ea2d 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -35,6 +35,7 @@ #include "llmultifloater.h" #include "llavatarpropertiesprocessor.h" #include "llgroupmgr.h" +#include "lltrans.h" #include "llconversationmodel.h" class LLButton; @@ -75,10 +76,11 @@ public: // LLIMSessionObserver observe triggers - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; + /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id); /*virtual*/ void sessionRemoved(const LLUUID& session_id); - /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {}; + /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); + LLConversationViewModel& getRootViewModel() { return mConversationViewModel; } private: @@ -107,9 +109,9 @@ private: // Conversation list implementation public: - void removeConversationListItem(LLFloater* floaterp, bool change_focus = true); - void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp); - LLFloater* findConversationItem(LLUUID& uuid); + void removeConversationListItem(const LLUUID& uuid, bool change_focus = true); + void addConversationListItem(const LLUUID& uuid); + private: LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 8f0e6b4c83..fa8e423056 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -152,7 +152,7 @@ BOOL LLNearbyChat::postBuild() // title must be defined BEFORE call addConversationListItem() because // it is used for show the item's name in the conversations list - setTitle(getString("NearbyChatTitle")); + setTitle(LLTrans::getString("NearbyChatTitle")); addToHost(); @@ -177,16 +177,13 @@ BOOL LLNearbyChat::postBuild() loadHistory(); } - // added row in the conversations list when nearby chat is tear-off - LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); - im_box->addConversationListItem(getTitle(), LLSD(), this); - return result; } // virtual void LLNearbyChat::refresh() { + updateHeaderAndToolbar(); displaySpeakingIndicator(); updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); @@ -386,7 +383,7 @@ void LLNearbyChat::onChatFontChange(LLFontGL* fontp) //static LLNearbyChat* LLNearbyChat::getInstance() { - return LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar"); + return LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar", LLSD(LLUUID::null)); } void LLNearbyChat::show() diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 8758c8c4e5..6be12711ac 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -49,6 +49,8 @@ class LLSysWellChiclet; class LLSysWellWindow : public LLTransientDockableFloater { public: + LOG_CLASS(LLSysWellWindow); + LLSysWellWindow(const LLSD& key); ~LLSysWellWindow(); BOOL postBuild(); diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 4abe4d6941..37aa8bb787 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -17,9 +17,6 @@ min_width="250" min_height="190" positioning="relative"> - <floater.string - name="NearbyChatTitle" - value="Nearby Chat"/> <floater.string name="call_btn_start">Conv_toolbar_open_call</floater.string> <floater.string name="call_btn_stop">Conv_toolbar_hang_up</floater.string> <floater.string diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 2806bcaa2e..696c282887 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -384,13 +384,14 @@ Please try logging in again in a minute.</string> <string name="ST_NO_JOINT">Can't find ROOT or JOINT.</string> <!-- Chat --> + <string name="NearbyChatTitle">Nearby chat</string> <string name="whisper">whispers:</string> <string name="shout">shouts:</string> <string name="ringing">Connecting to in-world Voice Chat...</string> <string name="connected">Connected</string> <string name="unavailable">Voice not available at your current location</string> <string name="hang_up">Disconnected from in-world Voice Chat</string> - <string name="reconnect_nearby">You will now be reconnected to Nearby Voice Chat</string> + <string name="reconnect_nearby">You will now be reconnected to Nearby Voice Chat</string> <string name="ScriptQuestionCautionChatGranted">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been granted permission to: [PERMISSIONS].</string> <string name="ScriptQuestionCautionChatDenied">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been denied permission to: [PERMISSIONS].</string> <string name="AdditionalPermissionsRequestHeader">If you allow access to your account, you will also be allowing the object to:</string> -- cgit v1.2.3 From f744fe8b5496e8d2d357ce88b3552eeee2125a5e Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Fri, 10 Aug 2012 02:51:56 +0300 Subject: CHUI-120 WIP Different notifications about single and multiple chat participants invited. The notification about starting a new conversation now applies only to P2P chat. Some code refactoring and clean up. --- indra/newview/llimfloater.cpp | 285 +++++++++------------ indra/newview/llimfloater.h | 8 +- .../skins/default/xui/en/floater_im_session.xml | 11 +- 3 files changed, 137 insertions(+), 167 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index a2989375ea..c3c9e334f2 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -60,6 +60,10 @@ #include "llnotificationmanager.h" #include "llautoreplace.h" +/// Helper function to resolve resident names from given uuids +/// and form a string of names separated by "words_separator". +static void build_names_string(const uuid_vec_t& uuids, std::string& names_string); + floater_showed_signal_t LLIMFloater::sIMFloaterShowedSignal; LLIMFloater::LLIMFloater(const LLUUID& session_id) @@ -186,49 +190,55 @@ void LLIMFloater::onVisibilityChange(const LLSD& new_visibility) void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata ) { LLIMFloater* self = (LLIMFloater*) userdata; - self->sendMsg(); + self->sendMsgFromInputEditor(); self->setTyping(false); } -void LLIMFloater::sendMsg() +void LLIMFloater::sendMsgFromInputEditor() { if (gAgent.isGodlike() || (mDialog != IM_NOTHING_SPECIAL) || !mOtherParticipantUUID.isNull()) { - if (mInputEditor) - { + if (mInputEditor) + { LLWString text = mInputEditor->getWText(); LLWStringUtil::trim(text); LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. - if(!text.empty()) - { - // Truncate and convert to UTF8 for transport - std::string utf8_text = wstring_to_utf8str(text); - utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); - - if (mSessionInitialized) - { - LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog); - } - else + if(!text.empty()) { - //queue up the message to send once the session is initialized - mQueuedMsgsForInit.append(utf8_text); - } + // Truncate and convert to UTF8 for transport + std::string utf8_text = wstring_to_utf8str(text); - mInputEditor->setText(LLStringUtil::null); + sendMsg(utf8_text); - updateMessages(); + mInputEditor->setText(LLStringUtil::null); + } } } -} else { llinfos << "Cannot send IM to everyone unless you're a god." << llendl; } } +void LLIMFloater::sendMsg(const std::string& msg) +{ + const std::string utf8_text = utf8str_truncate(msg, MAX_MSG_BUF_SIZE - 1); + + if (mSessionInitialized) + { + LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog); + } + else + { + //queue up the message to send once the session is initialized + mQueuedMsgsForInit.append(utf8_text); + } + + updateMessages(); +} + LLIMFloater::~LLIMFloater() { mParticipantsListRefreshConnection.disconnect(); @@ -241,6 +251,7 @@ LLIMFloater::~LLIMFloater() LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); } + void LLIMFloater::initIMSession(const LLUUID& session_id) { // Change the floater key to bind it to a new session. @@ -353,7 +364,7 @@ BOOL LLIMFloater::postBuild() void LLIMFloater::onAddButtonClicked() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::onAddSessionParticipants, this, _1), TRUE, TRUE); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE); if (!picker) { return; @@ -420,113 +431,65 @@ bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) return true; } -void LLIMFloater::onAddSessionParticipants(const uuid_vec_t& uuids) +void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) { - LLSD payload; - LLSD args; - for (uuid_vec_t::const_iterator iter = uuids.begin(); iter != uuids.end(); ++iter) + if (mIsP2PChat) { - payload["participant_ids"].append(*iter); - } - - LLNotificationsUtil::add("ConfirmAddingChatParticipants", args, payload, - boost::bind(&LLIMFloater::addSessionParticipants, this, _1, _2)); -} + LLSD payload; + LLSD args; -void LLIMFloater::addSessionParticipants(const LLSD& notification, const LLSD& response) -{ - uuid_vec_t uuids; - LLSD::array_const_iterator list_it = notification["payload"]["participant_ids"].beginArray(); - LLSD::array_const_iterator list_end = notification["payload"]["participant_ids"].endArray(); - for (; list_it != list_end; ++list_it) - { - uuids.push_back(list_it->asUUID()); + LLNotificationsUtil::add("ConfirmAddingChatParticipants", args, payload, + boost::bind(&LLIMFloater::addP2PSessionParticipants, this, uuids)); } - - std::vector<LLAvatarName> avatar_names; - uuid_vec_t::const_iterator it = uuids.begin(); - for (; it != uuids.end(); ++it) + else { - const LLUUID& id = *it; - LLAvatarName av_name; - if (LLAvatarNameCache::get(id, &av_name)) - { - avatar_names.push_back(av_name); - } - } - - std::string added_participants; + sendParticipantsAddedNotification(uuids); - // We should check whether the vector is not empty to pass the assertion - // that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. - if (!avatar_names.empty()) - { - LLAvatarActions::buildResidentsString(avatar_names, added_participants); + inviteToSession(uuids); } +} - LLStringUtil::format_map_t args; - args["[NAMES]"] = added_participants; - std::string participants_added_notification; - - if (mIsP2PChat) - { - mStartConferenceInSameFloater = true; +void LLIMFloater::addP2PSessionParticipants(const uuid_vec_t& uuids) +{ + sendParticipantsAddedNotification(uuids); - uuid_vec_t temp_ids; + mStartConferenceInSameFloater = true; - // Add the initial participant of a P2P session - temp_ids.push_back(mOtherParticipantUUID); - temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end()); + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + // first check whether this is a voice session + bool is_voice_call = voice_channel != NULL && voice_channel->isActive(); - // first check whether this is a voice session - bool is_voice_call = voice_channel != NULL && voice_channel->isActive(); + uuid_vec_t temp_ids; - // then we can close the current session - onClose(false); + // Add the initial participant of a P2P session + temp_ids.push_back(mOtherParticipantUUID); + temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end()); - participants_added_notification = getString("participants_added_new_window", args); - participants_added_notification = utf8str_truncate(participants_added_notification, MAX_MSG_BUF_SIZE - 1); + // then we can close the current session + onClose(false); - if (mSessionInitialized) - { - LLIMModel::sendMessage(participants_added_notification, mSessionID, mOtherParticipantUUID, mDialog); - } - else - { - //queue up the message to send once the session is initialized - mQueuedMsgsForInit.append(participants_added_notification); - } - - // Start a new ad hoc voice call if we invite new participants to a P2P call, - // or start a text chat otherwise. - if (is_voice_call) - { - LLAvatarActions::startAdhocCall(temp_ids, mSessionID); - } - else - { - LLAvatarActions::startConference(temp_ids, mSessionID); - } + // Start a new ad hoc voice call if we invite new participants to a P2P call, + // or start a text chat otherwise. + if (is_voice_call) + { + LLAvatarActions::startAdhocCall(temp_ids, mSessionID); } else { - participants_added_notification = getString("participants_added", args); - participants_added_notification = utf8str_truncate(participants_added_notification, MAX_MSG_BUF_SIZE - 1); + LLAvatarActions::startConference(temp_ids, mSessionID); + } +} - if (mSessionInitialized) - { - LLIMModel::sendMessage(participants_added_notification, mSessionID, mOtherParticipantUUID, mDialog); - } - else - { - //queue up the message to send once the session is initialized - mQueuedMsgsForInit.append(participants_added_notification); - } +void LLIMFloater::sendParticipantsAddedNotification(const uuid_vec_t& uuids) +{ + std::string names_string; + build_names_string(uuids, names_string); + LLStringUtil::format_map_t args; + args["[NAME]"] = names_string; + args["[NEW_WINDOW]"] = mIsP2PChat ? getString("new_window") : LLStringUtil::null; - inviteToSession(uuids); - } + sendMsg(getString(uuids.size() > 1 ? "multiple_participants_added" : "participant_added", args)); } void LLIMFloater::boundVoiceChannel() @@ -619,17 +582,19 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) if (!avatar_list) { return; - } + } bool all_names_resolved = true; std::vector<LLSD> participants_uuids; + uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string avatar_list->getValues(participants_uuids); // Check whether we have all participants names in LLAvatarNameCache for (std::vector<LLSD>::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it) -{ + { const LLUUID& id = it->asUUID(); + temp_uuids.push_back(id); LLAvatarName av_name; if (!LLAvatarNameCache::get(id, &av_name)) { @@ -641,31 +606,14 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list)); break; } -} + } if (all_names_resolved) { - std::vector<LLAvatarName> avatar_names; - std::vector<LLSD>::const_iterator it = participants_uuids.begin(); - for (; it != participants_uuids.end(); ++it) - { - const LLUUID& id = it->asUUID(); - LLAvatarName av_name; - if (LLAvatarNameCache::get(id, &av_name)) -{ - avatar_names.push_back(av_name); - } -} - - // We should check whether the vector is not empty to pass the assertion - // that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. - if (!avatar_names.empty()) -{ - std::string ui_title; - LLAvatarActions::buildResidentsString(avatar_names, ui_title); - updateSessionName(ui_title, ui_title); - } -} + std::string ui_title; + build_names_string(temp_uuids, ui_title); + updateSessionName(ui_title, ui_title); + } } //static @@ -1215,7 +1163,7 @@ bool LLIMFloater::dropPerson(LLUUID* person_id, bool drop) res = canAddSelectedToChat(ids); if(res && drop) { - onAddSessionParticipants(ids); + addSessionParticipants(ids); } } @@ -1254,37 +1202,32 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) if (is_region_exist) { - S32 count = ids.size(); + S32 count = ids.size(); - if( isInviteAllowed() && (count > 0) ) - { - llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl; - - std::string url = region->getCapability("ChatSessionRequest"); + if( isInviteAllowed() && (count > 0) ) + { + llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl; - LLSD data; + std::string url = region->getCapability("ChatSessionRequest"); - data["params"] = LLSD::emptyArray(); - for (int i = 0; i < count; i++) + LLSD data; + data["params"] = LLSD::emptyArray(); + for (int i = 0; i < count; i++) + { + data["params"].append(ids[i]); + } + data["method"] = "invite"; + data["session-id"] = mSessionID; + LLHTTPClient::post(url, data,new LLSessionInviteResponder(mSessionID)); + } + else { - data["params"].append(ids[i]); + llinfos << "LLIMFloater::inviteToSession -" + << " no need to invite agents for " + << mDialog << llendl; + // successful add, because everyone that needed to get added + // was added. } - - data["method"] = "invite"; - data["session-id"] = mSessionID; - LLHTTPClient::post( - url, - data, - new LLSessionInviteResponder(mSessionID)); - } - else - { - llinfos << "LLIMFloater::inviteToSession -" - << " no need to invite agents for " - << mDialog << llendl; - // successful add, because everyone that needed to get added - // was added. - } } return is_region_exist; @@ -1414,3 +1357,25 @@ boost::signals2::connection LLIMFloater::setIMFloaterShowedCallback(const floate { return LLIMFloater::sIMFloaterShowedSignal.connect(cb); } + +// static +void build_names_string(const uuid_vec_t& uuids, std::string& names_string) +{ + std::vector<LLAvatarName> avatar_names; + uuid_vec_t::const_iterator it = uuids.begin(); + for (; it != uuids.end(); ++it) + { + LLAvatarName av_name; + if (LLAvatarNameCache::get(*it, &av_name)) + { + avatar_names.push_back(av_name); + } + } + + // We should check whether the vector is not empty to pass the assertion + // that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. + if (!avatar_names.empty()) + { + LLAvatarActions::buildResidentsString(avatar_names, names_string); + } +} diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index d98213b54c..4e09a24a09 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -89,7 +89,8 @@ public: void updateMessages(); void reloadMessages(); static void onSendMsg(LLUICtrl*, void*); - void sendMsg(); + void sendMsgFromInputEditor(); + void sendMsg(const std::string& msg); // callback for LLIMModel on new messages // route to specific floater if it is visible @@ -160,8 +161,9 @@ private: static void onInputEditorKeystroke(LLTextEditor* caller, void* userdata); void setTyping(bool typing); void onAddButtonClicked(); - void onAddSessionParticipants(const uuid_vec_t& uuids); - void addSessionParticipants(const LLSD& notification, const LLSD& response); + void addSessionParticipants(const uuid_vec_t& uuids); + void addP2PSessionParticipants(const uuid_vec_t& uuids); + void sendParticipantsAddedNotification(const uuid_vec_t& uuids); bool canAddSelectedToChat(const uuid_vec_t& uuids); void onCallButtonClicked(); diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 2b63430106..de8d5f22fd 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -35,11 +35,14 @@ name="return_icon" value="Conv_toolbar_arrow_sw"/> <floater.string - name="participants_added" - value="New participant(s) were invited to the conversation: [NAMES]."/> + name="participant_added" + value="[NAME] was invited to the conversation.[NEW_WINDOW]"/> <floater.string - name="participants_added_new_window" - value="New participant(s) were invited to the conversation: [NAMES]. The conversation will be started in a new window."/> + name="multiple_participants_added" + value="[NAME] were invited to the conversation.[NEW_WINDOW]"/> + <floater.string + name="new_window" + value=" The conversation will be started in a new window."/> <view follows="all" layout="topleft" -- cgit v1.2.3 From a06256838cfc59c59d50bca0d75ad1b121bdd096 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 10 Aug 2012 17:13:16 +0300 Subject: build fix --- indra/newview/llimconversation.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 94a3a7781b..f21be94ee2 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -95,6 +95,9 @@ protected: void hideOrShowTitle(); // toggle the floater's drag handle void hideAllStandardButtons(); + /// Update floater header and toolbar buttons when hosted/torn off state is toggled. + void updateHeaderAndToolbar(); + bool mIsNearbyChat; bool mIsP2PChat; @@ -114,8 +117,6 @@ private: /// Refreshes the floater at a constant rate. virtual void refresh() = 0; - /// Update floater header and toolbar buttons when hosted/torn off state is toggled. - void updateHeaderAndToolbar(); /** * Adjusts chat history height to fit vertically with input chat field -- cgit v1.2.3 From f4c4df4cdd3dae7ce90efb8fbea8af1ba66410ff Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 10 Aug 2012 17:39:46 +0300 Subject: fix incorrect merge --- indra/newview/llimfloatercontainer.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 1896ed65f3..ad3b0279e5 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -73,6 +73,11 @@ LLIMFloaterContainer::~LLIMFloaterContainer() } } +void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +{ + addConversationListItem(session_id); +} + void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { LLIMFloater::show(session_id); -- cgit v1.2.3 From 09c890db98bb0996058e9faf1f867650707e3e31 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 10 Aug 2012 19:03:37 +0300 Subject: fixed merge issue. Done. --- indra/newview/llimfloatercontainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index ad3b0279e5..38b5768a60 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -317,7 +317,7 @@ void LLIMFloaterContainer::setVisible(BOOL visible) if (visible) { // Make sure we have the Nearby Chat present when showing the conversation container - LLIMConversation* nearby_chat = LLIMConversation::getConversation(LLUUID::null); + LLIMConversation* nearby_chat = LLIMConversation::findConversation(LLUUID::null); if (nearby_chat == NULL) { // If not found, force the creation of the nearby chat conversation panel -- cgit v1.2.3 From 52814c4e99f62815af85d1270f3268ef37adcb49 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 10 Aug 2012 17:09:14 -0700 Subject: CHUI-273: Problem was that after renaming the item, the item was not triggering a sort. Resolution: Once the name of the item is set, trigger a sorting of the parent. --- indra/llui/llfolderviewitem.cpp | 5 ----- indra/newview/llinventorybridge.cpp | 12 ++++++++++++ 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 68b442dd9a..1c33c4489b 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -415,11 +415,6 @@ void LLFolderViewItem::rename(const std::string& new_name) if( !new_name.empty() ) { getViewModelItem()->renameItem(new_name); - - //if(mParentFolder) - //{ - // mParentFolder->requestSort(); - //} } } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 43c4ce1278..6c3aaf5eec 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1553,6 +1553,12 @@ void LLItemBridge::buildDisplayName() const mSearchableName.assign(mDisplayName); mSearchableName.append(getLabelSuffix()); LLStringUtil::toUpper(mSearchableName); + + //Name set, so trigger a sort + if(mParent) + { + mParent->requestSort(); + } } LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const @@ -1859,6 +1865,12 @@ void LLFolderBridge::buildDisplayName() const mSearchableName.assign(mDisplayName); mSearchableName.append(getLabelSuffix()); LLStringUtil::toUpper(mSearchableName); + + //Name set, so trigger a sort + if(mParent) + { + mParent->requestSort(); + } } -- cgit v1.2.3 From c01254daf16adb3d91ad8990ba5c66d2b51eae45 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 14 Aug 2012 16:05:47 +0300 Subject: CHUI-171, CHUI-272 conversation is added as docked in conversation floater when session started (without click on an conv. list's item) --- indra/newview/llimfloatercontainer.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 38b5768a60..fe47e03beb 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -75,6 +75,7 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { + LLIMFloater::show(session_id); addConversationListItem(session_id); } -- cgit v1.2.3 From 039cc929d09828b449d3d9ec29c9ea297af56088 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Wed, 15 Aug 2012 15:03:19 +0300 Subject: CHUI-257 FIXED (Using clear cache option in preferences clears call log also) - Changed location where call log file is saved. Now it's saved with other user settings files under each avatar's directory in the user settings directory. --- indra/newview/llconversationlog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 137b97326c..b6713465f3 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -241,7 +241,7 @@ std::string LLConversationLog::getFileName() std::string agent_id_string; gAgent.getID().toString(agent_id_string); - return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, agent_id_string) + ".call_log"; + return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, agent_id_string) + ".call_log"; } bool LLConversationLog::saveToFile(const std::string& filename) -- cgit v1.2.3 From c234ef4b3a1ab22132512958c324e5f796912144 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Wed, 15 Aug 2012 15:06:25 +0300 Subject: CHUI-235 FIXED (Create icons for new conversation log list items) - Replaced old icons with new ones --- .../skins/default/textures/icons/Conv_log_inbox.png | Bin 0 -> 556 bytes indra/newview/skins/default/textures/textures.xml | 1 + .../default/xui/en/panel_conversation_log_list_item.xml | 9 ++++----- 3 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 indra/newview/skins/default/textures/icons/Conv_log_inbox.png (limited to 'indra') diff --git a/indra/newview/skins/default/textures/icons/Conv_log_inbox.png b/indra/newview/skins/default/textures/icons/Conv_log_inbox.png new file mode 100644 index 0000000000..bb6ca28147 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_log_inbox.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 212f05d284..47b0c12fa0 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -176,6 +176,7 @@ with the same filename but different name <texture name="Conv_toolbar_open_call" file_name="icons/Conv_toolbar_open_call.png" preload="false" /> <texture name="Conv_toolbar_plus" file_name="icons/Conv_toolbar_plus.png" preload="false" /> <texture name="Conv_toolbar_sort" file_name="icons/Conv_toolbar_sort.png" preload="false" /> + <texture name="Conv_log_inbox" file_name="icons/Conv_log_inbox.png" preload="false" /> <texture name="Copy" file_name="icons/Copy.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml index 3c98e32e7d..cee7d8581a 100644 --- a/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml @@ -33,19 +33,18 @@ height="20" layout="topleft" left="5" - image_name="Audio_Press" + image_name="Conv_toolbar_open_call" mouse_opaque="true" name="voice_session_icon" top="2" visible="false" width="20" /> <icon - default_icon_name="incoming_unread_im_icon" follows="top|left" height="20" layout="topleft" left="5" - image_name="Movement_Backward_Off" + image_name="Conv_log_inbox" mouse_opaque="false" name="unread_ims_icon" top="2" @@ -98,8 +97,8 @@ name="delete_btn" layout="topleft" follows="top|right" - image_unselected="Toast_CloseBtn" - image_selected="Toast_CloseBtn" + image_unselected="Conv_toolbar_close" + image_selected="Conv_toolbar_close" top="5" left_pad="0" height="14" -- cgit v1.2.3 From 3a21eb59f1cf0b7672e2beb671e1dbc717e28b3f Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 15 Aug 2012 20:10:00 +0300 Subject: CHUI-286 (Conversations floater opened by default when a new IM session is started (no IM toast shown): now floater silently adds itself to the container --- indra/newview/llimconversation.cpp | 3 +- indra/newview/llimfloater.cpp | 91 +++++++++++++++++----------------- indra/newview/llimfloater.h | 1 + indra/newview/llimfloatercontainer.cpp | 6 +-- indra/newview/llnearbychat.cpp | 1 - 5 files changed, 50 insertions(+), 52 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index ec25583c8f..4ca9476458 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -153,6 +153,7 @@ void LLIMConversation::draw() } refresh(); + updateHeaderAndToolbar(); // Restart the refresh timer mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); @@ -265,7 +266,7 @@ void LLIMConversation::hideAllStandardButtons() void LLIMConversation::updateHeaderAndToolbar() { - bool is_torn_off = isTornOff(); + bool is_torn_off = !getHost(); if (!is_torn_off) { hideAllStandardButtons(); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 6a1437f318..cdd5ba6889 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -128,7 +128,7 @@ void LLIMFloater::onClickCloseBtn() if (session == NULL) { - llwarns << "Empty session." << llendl; + llwarns << "Empty session with id: " << (mSessionID.asString()) << llendl; return; } @@ -250,7 +250,7 @@ void LLIMFloater::initIMSession(const LLUUID& session_id) mSession = LLIMModel::getInstance()->findIMSession(mSessionID); if (mSession) -{ + { mIsP2PChat = mSession->isP2PSessionType(); mSessionInitialized = mSession->mSessionInitialized; @@ -593,38 +593,19 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) } //static -LLIMFloater* LLIMFloater::show(const LLUUID& session_id) +LLIMFloater* LLIMFloater::addToIMContainer(const LLUUID& session_id) { - closeHiddenIMToasts(); - if (!gIMMgr->hasSession(session_id)) return NULL; - if(!isChatMultiTab()) - { - //hide all - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); - iter != inst_list.end(); ++iter) - { - LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); - if (floater && floater->isDocked()) - { - floater->setVisible(false); - } - } - } - // Test the existence of the floater before we try to create it bool exist = findInstance(session_id); // Get the floater: this will create the instance if it didn't exist LLIMFloater* floater = getInstance(session_id); - if (!floater) - return NULL; - - if(isChatMultiTab()) + if (floater) { + LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); // Do not add again existing floaters @@ -639,33 +620,51 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) } } - floater->openFloater(floater->getKey()); + if (floater_container && floater_container->getVisible()) + { + floater->openFloater(floater->getKey()); + floater->setVisible(TRUE); + } + else + { + floater->setVisible(FALSE); + } } - else - { - // Docking may move chat window, hide it before moving, or user will see how window "jumps" - floater->setVisible(false); + return floater; +} - if (floater->getDockControl() == NULL) - { - LLChiclet* chiclet = - LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLChiclet>( - session_id); - if (chiclet == NULL) - { - llerror("Dock chiclet for LLIMFloater doesn't exists", 0); - } - else - { - LLChicletBar::getInstance()->getChicletPanel()->scrollToChiclet(chiclet); - } +//static +LLIMFloater* LLIMFloater::show(const LLUUID& session_id) +{ + closeHiddenIMToasts(); - floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(), - LLDockControl::BOTTOM)); - } + if (!gIMMgr->hasSession(session_id)) + return NULL; - // window is positioned, now we can show it. + // Test the existence of the floater before we try to create it + bool exist = findInstance(session_id); + + // Get the floater: this will create the instance if it didn't exist + LLIMFloater* floater = getInstance(session_id); + if (!floater) + return NULL; + + LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); + + // Do not add again existing floaters + if (!exist) + { + // LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; + // TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists + LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END; + if (floater_container) + { + floater_container->addFloater(floater, TRUE, i_pt); + } } + + floater->openFloater(floater->getKey()); + floater->setVisible(TRUE); return floater; diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 434613ff43..d528c77e8d 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -78,6 +78,7 @@ public: /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); // Make IM conversion visible and update the message history static LLIMFloater* show(const LLUUID& session_id); + static LLIMFloater* addToIMContainer(const LLUUID& session_id); // Toggle panel specified by session_id // Returns true iff panel became visible diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index fe47e03beb..bcad7adcce 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -75,13 +75,13 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - LLIMFloater::show(session_id); + LLIMFloater::addToIMContainer(session_id); addConversationListItem(session_id); } void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { - LLIMFloater::show(session_id); + LLIMFloater::addToIMContainer(session_id); addConversationListItem(session_id); } @@ -93,8 +93,6 @@ void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const void LLIMFloaterContainer::sessionRemoved(const LLUUID& session_id) { - LLIMFloater* floaterp = LLIMFloater::findInstance(session_id); - LLFloater::onClickClose(floaterp); removeConversationListItem(session_id); } diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index fa8e423056..e1454fb5dc 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -183,7 +183,6 @@ BOOL LLNearbyChat::postBuild() // virtual void LLNearbyChat::refresh() { - updateHeaderAndToolbar(); displaySpeakingIndicator(); updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); -- cgit v1.2.3 From effccb94489d41a533e76f5f5834d52e3e817cbd Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Thu, 16 Aug 2012 04:55:48 +0300 Subject: CHUI-120 WIP Notifications about added chat participants should be sent to the conference when those participants actually join. - Removed notifying existing P2P participants about ad hoc conference staring in a new window. Now the notifications should arrive in that new window. - Fixed "Cancel" button which had no effect in adding P2P participants notification. --- indra/newview/llimfloater.cpp | 131 ++++++++++++++------- indra/newview/llimfloater.h | 4 +- .../skins/default/xui/en/floater_im_session.xml | 7 +- 3 files changed, 94 insertions(+), 48 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index c3c9e334f2..0f0048b0d0 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -127,14 +127,13 @@ void LLIMFloater::refresh() // virtual void LLIMFloater::onClickCloseBtn() { - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - mSessionID); + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); if (session == NULL) { llwarns << "Empty session." << llendl; return; -} + } bool is_call_with_chat = session->isGroupSessionType() || session->isAdHocSessionType() || session->isP2PSessionType(); @@ -228,7 +227,7 @@ void LLIMFloater::sendMsg(const std::string& msg) if (mSessionInitialized) { - LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog); + LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog); } else { @@ -261,7 +260,7 @@ void LLIMFloater::initIMSession(const LLUUID& session_id) mSession = LLIMModel::getInstance()->findIMSession(mSessionID); if (mSession) -{ + { mIsP2PChat = mSession->isP2PSessionType(); mSessionInitialized = mSession->mSessionInitialized; @@ -411,7 +410,7 @@ bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) if (speaker_mgr) { speaker_mgr->getSpeakerList(&speaker_list, true); - } + } for (uuid_vec_t::const_iterator id = uuids.begin(); id != uuids.end(); ++id) @@ -439,19 +438,24 @@ void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) LLSD args; LLNotificationsUtil::add("ConfirmAddingChatParticipants", args, payload, - boost::bind(&LLIMFloater::addP2PSessionParticipants, this, uuids)); + boost::bind(&LLIMFloater::addP2PSessionParticipants, this, _1, _2, uuids)); } else { - sendParticipantsAddedNotification(uuids); - + // remember whom we have invited, to notify others later, when the invited ones actually join + mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); + inviteToSession(uuids); } } -void LLIMFloater::addP2PSessionParticipants(const uuid_vec_t& uuids) +void LLIMFloater::addP2PSessionParticipants(const LLSD& notification, const LLSD& response, const uuid_vec_t& uuids) { - sendParticipantsAddedNotification(uuids); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) + { + return; + } mStartConferenceInSameFloater = true; @@ -469,6 +473,12 @@ void LLIMFloater::addP2PSessionParticipants(const uuid_vec_t& uuids) // then we can close the current session onClose(false); + // we start a new session so reset the initialization flag + mSessionInitialized = false; + + // remember whom we have invited, to notify others later, when the invited ones actually join + mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); + // Start a new ad hoc voice call if we invite new participants to a P2P call, // or start a text chat otherwise. if (is_voice_call) @@ -487,7 +497,6 @@ void LLIMFloater::sendParticipantsAddedNotification(const uuid_vec_t& uuids) build_names_string(uuids, names_string); LLStringUtil::format_map_t args; args["[NAME]"] = names_string; - args["[NEW_WINDOW]"] = mIsP2PChat ? getString("new_window") : LLStringUtil::null; sendMsg(getString(uuids.size() > 1 ? "multiple_participants_added" : "participant_added", args)); } @@ -865,18 +874,20 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) - //need to send delayed messaged collected while waiting for session initialization + //need to send delayed messages collected while waiting for session initialization if (mQueuedMsgsForInit.size()) { - LLSD::array_iterator iter; - for ( iter = mQueuedMsgsForInit.beginArray(); - iter != mQueuedMsgsForInit.endArray(); ++iter) - { - LLIMModel::sendMessage(iter->asString(), mSessionID, - mOtherParticipantUUID, mDialog); + LLSD::array_iterator iter; + for ( iter = mQueuedMsgsForInit.beginArray(); + iter != mQueuedMsgsForInit.endArray(); ++iter) + { + LLIMModel::sendMessage(iter->asString(), mSessionID, + mOtherParticipantUUID, mDialog); + } + + mQueuedMsgsForInit.clear(); } } -} void LLIMFloater::appendMessage(const LLChat& chat, const LLSD &args) { @@ -1044,19 +1055,18 @@ void LLIMFloater::setTyping(bool typing) { LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, mMeTyping); - mShouldSendTypingState = false; - - } + mShouldSendTypingState = false; } + } if (!mIsNearbyChat) + { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) { - LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if (speaker_mgr) - { - speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); + speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); } -} + } } void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) @@ -1075,29 +1085,66 @@ void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) void LLIMFloater::processAgentListUpdates(const LLSD& body) { + uuid_vec_t joined_uuids; + if (body.isMap() && body.has("agent_updates") && body["agent_updates"].isMap()) { - LLSD agent_data = body["agent_updates"].get(gAgentID.asString()); - if (agent_data.isMap() && agent_data.has("info")) + LLSD::map_const_iterator update_it; + for(update_it = body["agent_updates"].beginMap(); + update_it != body["agent_updates"].endMap(); + ++update_it) { - LLSD agent_info = agent_data["info"]; + LLUUID agent_id(update_it->first); + LLSD agent_data = update_it->second; - if (agent_info.has("mutes")) + if (agent_data.isMap()) { - BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean(); - mInputEditor->setEnabled(!moderator_muted_text); - std::string label; - if (moderator_muted_text) - label = LLTrans::getString("IM_muted_text_label"); - else - label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID); - mInputEditor->setLabel(label); + // store the new participants in joined_uuids + if (agent_data.has("transition") && agent_data["transition"].asString() == "ENTER") + { + joined_uuids.push_back(agent_id); + } - if (moderator_muted_text) - LLNotificationsUtil::add("TextChatIsMutedByModerator"); + // process the moderator mutes + if (agent_id == gAgentID && agent_data.has("info") && agent_data["info"].has("mutes")) + { + BOOL moderator_muted_text = agent_data["info"]["mutes"]["text"].asBoolean(); + mInputEditor->setEnabled(!moderator_muted_text); + std::string label; + if (moderator_muted_text) + label = LLTrans::getString("IM_muted_text_label"); + else + label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID); + mInputEditor->setLabel(label); + + if (moderator_muted_text) + LLNotificationsUtil::add("TextChatIsMutedByModerator"); + } } } } + + // the vectors need to be sorted for computing the intersection and difference + std::sort(mInvitedParticipants.begin(), mInvitedParticipants.end()); + std::sort(joined_uuids.begin(), joined_uuids.end()); + + uuid_vec_t intersection; // uuids of invited residents who have joined the conversation + std::set_intersection(mInvitedParticipants.begin(), mInvitedParticipants.end(), + joined_uuids.begin(), joined_uuids.end(), + std::back_inserter(intersection)); + + if (intersection.size() > 0) + { + sendParticipantsAddedNotification(intersection); + } + + // Remove all joined participants from invited array. + // The difference between the two vectors (the elements in mInvitedParticipants which are not in joined_uuids) + // is placed at the beginning of mInvitedParticipants, then all other elements are erased. + mInvitedParticipants.erase(std::set_difference(mInvitedParticipants.begin(), mInvitedParticipants.end(), + joined_uuids.begin(), joined_uuids.end(), + mInvitedParticipants.begin()), + mInvitedParticipants.end()); } void LLIMFloater::processSessionUpdate(const LLSD& session_update) diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 4e09a24a09..f78fa46b6e 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -162,7 +162,7 @@ private: void setTyping(bool typing); void onAddButtonClicked(); void addSessionParticipants(const uuid_vec_t& uuids); - void addP2PSessionParticipants(const uuid_vec_t& uuids); + void addP2PSessionParticipants(const LLSD& notification, const LLSD& response, const uuid_vec_t& uuids); void sendParticipantsAddedNotification(const uuid_vec_t& uuids); bool canAddSelectedToChat(const uuid_vec_t& uuids); @@ -204,6 +204,8 @@ private: bool mStartConferenceInSameFloater; + uuid_vec_t mInvitedParticipants; + // connection to voice channel state change signal boost::signals2::connection mVoiceChannelStateChangeConnection; diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index de8d5f22fd..15d3dc30ae 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -36,13 +36,10 @@ value="Conv_toolbar_arrow_sw"/> <floater.string name="participant_added" - value="[NAME] was invited to the conversation.[NEW_WINDOW]"/> + value="[NAME] was invited to the conversation."/> <floater.string name="multiple_participants_added" - value="[NAME] were invited to the conversation.[NEW_WINDOW]"/> - <floater.string - name="new_window" - value=" The conversation will be started in a new window."/> + value="[NAME] were invited to the conversation."/> <view follows="all" layout="topleft" -- cgit v1.2.3 From bec60ef80e72ab6df8ae0bf6b7a7824e8504426a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 20 Aug 2012 16:11:03 -0700 Subject: CHUI-295: Problem: The places panel implemention was incomplete and trying to make use of a class that was not fully implemented (placesfolderview). Resoltuion: Upon creation of the places panel, placesfolderview is created which contains the proper overloaded functions to show the correct menu when right clicking. --- indra/newview/CMakeLists.txt | 2 + indra/newview/llinventorypanel.cpp | 48 +++++++++--------- indra/newview/llinventorypanel.h | 1 + indra/newview/llpanellandmarks.cpp | 1 + indra/newview/llplacesfolderview.cpp | 74 +++++++++++++++++++++++++++ indra/newview/llplacesfolderview.h | 72 ++++++++++++++++++++++++++ indra/newview/llplacesinventorypanel.cpp | 86 +++++++++++--------------------- indra/newview/llplacesinventorypanel.h | 33 +----------- 8 files changed, 206 insertions(+), 111 deletions(-) create mode 100644 indra/newview/llplacesfolderview.cpp create mode 100644 indra/newview/llplacesfolderview.h (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 70493b1214..9553476aaf 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -445,6 +445,7 @@ set(viewer_SOURCE_FILES llphysicsshapebuilderutil.cpp llplacesinventorybridge.cpp llplacesinventorypanel.cpp + llplacesfolderview.cpp llpopupview.cpp llpolymesh.cpp llpolymorph.cpp @@ -1015,6 +1016,7 @@ set(viewer_HEADER_FILES llphysicsshapebuilderutil.h llplacesinventorybridge.h llplacesinventorypanel.h + llplacesfolderview.h llpolymesh.h llpolymorph.h llpopupview.h diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 22e6943f50..03dfada77c 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -151,6 +151,30 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : } +LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id ) +{ + LLFolderView::Params p(mParams.folder_view); + p.name = getName(); + p.title = getLabel(); + p.rect = LLRect(0, 0, getRect().getWidth(), 0); + p.parent_panel = this; + p.tool_tip = p.name; + p.listener = mInvFVBridgeBuilder->createBridge( LLAssetType::AT_CATEGORY, + LLAssetType::AT_CATEGORY, + LLInventoryType::IT_CATEGORY, + this, + &mInventoryViewModel, + NULL, + root_id); + p.view_model = &mInventoryViewModel; + p.use_label_suffix = mParams.use_label_suffix; + p.allow_multiselect = mAllowMultiSelect; + p.show_empty_message = mShowEmptyMessage; + p.show_item_link_overlays = mShowItemLinkOverlays; + p.root = NULL; + + return LLUICtrlFactory::create<LLFolderView>(p); +} void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) { @@ -172,29 +196,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) { // Determine the root folder in case specified, and // build the views starting with that folder. - - - LLFolderView::Params p(mParams.folder_view); - p.name = getName(); - p.title = getLabel(); - p.rect = LLRect(0, 0, getRect().getWidth(), 0); - p.parent_panel = this; - p.tool_tip = p.name; - p.listener = mInvFVBridgeBuilder->createBridge( LLAssetType::AT_CATEGORY, - LLAssetType::AT_CATEGORY, - LLInventoryType::IT_CATEGORY, - this, - &mInventoryViewModel, - NULL, - root_id); - p.view_model = &mInventoryViewModel; - p.use_label_suffix = mParams.use_label_suffix; - p.allow_multiselect = mAllowMultiSelect; - p.show_empty_message = mShowEmptyMessage; - p.show_item_link_overlays = mShowItemLinkOverlays; - p.root = NULL; - - mFolderRoot = LLUICtrlFactory::create<LLFolderView>(p); + mFolderRoot = createFolderRoot(root_id); addItemID(root_id, mFolderRoot); } diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index e9bfcb0ccf..c4f3c1b47d 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -278,6 +278,7 @@ protected: LLFolderViewItem* buildNewViews(const LLUUID& id); BOOL getIsHiddenFolderType(LLFolderType::EType folder_type) const; + virtual LLFolderView * createFolderRoot(LLUUID root_id ); virtual LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge); virtual LLFolderViewItem* createFolderViewItem(LLInvFVBridge * bridge); private: diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 9225ea3d53..469656c33f 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -52,6 +52,7 @@ #include "llmenubutton.h" #include "llplacesinventorybridge.h" #include "llplacesinventorypanel.h" +#include "llplacesfolderview.h" #include "lltoggleablemenu.h" #include "llviewermenu.h" #include "llviewerregion.h" diff --git a/indra/newview/llplacesfolderview.cpp b/indra/newview/llplacesfolderview.cpp new file mode 100644 index 0000000000..3caa93ae71 --- /dev/null +++ b/indra/newview/llplacesfolderview.cpp @@ -0,0 +1,74 @@ +/** +* @file llplacesfolderview.cpp +* @brief llplacesfolderview used within llplacesinventorypanel +* @author Gilbert@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" + +#include "llplacesfolderview.h" + +#include "llplacesinventorypanel.h" +#include "llpanellandmarks.h" + +LLPlacesFolderView::LLPlacesFolderView(const LLFolderView::Params& p) + : LLFolderView(p) +{ + // we do not need auto select functionality in places landmarks, so override default behavior. + // this disables applying of the LLSelectFirstFilteredItem in LLFolderView::doIdle. + // Fixed issues: EXT-1631, EXT-4994. + mAutoSelectOverride = TRUE; +} + +BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + // let children to change selection first + childrenHandleRightMouseDown(x, y, mask); + mParentLandmarksPanel->setCurrentSelectedList((LLPlacesInventoryPanel*)getParentPanel()); + + // then determine its type and set necessary menu handle + if (getCurSelectedItem()) + { + LLInventoryType::EType inventory_type = static_cast<LLFolderViewModelItemInventory*>(getCurSelectedItem()->getViewModelItem())->getInventoryType(); + inventory_type_menu_handle_t::iterator it_handle = mMenuHandlesByInventoryType.find(inventory_type); + + if (it_handle != mMenuHandlesByInventoryType.end()) + { + mPopupMenuHandle = (*it_handle).second; + } + else + { + llwarns << "Requested menu handle for non-setup inventory type: " << inventory_type << llendl; + } + + } + + return LLFolderView::handleRightMouseDown(x, y, mask); +} + +void LLPlacesFolderView::setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle) +{ + mMenuHandlesByInventoryType[asset_type] = menu_handle; +} + diff --git a/indra/newview/llplacesfolderview.h b/indra/newview/llplacesfolderview.h new file mode 100644 index 0000000000..8c5be39b5e --- /dev/null +++ b/indra/newview/llplacesfolderview.h @@ -0,0 +1,72 @@ +/** +* @file llplacesfolderview.h +* @brief llplacesfolderview used within llplacesinventorypanel +* @author Gilbert@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#ifndef LL_LLPLACESFOLDERVIEW_H +#define LL_LLPLACESFOLDERVIEW_H + +#include "llfolderview.h" +#include "llinventorypanel.h" + +class LLLandmarksPanel; + +class LLPlacesFolderView : public LLFolderView +{ +public: + + struct Params : public LLInitParam::Block<Params, LLFolderView::Params> + { + Params() + {} + }; + + LLPlacesFolderView(const LLFolderView::Params& p); + /** + * Handles right mouse down + * + * Contains workaround for EXT-2786: sets current selected list for landmark + * panel using @c mParentLandmarksPanel which is set in @c LLLandmarksPanel::initLandmarksPanel + */ + /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + + void setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle); + + void setParentLandmarksPanel(LLLandmarksPanel* panel) + { + mParentLandmarksPanel = panel; + } + +private: + /** + * holds pointer to landmark panel. This pointer is used in @c LLPlacesFolderView::handleRightMouseDown + */ + LLLandmarksPanel* mParentLandmarksPanel; + typedef std::map<LLInventoryType::EType, LLHandle<LLView> > inventory_type_menu_handle_t; + inventory_type_menu_handle_t mMenuHandlesByInventoryType; + +}; + +#endif // LL_LLPLACESFOLDERVIEW_H + diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index db3f245389..01586a4d91 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -31,7 +31,7 @@ #include "llplacesinventorypanel.h" #include "llfolderviewmodel.h" -#include "llfolderview.h" +#include "llplacesfolderview.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llpanellandmarks.h" @@ -58,6 +58,34 @@ LLPlacesInventoryPanel::~LLPlacesInventoryPanel() delete mSavedFolderState; } + +LLFolderView * LLPlacesInventoryPanel::createFolderRoot(LLUUID root_id ) +{ + LLPlacesFolderView::Params p; + + p.name = getName(); + p.title = getLabel(); + p.rect = LLRect(0, 0, getRect().getWidth(), 0); + p.parent_panel = this; + p.tool_tip = p.name; + p.listener = mInvFVBridgeBuilder->createBridge( LLAssetType::AT_CATEGORY, + LLAssetType::AT_CATEGORY, + LLInventoryType::IT_CATEGORY, + this, + &mInventoryViewModel, + NULL, + root_id); + p.view_model = &mInventoryViewModel; + p.use_label_suffix = mParams.use_label_suffix; + p.allow_multiselect = mAllowMultiSelect; + p.show_empty_message = mShowEmptyMessage; + p.show_item_link_overlays = mShowItemLinkOverlays; + p.root = NULL; + p.use_ellipses = mParams.folder_view.use_ellipses; + + return LLUICtrlFactory::create<LLPlacesFolderView>(p); +} + // save current folder open state void LLPlacesInventoryPanel::saveFolderState() { @@ -91,59 +119,3 @@ S32 LLPlacesInventoryPanel::notify(const LLSD& info) } return 0; } - -/************************************************************************/ -/* PROTECTED METHODS */ -/************************************************************************/ - - - -/************************************************************************/ -/* LLPlacesFolderView implementation */ -/************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// PUBLIC METHODS -////////////////////////////////////////////////////////////////////////// - -LLPlacesFolderView::LLPlacesFolderView(const LLFolderView::Params& p) -: LLFolderView(p) -{ - // we do not need auto select functionality in places landmarks, so override default behavior. - // this disables applying of the LLSelectFirstFilteredItem in LLFolderView::doIdle. - // Fixed issues: EXT-1631, EXT-4994. - mAutoSelectOverride = TRUE; -} - -BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - // let children to change selection first - childrenHandleRightMouseDown(x, y, mask); - mParentLandmarksPanel->setCurrentSelectedList((LLPlacesInventoryPanel*)getParentPanel()); - - // then determine its type and set necessary menu handle - if (getCurSelectedItem()) - { - LLInventoryType::EType inventory_type = static_cast<LLFolderViewModelItemInventory*>(getCurSelectedItem()->getViewModelItem())->getInventoryType(); - inventory_type_menu_handle_t::iterator it_handle = mMenuHandlesByInventoryType.find(inventory_type); - - if (it_handle != mMenuHandlesByInventoryType.end()) - { - mPopupMenuHandle = (*it_handle).second; - } - else - { - llwarns << "Requested menu handle for non-setup inventory type: " << inventory_type << llendl; - } - - } - - return LLFolderView::handleRightMouseDown(x, y, mask); -} - -void LLPlacesFolderView::setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle) -{ - mMenuHandlesByInventoryType[asset_type] = menu_handle; -} - -// EOF diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h index 1544b51aed..2805fc4257 100644 --- a/indra/newview/llplacesinventorypanel.h +++ b/indra/newview/llplacesinventorypanel.h @@ -29,9 +29,9 @@ #include "llfloaterinventory.h" #include "llinventorypanel.h" -#include "llfolderview.h" class LLLandmarksPanel; +class LLFolderView; class LLPlacesInventoryPanel : public LLInventoryPanel { @@ -46,6 +46,7 @@ public: LLPlacesInventoryPanel(const Params& p); ~LLPlacesInventoryPanel(); + LLFolderView * createFolderRoot(LLUUID root_id ); void saveFolderState(); void restoreFolderState(); @@ -55,34 +56,4 @@ private: LLSaveFolderState* mSavedFolderState; }; -//TODO RN: this class is currently unused, make sure that behavior remains -class LLPlacesFolderView : public LLFolderView -{ -public: - LLPlacesFolderView(const LLFolderView::Params& p); - /** - * Handles right mouse down - * - * Contains workaround for EXT-2786: sets current selected list for landmark - * panel using @c mParentLandmarksPanel which is set in @c LLLandmarksPanel::initLandmarksPanel - */ - /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - - void setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle); - - void setParentLandmarksPanel(LLLandmarksPanel* panel) - { - mParentLandmarksPanel = panel; - } - -private: - /** - * holds pointer to landmark panel. This pointer is used in @c LLPlacesFolderView::handleRightMouseDown - */ - LLLandmarksPanel* mParentLandmarksPanel; - typedef std::map<LLInventoryType::EType, LLHandle<LLView> > inventory_type_menu_handle_t; - inventory_type_menu_handle_t mMenuHandlesByInventoryType; - -}; - #endif //LL_LLINVENTORYSUBTREEPANEL_H -- cgit v1.2.3 From 0fc67126fe1c082caf640cba6b63ce9a0438cc23 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 20 Aug 2012 18:38:55 +0300 Subject: CHUI-290 FIXED (User cannot collapse names in ad hoc conversation when changed from p2p to ad hoc in torn off state): detect new collapse button state after rebuild of a participant list --- indra/newview/llimconversation.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 4ca9476458..ee7f58b01f 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -177,6 +177,7 @@ void LLIMConversation::buildParticipantList() mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false); } } + updateHeaderAndToolbar(); } void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata) -- cgit v1.2.3 From 2097e61dcb6865ad4c5b6667c9032f2cef658bd6 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 20 Aug 2012 17:54:33 +0300 Subject: CHUI-302 FIXED (User can resize conversation list too small with message panel collapsed) set floater's resize limits from a left panel's limits --- indra/newview/llimfloatercontainer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 450717e624..6b7912205e 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -402,6 +402,14 @@ void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) setCanResize(is_left_pane_expanded || is_right_pane_expanded); setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); + + // restore floater's resize limits (prevent collapse when left panel is expanded) + if (is_left_pane_expanded && !is_right_pane_expanded) + { + S32 expanded_min_size = mConversationsPane->getExpandedMinDim(); + setResizeLimits(expanded_min_size, expanded_min_size); + } + } void LLIMFloaterContainer::onAddButtonClicked() -- cgit v1.2.3 From 3d2045877c07810188ecbd4aac14befea57ddfb3 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 17 Aug 2012 19:33:24 +0300 Subject: CHUI-286 ADD. FIX (Conversations floater opened by default when a new IM session is started (no IM toast shown)): repair toast's system - suppress toasts only if corresponding floater is visible --- indra/newview/llimfloater.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index cdd5ba6889..2efe5d94e2 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -97,12 +97,12 @@ void LLIMFloater::onFocusLost() void LLIMFloater::onFocusReceived() { - LLIMModel::getInstance()->setActiveSessionID(mSessionID); - LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, true); if (getVisible()) { + // suppress corresponding toast only if this floater is visible and have focus + LLIMModel::getInstance()->setActiveSessionID(mSessionID); LLIMModel::instance().sendNoUnreadMessages(mSessionID); } } @@ -726,6 +726,7 @@ void LLIMFloater::setVisible(BOOL visible) LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> (LLNotificationsUI::LLChannelManager::getInstance()-> findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + LLTransientDockableFloater::setVisible(visible); // update notification channel state -- cgit v1.2.3 From 9a49dbcc456e1313750d5f8b127f29945f8d7ba9 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 16 Aug 2012 13:47:46 +0300 Subject: CHUI-299 (User can start IM session with themselves) FIXED: agent was excluded from the search results --- indra/newview/llfloateravatarpicker.cpp | 147 +++++++++++++++++--------------- indra/newview/llfloateravatarpicker.h | 7 +- indra/newview/llimfloatercontainer.cpp | 2 +- 3 files changed, 85 insertions(+), 71 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 0290e7cdf0..47acdf7057 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -58,7 +58,8 @@ static std::map<LLUUID, LLAvatarName> sAvatarNameMap; LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback, BOOL allow_multiple, - BOOL closeOnSelect) + BOOL closeOnSelect, + BOOL skip_agent) { // *TODO: Use a key to allow this not to be an effective singleton LLFloaterAvatarPicker* floater = @@ -73,6 +74,7 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback, floater->setAllowMultiple(allow_multiple); floater->mNearMeListComplete = FALSE; floater->mCloseOnSelect = closeOnSelect; + floater->mExcludeAgentFromSearchResults = skip_agent; if (!closeOnSelect) { @@ -581,35 +583,38 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void* msg->getUUIDFast( _PREHASH_Data,_PREHASH_AvatarID, avatar_id, i); msg->getStringFast(_PREHASH_Data,_PREHASH_FirstName, first_name, i); msg->getStringFast(_PREHASH_Data,_PREHASH_LastName, last_name, i); - - std::string avatar_name; - if (avatar_id.isNull()) - { - LLStringUtil::format_map_t map; - map["[TEXT]"] = floater->getChild<LLUICtrl>("Edit")->getValue().asString(); - avatar_name = floater->getString("not_found", map); - search_results->setEnabled(FALSE); - floater->getChildView("ok_btn")->setEnabled(FALSE); - } - else + + if (avatar_id != agent_id || !floater->isExcludeAgentFromSearchResults()) // exclude agent from search results? { - avatar_name = LLCacheName::buildFullName(first_name, last_name); - search_results->setEnabled(TRUE); - found_one = TRUE; + std::string avatar_name; + if (avatar_id.isNull()) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = floater->getChild<LLUICtrl>("Edit")->getValue().asString(); + avatar_name = floater->getString("not_found", map); + search_results->setEnabled(FALSE); + floater->getChildView("ok_btn")->setEnabled(FALSE); + } + else + { + avatar_name = LLCacheName::buildFullName(first_name, last_name); + search_results->setEnabled(TRUE); + found_one = TRUE; - LLAvatarName av_name; - av_name.mLegacyFirstName = first_name; - av_name.mLegacyLastName = last_name; - av_name.mDisplayName = avatar_name; - const LLUUID& agent_id = avatar_id; - sAvatarNameMap[agent_id] = av_name; + LLAvatarName av_name; + av_name.mLegacyFirstName = first_name; + av_name.mLegacyLastName = last_name; + av_name.mDisplayName = avatar_name; + const LLUUID& agent_id = avatar_id; + sAvatarNameMap[agent_id] = av_name; + } + LLSD element; + element["id"] = avatar_id; // value + element["columns"][0]["column"] = "name"; + element["columns"][0]["value"] = avatar_name; + search_results->addElement(element); } - LLSD element; - element["id"] = avatar_id; // value - element["columns"][0]["column"] = "name"; - element["columns"][0]["value"] = avatar_name; - search_results->addElement(element); } if (found_one) @@ -624,52 +629,58 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void* void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD& content) { // Check for out-of-date query - if (query_id != mQueryID) return; + if (query_id == mQueryID) + { + LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>("SearchResults"); - LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>("SearchResults"); + LLSD agents = content["agents"]; + + // clear "Searching" label on first results + search_results->deleteAllItems(); - LLSD agents = content["agents"]; - if (agents.size() == 0) - { - LLStringUtil::format_map_t map; - map["[TEXT]"] = childGetText("Edit"); LLSD item; - item["id"] = LLUUID::null; - item["columns"][0]["column"] = "name"; - item["columns"][0]["value"] = getString("not_found", map); - search_results->addElement(item); - search_results->setEnabled(false); - getChildView("ok_btn")->setEnabled(false); - return; - } + LLSD::array_const_iterator it = agents.beginArray(); + for ( ; it != agents.endArray(); ++it) + { + const LLSD& row = *it; + if (row["id"].asUUID() != gAgent.getID() || !mExcludeAgentFromSearchResults) + { + item["id"] = row["id"]; + LLSD& columns = item["columns"]; + columns[0]["column"] = "name"; + columns[0]["value"] = row["display_name"]; + columns[1]["column"] = "username"; + columns[1]["value"] = row["username"]; + search_results->addElement(item); + + // add the avatar name to our list + LLAvatarName avatar_name; + avatar_name.fromLLSD(row); + sAvatarNameMap[row["id"].asUUID()] = avatar_name; + } + } - // clear "Searching" label on first results - search_results->deleteAllItems(); - - LLSD item; - LLSD::array_const_iterator it = agents.beginArray(); - for ( ; it != agents.endArray(); ++it) - { - const LLSD& row = *it; - item["id"] = row["id"]; - LLSD& columns = item["columns"]; - columns[0]["column"] = "name"; - columns[0]["value"] = row["display_name"]; - columns[1]["column"] = "username"; - columns[1]["value"] = row["username"]; - search_results->addElement(item); - - // add the avatar name to our list - LLAvatarName avatar_name; - avatar_name.fromLLSD(row); - sAvatarNameMap[row["id"].asUUID()] = avatar_name; - } - - getChildView("ok_btn")->setEnabled(true); - search_results->setEnabled(true); - search_results->selectFirstItem(); - onList(); - search_results->setFocus(TRUE); + if (search_results->isEmpty()) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = childGetText("Edit"); + LLSD item; + item["id"] = LLUUID::null; + item["columns"][0]["column"] = "name"; + item["columns"][0]["value"] = getString("not_found", map); + search_results->addElement(item); + search_results->setEnabled(false); + getChildView("ok_btn")->setEnabled(false); + } + else + { + getChildView("ok_btn")->setEnabled(true); + search_results->setEnabled(true); + search_results->selectFirstItem(); + onList(); + search_results->setFocus(TRUE); + } + } } //static diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index 96c039443a..7067cd7b3e 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -45,7 +45,8 @@ public: // Call this to select an avatar. static LLFloaterAvatarPicker* show(select_callback_t callback, BOOL allow_multiple = FALSE, - BOOL closeOnSelect = FALSE); + BOOL closeOnSelect = FALSE, + BOOL skip_agent = FALSE); LLFloaterAvatarPicker(const LLSD& key); virtual ~LLFloaterAvatarPicker(); @@ -63,6 +64,7 @@ public: std::string& tooltip_msg); void openFriendsTab(); + BOOL isExcludeAgentFromSearchResults() {return mExcludeAgentFromSearchResults;} private: void editKeystroke(class LLLineEditor* caller, void* user_data); @@ -88,9 +90,10 @@ private: virtual BOOL handleKeyHere(KEY key, MASK mask); LLUUID mQueryID; - int mNumResultsReturned; + int mNumResultsReturned; BOOL mNearMeListComplete; BOOL mCloseOnSelect; + BOOL mExcludeAgentFromSearchResults; validate_signal_t mOkButtonValidateSignal; select_callback_t mSelectionCallback; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 6b7912205e..1e136b721c 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -414,7 +414,7 @@ void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) void LLIMFloaterContainer::onAddButtonClicked() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloaterContainer::onAvatarPicked, this, _1), TRUE, TRUE); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloaterContainer::onAvatarPicked, this, _1), TRUE, TRUE, TRUE); LLFloater* root_floater = gFloaterView->getParentFloater(this); if (picker && root_floater) { -- cgit v1.2.3 From 7f26bbac80669ecd15b666cc6c5ffec77945438b Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 16 Aug 2012 17:37:26 +0300 Subject: CHUI-278, CHUI-288 FIXED Panels in conversations floater does not fully collapse: changed parameter min_width -> expanded_min_dim --- indra/newview/skins/default/xui/en/floater_im_container.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index ea6fd65b95..e439fc9005 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -34,9 +34,9 @@ user_resize="true" height="430" name="conversations_layout_panel" - min_dim="51" + min_dim="38" width="268" - min_width="120"> + expanded_min_dim="120"> <layout_stack animate="false" follows="left|top|right" @@ -113,7 +113,7 @@ height="430" name="messages_layout_panel" width="412" - min_width="205"> + expanded_min_dim="205"> <panel_container follows="all" height="430" -- cgit v1.2.3 From 41cba389f89ff16c0e574ea26d6a1ceb60133ef7 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 16 Aug 2012 12:14:25 -0700 Subject: CHUI-269: Problem: When an item was purchased and delivered into the 'Received Items' panel, the badge icon and new item count would not show. This was due to the creation date of the folders not being set when a new item was added. Resolution: Now when an item is added into the 'Received Items' panel, the folder hierachy is updated, triggering the badge icon and new item count to show. --- indra/llui/llfolderviewitem.cpp | 17 ---------- indra/newview/llinventorybridge.cpp | 13 ++++++++ indra/newview/llinventorybridge.h | 1 + indra/newview/llinventorypanel.cpp | 11 +++--- indra/newview/llpanelmarketplaceinbox.cpp | 8 ----- indra/newview/llpanelmarketplaceinboxinventory.cpp | 39 ++++++++++------------ indra/newview/llpanelmarketplaceinboxinventory.h | 2 +- 7 files changed, 39 insertions(+), 52 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 1c33c4489b..b172359851 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1487,26 +1487,9 @@ void LLFolderViewFolder::addItem(LLFolderViewItem* item) item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); item->setVisible(FALSE); - - - // TODO RN - port creation date management to new code location -#if 0 - // Update the folder creation date if the child is newer than our current date - setCreationDate(llmax<time_t>(mCreationDate, item->getCreationDate())); -#endif addChild(item); getViewModelItem()->addChild(item->getViewModelItem()); - // TODO RN - port creation date management to new code location -#if 0 - // Traverse parent folders and update creation date and resort, if necessary - LLFolderViewFolder* parentp = getParentFolder(); - while (parentp) - { - // Update the folder creation date if the child is newer than our current date - parentp->setCreationDate(llmax<time_t>(parentp->mCreationDate, item->getCreationDate())); - } -#endif //TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria //// Traverse parent folders and update creation date and resort, if necessary diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 6c3aaf5eec..215a08b34a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3098,6 +3098,19 @@ bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& re return FALSE; } +//Recursively update the folder's creation date +void LLFolderBridge::updateHierarchyCreationDate(time_t date) +{ + if(getCreationDate() < date) + { + setCreationDate(date); + if(mParent) + { + static_cast<LLFolderBridge *>(mParent)->updateHierarchyCreationDate(date); + } + } +} + void LLFolderBridge::pasteFromClipboard() { LLInventoryModel* model = getInventoryModel(); diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index fc0b15acad..6beccf19ae 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -274,6 +274,7 @@ public: virtual BOOL removeItem(); BOOL removeSystemFolder(); bool removeItemResponse(const LLSD& notification, const LLSD& response); + void updateHierarchyCreationDate(time_t date); virtual void pasteFromClipboard(); virtual void pasteLinkFromClipboard(); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 82cb268e9e..22e6943f50 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -774,12 +774,13 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) } } - if (folder_view_item) - { - folder_view_item->addToFolder(parent_folder); + if (folder_view_item) + { + llassert(parent_folder != NULL); + folder_view_item->addToFolder(parent_folder); addItemID(id, folder_view_item); - } - } + } + } // If this is a folder, add the children of the folder and recursively add any // child folders. diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index ea0521e3a7..4a63585ed5 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -128,7 +128,6 @@ BOOL LLPanelMarketplaceInbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL dr U32 LLPanelMarketplaceInbox::getFreshItemCount() const { -#if SUPPORTING_FRESH_ITEM_COUNT // // NOTE: When turning this on, be sure to test the no inbox/outbox case because this code probably @@ -174,9 +173,6 @@ U32 LLPanelMarketplaceInbox::getFreshItemCount() const } return fresh_item_count; -#else - return getTotalItemCount(); -#endif } U32 LLPanelMarketplaceInbox::getTotalItemCount() const @@ -231,7 +227,6 @@ void LLPanelMarketplaceInbox::draw() args["[NUM]"] = item_count_str; mInboxButton->setLabel(getString("InboxLabelWithArg", args)); -#if SUPPORTING_FRESH_ITEM_COUNT // set green text to fresh item count U32 fresh_item_count = getFreshItemCount(); mFreshCountCtrl->setVisible((fresh_item_count > 0)); @@ -240,9 +235,6 @@ void LLPanelMarketplaceInbox::draw() { mFreshCountCtrl->setTextArg("[NUM]", llformat("%d", fresh_item_count)); } -#else - mFreshCountCtrl->setVisible(FALSE); -#endif } else { diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index 0d3fbe66d7..68aefa7fb7 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -95,22 +95,36 @@ LLInboxFolderViewFolder::LLInboxFolderViewFolder(const Params& p) LLBadgeOwner(getHandle()), mFresh(false) { -#if SUPPORTING_FRESH_ITEM_COUNT initBadgeParams(p.new_badge()); -#endif +} + +void LLInboxFolderViewFolder::addItem(LLFolderViewItem* item) +{ + LLFolderViewFolder::addItem(item); + + if(item) + { + LLInvFVBridge* itemBridge = static_cast<LLInvFVBridge*>(item->getViewModelItem()); + LLFolderBridge * bridge = static_cast<LLFolderBridge *>(getViewModelItem()); + bridge->updateHierarchyCreationDate(itemBridge->getCreationDate()); + } + + // Compute freshness if our parent is the root folder for the inbox + if (mParentFolder == mRoot) + { + computeFreshness(); + } } // virtual void LLInboxFolderViewFolder::draw() { -#if SUPPORTING_FRESH_ITEM_COUNT if (!badgeHasParent()) { addBadgeToParentPanel(); } setBadgeVisibility(mFresh); -#endif LLFolderViewFolder::draw(); } @@ -157,17 +171,6 @@ void LLInboxFolderViewFolder::deFreshify() gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); } -// TODO RN: move this behavior to modelview? -//void LLInboxFolderViewFolder::setCreationDate(time_t creation_date_utc) -//{ -// mCreationDate = creation_date_utc; -// -// if (LLFolderViewItem::mParentFolder == mRoot) -// { -// computeFreshness(); -// } -//} - // // LLInboxFolderViewItem Implementation // @@ -177,22 +180,18 @@ LLInboxFolderViewItem::LLInboxFolderViewItem(const Params& p) , LLBadgeOwner(getHandle()) , mFresh(false) { -#if SUPPORTING_FRESH_ITEM_COUNT initBadgeParams(p.new_badge()); -#endif } void LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder) { LLFolderViewItem::addToFolder(folder); -#if SUPPORTING_FRESH_ITEM_COUNT // Compute freshness if our parent is the root folder for the inbox if (mParentFolder == mRoot) { computeFreshness(); } -#endif } BOOL LLInboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask) @@ -205,14 +204,12 @@ BOOL LLInboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask) // virtual void LLInboxFolderViewItem::draw() { -#if SUPPORTING_FRESH_ITEM_COUNT if (!badgeHasParent()) { addBadgeToParentPanel(); } setBadgeVisibility(mFresh); -#endif LLFolderViewItem::draw(); } diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h index 098969aca6..c05e18c300 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.h +++ b/indra/newview/llpanelmarketplaceinboxinventory.h @@ -33,7 +33,6 @@ #include "llfolderviewitem.h" -#define SUPPORTING_FRESH_ITEM_COUNT 1 @@ -66,6 +65,7 @@ public: LLInboxFolderViewFolder(const Params& p); + void addItem(LLFolderViewItem* item); void draw(); void selectItem(); -- cgit v1.2.3 From d2b813fd79e4cf60d1670472c5a5f09ee9a2eed7 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 17 Aug 2012 20:08:01 +0300 Subject: Remove typo --- indra/newview/llimfloatercontainer.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index bcad7adcce..450717e624 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -125,8 +125,6 @@ BOOL LLIMFloaterContainer::postBuild() addConversationListItem(LLUUID()); // manually add nearby chat - addConversationListItem(LLUUID()); // manually add nearby chat - mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this)); -- cgit v1.2.3 From 8922dec40039a10e770243f3047793f8501fe43a Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Tue, 21 Aug 2012 19:51:41 +0300 Subject: CHUI-293 CHUI-294 FIXED displaying Group Invite and Transfer Object as notifications, instead of displaying as messages from an object. Restored the exception in handling "LoadWebPage", "ScriptDialog" and "ScriptDialogGroup" notifications, that caused only those notifications to be shown as messages from an object. --- indra/newview/llnotificationscripthandler.cpp | 42 +++++++++++----------- .../newview/skins/default/xui/en/notifications.xml | 3 ++ 2 files changed, 24 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 7e9c0d4f4b..5dcd84b400 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -78,33 +78,33 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) } if (notification->canLogToIM()) - { - LLHandlerUtil::logToIMP2P(notification); - } + { + LLHandlerUtil::logToIMP2P(notification); + } - if(notification->hasFormElements()) + if(notification->hasFormElements() && !notification->canShowToast()) + { + LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID()); + } + else + { + LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); + + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = notify_box; + p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); + + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); + if(channel) { - LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID()); + channel->addToast(p); } - else - { - LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); - - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.panel = notify_box; - p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); - - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); - if(channel) - { - channel->addToast(p); - } } return false; - } +} void LLScriptHandler::onDelete( LLNotificationPtr notification ) diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 64db7cd969..933135954f 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6742,6 +6742,7 @@ If you stay in this region you will be logged out. <notification icon="notify.tga" name="LoadWebPage" + show_toast="false" type="notify"> Load web page [URL]? @@ -6844,6 +6845,7 @@ It is rare that such a request is legitimate. Do not allow access if you do not <notification icon="notify.tga" name="ScriptDialog" + show_toast="false" type="notify"> [NAME]'s '<nolink>[TITLE]</nolink>' [MESSAGE] @@ -6862,6 +6864,7 @@ It is rare that such a request is legitimate. Do not allow access if you do not <notification icon="notify.tga" name="ScriptDialogGroup" + show_toast="false" type="notify"> <tag>group</tag> [GROUPNAME]'s '<nolink>[TITLE]</nolink>' -- cgit v1.2.3 From f809409de5df3f5ddef24433a4310b18caf3cd8a Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Tue, 21 Aug 2012 20:02:29 +0300 Subject: CHUI-300 FIXED (Simplify conversation log name saved to user settings?) - Changed file name agentID#.call_log to conversation.log --- indra/newview/llconversationlog.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index b6713465f3..486cea4064 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -238,10 +238,8 @@ void LLConversationLog::cache() std::string LLConversationLog::getFileName() { - std::string agent_id_string; - gAgent.getID().toString(agent_id_string); - - return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, agent_id_string) + ".call_log"; + std::string filename = "conversation"; + return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, filename) + ".log"; } bool LLConversationLog::saveToFile(const std::string& filename) -- cgit v1.2.3 From b93e2f7c84a8e14d7ca6c58c35183216a7fbf5bb Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Tue, 21 Aug 2012 20:04:13 +0300 Subject: CHUI-297 FIXED (Double clicking line item in conversation log does not start IM with User) - Added callback on double click which initiates IM session with selected conversation log list item --- indra/newview/llconversationloglistitem.cpp | 20 ++++++++++++++++++++ indra/newview/llconversationloglistitem.h | 2 ++ 2 files changed, 22 insertions(+) (limited to 'indra') diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp index fc2e757864..9f7c588989 100644 --- a/indra/newview/llconversationloglistitem.cpp +++ b/indra/newview/llconversationloglistitem.cpp @@ -31,9 +31,11 @@ #include "lltextutil.h" // newview +#include "llavataractions.h" #include "llavatariconctrl.h" #include "llconversationlog.h" #include "llconversationloglistitem.h" +#include "llgroupactions.h" #include "llgroupiconctrl.h" #include "llinventoryicon.h" @@ -74,6 +76,7 @@ BOOL LLConversationLogListItem::postBuild() mConversationDate->setValue(mConversation->getTimestamp()); getChild<LLButton>("delete_btn")->setClickedCallback(boost::bind(&LLConversationLogListItem::onRemoveBtnClicked, this)); + setDoubleClickCallback(boost::bind(&LLConversationLogListItem::onDoubleClick, this)); return TRUE; } @@ -155,3 +158,20 @@ void LLConversationLogListItem::highlightNameDate(const std::string& highlited_t LLTextUtil::textboxSetHighlightedVal(mConversationName, params, mConversation->getConversationName(), highlited_text); LLTextUtil::textboxSetHighlightedVal(mConversationDate, params, mConversation->getTimestamp(), highlited_text); } + +void LLConversationLogListItem::onDoubleClick() +{ + switch (mConversation->getConversationType()) + { + case LLIMModel::LLIMSession::P2P_SESSION: + LLAvatarActions::startIM(mConversation->getParticipantID()); + break; + + case LLIMModel::LLIMSession::GROUP_SESSION: + LLGroupActions::startIM(mConversation->getParticipantID()); + break; + + default: + break; + } +} diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h index deba7d4563..8943e11604 100644 --- a/indra/newview/llconversationloglistitem.h +++ b/indra/newview/llconversationloglistitem.h @@ -62,6 +62,8 @@ public: void highlightNameDate(const std::string& highlited_text); + void onDoubleClick(); + private: void initIcons(); -- cgit v1.2.3 From 10d2f695c8bf17357438729a1bf1a7f7bd1ee3f2 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 14 Sep 2012 13:59:32 +0300 Subject: CHUI-321 ADDITIONAL FIX (Indicate within the Call Log why there's nothing in it) - Corrected grammatical error --- indra/newview/skins/default/xui/en/floater_conversation_log.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml index df78bbccec..12d17e6b37 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -15,7 +15,7 @@ width="450"> <string name="logging_calls_disabled"> - Conversations are not being logged. To log conversations in the future, select "Save IM logs in my computer" under Preferences > Privacy. + Conversations are not being logged. To log conversations in the future, select "Save IM logs on my computer" under Preferences > Privacy. </string> <panel -- cgit v1.2.3 From e4de40ad8e1abed99c8c8d681c1dda46e72df94f Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 14 Sep 2012 14:37:48 +0300 Subject: CHUI-119 (Add Nearby chat to Conversations floater): addit. fix: use LLSD(LLUUID::null) instead LLSD::null as "default" floater's key --- indra/llui/llfloaterreg.cpp | 2 +- indra/llui/llfloaterreg.h | 24 ++++++++++++------------ indra/newview/llnearbychat.cpp | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 9115eb7174..920525448c 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -318,7 +318,7 @@ void LLFloaterReg::showInitialVisibleInstances() BOOL isvis = LLFloater::getControlGroup()->getBOOL(controlname); if (isvis) { - showInstance(name, LLSD()); // keyed floaters shouldn't set save_vis to true + showInstance(name, LLSD(LLUUID())); // keyed floaters shouldn't set save_vis to true } } } diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h index a1e1f8a988..7924b2a7b8 100644 --- a/indra/llui/llfloaterreg.h +++ b/indra/llui/llfloaterreg.h @@ -90,23 +90,23 @@ public: static LLFloater* getLastFloaterCascading(); // Find / get (create) / remove / destroy - static LLFloater* findInstance(const std::string& name, const LLSD& key = LLSD()); - static LLFloater* getInstance(const std::string& name, const LLSD& key = LLSD()); - static LLFloater* removeInstance(const std::string& name, const LLSD& key = LLSD()); - static bool destroyInstance(const std::string& name, const LLSD& key = LLSD()); + static LLFloater* findInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); + static LLFloater* getInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); + static LLFloater* removeInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); + static bool destroyInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); // Iterators static const_instance_list_t& getFloaterList(const std::string& name); // Visibility Management // return NULL if instance not found or can't create instance (no builder) - static LLFloater* showInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE); + static LLFloater* showInstance(const std::string& name, const LLSD& key = LLSD(LLUUID()), BOOL focus = FALSE); // Close a floater (may destroy or set invisible) // return false if can't find instance - static bool hideInstance(const std::string& name, const LLSD& key = LLSD()); + static bool hideInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); // return true if instance is visible: - static bool toggleInstance(const std::string& name, const LLSD& key = LLSD()); - static bool instanceVisible(const std::string& name, const LLSD& key = LLSD()); + static bool toggleInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); + static bool instanceVisible(const std::string& name, const LLSD& key = LLSD(LLUUID())); static void showInitialVisibleInstances(); static void hideVisibleInstances(const std::set<std::string>& exceptions = std::set<std::string>()); @@ -126,23 +126,23 @@ public: static void registerControlVariables(); // Callback wrappers - static void toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD()); + static void toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD(LLUUID())); // Typed find / get / show template <class T> - static T* findTypedInstance(const std::string& name, const LLSD& key = LLSD()) + static T* findTypedInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())) { return dynamic_cast<T*>(findInstance(name, key)); } template <class T> - static T* getTypedInstance(const std::string& name, const LLSD& key = LLSD()) + static T* getTypedInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())) { return dynamic_cast<T*>(getInstance(name, key)); } template <class T> - static T* showTypedInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE) + static T* showTypedInstance(const std::string& name, const LLSD& key = LLSD(LLUUID()), BOOL focus = FALSE) { return dynamic_cast<T*>(showInstance(name, key, focus)); } diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index ddd271e23f..a803b35aa8 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -108,7 +108,7 @@ static LLChatTypeTrigger sChatTypeTriggers[] = { LLNearbyChat::LLNearbyChat(const LLSD& llsd) -: LLIMConversation(LLSD()), +: LLIMConversation(llsd.asUUID()), //mOutputMonitor(NULL), mSpeakerMgr(NULL), mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) @@ -116,7 +116,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd) mIsP2PChat = false; mIsNearbyChat = true; setIsChrome(TRUE); - mKey = LLSD(); + mKey = LLSD(LLUUID()); mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); mSessionID = LLUUID(); setName("nearby_chat"); -- cgit v1.2.3 From 76827f03d429e3ce80def7a49c2657a1cb1179d4 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 22 Aug 2012 13:25:06 +0300 Subject: CHUI-289 FIXED (Newly added conversation is not selected in conversation list): added the "reverse" selecting - list item is selected when the corresponding floter gets focus. --- indra/newview/llconversationview.cpp | 3 ++- indra/newview/llimconversation.cpp | 10 ++++++++++ indra/newview/llimconversation.h | 3 +++ indra/newview/llimfloatercontainer.cpp | 26 +++++++++++++++++++++----- indra/newview/llimfloatercontainer.h | 4 +++- 5 files changed, 39 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 208a89cc8d..d5d4fc13da 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -239,7 +239,6 @@ S32 LLConversationViewSession::arrange(S32* width, S32* height) void LLConversationViewSession::selectItem() { - LLFolderViewItem::selectItem(); LLConversationItem* item = dynamic_cast<LLConversationItem*>(mViewModelItem); LLFloater* session_floater = LLIMConversation::getConversation(item->getUUID()); @@ -255,6 +254,8 @@ void LLConversationViewSession::selectItem() // Set the focus on the selected floater session_floater->setFocus(TRUE); + + LLFolderViewItem::selectItem(); } void LLConversationViewSession::setVisibleIfDetached(BOOL visible) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 216c5bbd70..bab588126f 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -215,11 +215,21 @@ void LLIMConversation::onFocusReceived() } LLTransientDockableFloater::onFocusReceived(); + + mHasFocus = mHaveFocus; + mHaveFocus = true; + + if (! mHasFocus) + { + LLIMFloaterContainer* container = LLIMFloaterContainer::getInstance(); + container->setConvItemSelect(mSessionID); + } } void LLIMConversation::onFocusLost() { setBackgroundOpaque(false); + mHaveFocus = false; LLTransientDockableFloater::onFocusLost(); } diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 41a76c206e..e09ba79a6a 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -139,6 +139,9 @@ private: void reshapeChatHistory(); LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. + + bool mHasFocus; + bool mHaveFocus; }; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 54a40627fb..81dddfaa70 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -183,9 +183,9 @@ void LLIMFloaterContainer::onOpen(const LLSD& key) } // virtual -void LLIMFloaterContainer::addFloater(LLFloater* floaterp, - BOOL select_added_floater, - LLTabContainer::eInsertionPoint insertion_point) +void LLIMFloaterContainer::addFloater(LLFloater* floaterp, + BOOL select_added_floater, + LLTabContainer::eInsertionPoint insertion_point) { if(!floaterp) return; @@ -427,7 +427,10 @@ void LLIMFloaterContainer::setVisible(BOOL visible) for (;widget_it != mConversationsWidgets.end(); ++widget_it) { LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); - widget->setVisibleIfDetached(visible); + if (widget) + { + widget->setVisibleIfDetached(visible); + } } // Now, do the normal multifloater show/hide @@ -608,6 +611,16 @@ void LLIMFloaterContainer::repositioningWidgets() } } +void LLIMFloaterContainer::setConvItemSelect(LLUUID& session_id) +{ + LLFolderViewItem* widget = mConversationsWidgets[session_id]; + if (widget && mSelectedSession != session_id) + { + mSelectedSession = session_id; + (widget->getRoot())->setSelection(widget, FALSE, FALSE); + } +} + void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) { bool is_nearby_chat = uuid.isNull(); @@ -675,7 +688,10 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c if (widget_it != mConversationsWidgets.end()) { LLFolderViewItem* widget = widget_it->second; - widget->destroyView(); + if (widget) + { + widget->destroyView(); + } } // Suppress the conversation items and widgets from their respective maps diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 324adfcc11..f6048bed37 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -62,7 +62,7 @@ public: /*virtual*/ void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); - + void setConvItemSelect(LLUUID& session_id); /*virtual*/ void tabClose(); static LLFloater* getCurrentVoiceFloater(); @@ -114,6 +114,8 @@ private: bool mInitialized; + LLUUID mSelectedSession; + // Conversation list implementation public: void removeConversationListItem(const LLUUID& uuid, bool change_focus = true); -- cgit v1.2.3 From b2f2a8b21610ae6863b773333c60b18b818c047f Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 22 Aug 2012 14:48:44 +0300 Subject: code style fix --- indra/newview/llimfloatercontainer.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 1e136b721c..6127a9a19b 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -519,7 +519,6 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c item->selectItem(); } } - return; } LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) -- cgit v1.2.3 From 14708a3ace184b0654ca7923732be6e06962d583 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 22 Aug 2012 18:27:29 +0300 Subject: CHUI_310 make NearbyChat a singletone --- indra/newview/llagent.cpp | 4 +- indra/newview/llchatitemscontainerctrl.cpp | 4 +- indra/newview/llfirstuse.cpp | 2 +- indra/newview/llfloatertranslationsettings.cpp | 2 +- indra/newview/llgesturemgr.cpp | 2 +- indra/newview/llimconversation.cpp | 32 +++++++++-- indra/newview/llimfloatercontainer.cpp | 6 +-- indra/newview/llimview.cpp | 7 +-- indra/newview/llnearbychat.cpp | 41 ++++++-------- indra/newview/llnearbychat.h | 8 +-- indra/newview/llnearbychathandler.cpp | 6 +-- indra/newview/llnotificationhandlerutil.cpp | 5 +- indra/newview/llnotificationtiphandler.cpp | 3 +- indra/newview/llstartup.cpp | 1 + indra/newview/llviewerfloaterreg.cpp | 2 +- indra/newview/llviewergesture.cpp | 2 +- indra/newview/llviewerkeyboard.cpp | 2 +- indra/newview/llviewermessage.cpp | 9 ++-- indra/newview/llviewerwindow.cpp | 62 +++++++++++----------- .../skins/default/xui/da/panel_nearby_chat_bar.xml | 2 +- .../skins/default/xui/de/floater_chat_bar.xml | 2 +- .../skins/default/xui/de/panel_nearby_chat_bar.xml | 2 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 4 +- .../skins/default/xui/en/panel_bottomtray_lite.xml | 2 +- .../skins/default/xui/en/panel_nearby_chat_bar.xml | 2 +- .../skins/default/xui/es/floater_chat_bar.xml | 2 +- .../skins/default/xui/es/panel_nearby_chat_bar.xml | 2 +- .../skins/default/xui/fr/floater_chat_bar.xml | 2 +- .../skins/default/xui/fr/panel_nearby_chat_bar.xml | 2 +- .../skins/default/xui/it/floater_chat_bar.xml | 2 +- .../skins/default/xui/it/panel_nearby_chat_bar.xml | 2 +- .../skins/default/xui/ja/floater_chat_bar.xml | 2 +- .../skins/default/xui/ja/panel_nearby_chat_bar.xml | 2 +- .../skins/default/xui/pl/panel_nearby_chat_bar.xml | 2 +- .../skins/default/xui/pt/floater_chat_bar.xml | 2 +- .../skins/default/xui/pt/panel_nearby_chat_bar.xml | 2 +- .../skins/default/xui/ru/floater_chat_bar.xml | 2 +- .../skins/default/xui/ru/panel_nearby_chat_bar.xml | 2 +- .../skins/default/xui/tr/floater_chat_bar.xml | 2 +- .../skins/default/xui/tr/panel_nearby_chat_bar.xml | 2 +- .../skins/default/xui/zh/panel_nearby_chat_bar.xml | 2 +- 41 files changed, 125 insertions(+), 121 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index f187318c0f..be6901c36a 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1911,7 +1911,7 @@ void LLAgent::startTyping() { sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START); } - LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE); + (LLNearbyChat::instance()).sendChatFromViewer("", CHAT_TYPE_START, FALSE); } //----------------------------------------------------------------------------- @@ -1923,7 +1923,7 @@ void LLAgent::stopTyping() { clearRenderState(AGENT_STATE_TYPING); sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); - LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); + (LLNearbyChat::instance()).sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); } } diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 61772b4bb7..e6340e0fa3 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -323,12 +323,12 @@ BOOL LLNearbyChatToastPanel::handleMouseUp (S32 x, S32 y, MASK mask) return TRUE; else { - LLNearbyChat::getInstance()->showHistory(); + LLNearbyChat::instance().showHistory(); return FALSE; } } - LLNearbyChat::getInstance()->showHistory(); + LLNearbyChat::instance().showHistory(); return LLPanel::handleMouseUp(x,y,mask); } diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp index a9f52282a5..e2850f5181 100644 --- a/indra/newview/llfirstuse.cpp +++ b/indra/newview/llfirstuse.cpp @@ -74,7 +74,7 @@ void LLFirstUse::resetFirstUse() // static void LLFirstUse::otherAvatarChatFirst(bool enable) { - firstUseNotification("FirstOtherChatBeforeUser", enable, "HintChat", LLSD(), LLSD().with("target", "chat_bar").with("direction", "top_right").with("distance", 24)); + firstUseNotification("FirstOtherChatBeforeUser", enable, "HintChat", LLSD(), LLSD().with("target", "nearby_chat").with("direction", "top_right").with("distance", 24)); } // static diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index bb01ce5a7e..b5b86dadc2 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -293,6 +293,6 @@ void LLFloaterTranslationSettings::onBtnOK() gSavedSettings.setString("TranslationService", getSelectedService()); gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey()); gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); - LLNearbyChat::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured()); + LLNearbyChat::instance().showTranslationCheckbox(LLTranslate::isTranslationConfigured()); closeFloater(false); } diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 26b63bdacb..0377337af6 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -997,7 +997,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) const BOOL animate = FALSE; - LLNearbyChat::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); + LLNearbyChat::instance().sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); gesture->mCurrentStep++; break; diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index ee7f58b01f..2212673d3a 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -81,13 +81,35 @@ LLIMConversation::~LLIMConversation() //static LLIMConversation* LLIMConversation::findConversation(const LLUUID& uuid) { - return LLFloaterReg::findTypedInstance<LLIMConversation>(uuid.isNull()? "chat_bar" : "impanel", LLSD(uuid)); + LLIMConversation* conv; + + if (uuid.isNull()) + { + conv = LLFloaterReg::findTypedInstance<LLIMConversation>("nearby_chat"); + } + else + { + conv = LLFloaterReg::findTypedInstance<LLIMConversation>("impanel", LLSD(uuid)); + } + + return conv; }; //static LLIMConversation* LLIMConversation::getConversation(const LLUUID& uuid) { - return LLFloaterReg::getTypedInstance<LLIMConversation>(uuid.isNull()? "chat_bar" : "impanel", LLSD(uuid)); + LLIMConversation* conv; + + if (uuid.isNull()) + { + conv = LLFloaterReg::getTypedInstance<LLIMConversation>("nearby_chat"); + } + else + { + conv = LLFloaterReg::getTypedInstance<LLIMConversation>("impanel", LLSD(uuid)); + } + + return conv; }; @@ -336,15 +358,15 @@ void LLIMConversation::processChatHistoryStyleUpdate() } } - LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - if (nearby_chat) + if (LLNearbyChat::instanceExists()) { - nearby_chat->reloadMessages(); + LLNearbyChat::instance().reloadMessages(); } } void LLIMConversation::updateCallBtnState(bool callIsActive) { +llwarns<<(this->getName())<<llendl; getChild<LLButton>("voice_call_btn")->setImageOverlay( callIsActive? getString("call_btn_stop") : getString("call_btn_start")); enableDisableCallBtn(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 4d0bd623f8..a3f5e357c9 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -315,13 +315,13 @@ void LLIMFloaterContainer::setVisible(BOOL visible) if (visible) { // Make sure we have the Nearby Chat present when showing the conversation container - LLIMConversation* nearby_chat = LLIMConversation::findConversation(LLUUID::null); + LLIMConversation* nearby_chat = LLFloaterReg::findTypedInstance<LLIMConversation>("nearby_chat"); if (nearby_chat == NULL) { // If not found, force the creation of the nearby chat conversation panel // *TODO: find a way to move this to XML as a default panel or something like that - LLSD name("chat_bar"); - LLFloaterReg::toggleInstanceOrBringToFront(name, LLSD(LLUUID::null)); + LLSD name("nearby_chat"); + LLFloaterReg::toggleInstanceOrBringToFront(name); } } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d88a558125..216db15c94 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2486,12 +2486,9 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess LLChat chat(message); chat.mSourceType = CHAT_SOURCE_SYSTEM; - - LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - - if(nearby_chat) + if (LLNearbyChat::instanceExists()) { - nearby_chat->addMessage(chat); + LLNearbyChat::instance().addMessage(chat); } } else // going to IM session diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index e1454fb5dc..a723748094 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -123,8 +123,8 @@ static LLChatTypeTrigger sChatTypeTriggers[] = { }; -LLNearbyChat::LLNearbyChat(const LLSD& key) -: LLIMConversation(key), +LLNearbyChat::LLNearbyChat(const LLSD& llsd) +: LLIMConversation(LLSD()), //mOutputMonitor(NULL), mSpeakerMgr(NULL), mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) @@ -133,6 +133,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& key) setIsChrome(TRUE); mKey = LLSD(); mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); + setName("nearby_chat"); } //virtual @@ -379,11 +380,6 @@ void LLNearbyChat::onChatFontChange(LLFontGL* fontp) } } -//static -LLNearbyChat* LLNearbyChat::getInstance() -{ - return LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar", LLSD(LLUUID::null)); -} void LLNearbyChat::show() { @@ -646,7 +642,10 @@ void LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args) chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); chat_args["show_names_for_p2p_conv"] = true; - mChatHistory->appendMessage(chat, chat_args); + if (mChatHistory) + { + mChatHistory->appendMessage(chat, chat_args); + } } } @@ -781,22 +780,20 @@ void LLNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BO // static void LLNearbyChat::startChat(const char* line) { - LLNearbyChat* cb = LLNearbyChat::getInstance(); - - if (cb ) + if (LLNearbyChat::instanceExists()) { - cb->show(); - cb->setVisible(TRUE); - cb->setFocus(TRUE); - cb->mInputEditor->setFocus(TRUE); + (LLNearbyChat::instance()).show(); + (LLNearbyChat::instance()).setVisible(TRUE); + (LLNearbyChat::instance()).setFocus(TRUE); + (LLNearbyChat::instance().mInputEditor)->setFocus(TRUE); if (line) { std::string line_string(line); - cb->mInputEditor->setText(line_string); + (LLNearbyChat::instance().mInputEditor)->setText(line_string); } - cb->mInputEditor->endOfDoc(); + (LLNearbyChat::instance().mInputEditor)->endOfDoc(); } } @@ -804,14 +801,10 @@ void LLNearbyChat::startChat(const char* line) // static void LLNearbyChat::stopChat() { - LLNearbyChat* cb = LLNearbyChat::getInstance(); - - if (cb) + if (LLNearbyChat::instanceExists()) { - cb->mInputEditor->setFocus(FALSE); - - // stop typing animation - gAgent.stopTyping(); + (LLNearbyChat::instance().mInputEditor)->setFocus(FALSE); + gAgent.stopTyping(); } } diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 7c58e3037e..379bfbee4b 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -35,17 +35,19 @@ #include "lloutputmonitorctrl.h" #include "llspeakers.h" #include "llscrollbar.h" +#include "llsingleton.h" #include "llviewerchat.h" #include "llpanel.h" class LLResizeBar; class LLNearbyChat - : public LLIMConversation + : public LLIMConversation, + public LLSingleton<LLNearbyChat> { public: // constructor for inline chat-bars (e.g. hosted in chat history window) - LLNearbyChat(const LLSD& key); + LLNearbyChat(const LLSD& key = LLSD()); ~LLNearbyChat() {} /*virtual*/ BOOL postBuild(); @@ -61,8 +63,6 @@ public: void reloadMessages(); void removeScreenChat(); - static LLNearbyChat* getInstance(); - void addToHost(); void show(); bool isChatVisible() const; diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index c97e3585e1..37f4cc4c19 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -487,8 +487,6 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, if(chat_msg.mText.empty()) return;//don't process empty messages - LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - // Build notification data LLSD chat; chat["message"] = chat_msg.mText; @@ -539,7 +537,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, } } - nearby_chat->addMessage(chat_msg, true, args); + LLNearbyChat::instance().addMessage(chat_msg, true, args); if(chat_msg.mSourceType == CHAT_SOURCE_AGENT && chat_msg.mFromID.notNull() @@ -555,7 +553,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, // Send event on to LLEventStream sChatWatcher->post(chat); - if( nearby_chat->isInVisibleChain() + if( LLNearbyChat::instance().isInVisibleChain() || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT && gSavedSettings.getBOOL("UseChatBubbles") ) || mChannel.isDead() diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index cba22b233b..db8e917435 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -181,14 +181,13 @@ void LLHandlerUtil::logGroupNoticeToIMGroup( // static void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type) { - LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - if(nearby_chat) + if (LLNearbyChat::instanceExists()) { LLChat chat_msg(notification->getMessage()); chat_msg.mSourceType = type; chat_msg.mFromName = SYSTEM_FROM; chat_msg.mFromID = LLUUID::null; - nearby_chat->addMessage(chat_msg); + LLNearbyChat::instance().addMessage(chat_msg); } } diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index a420c0d2ed..67fc9b27dc 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -85,8 +85,7 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); // don't show toast if Nearby Chat is opened - LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - if (nearby_chat->isChatVisible()) + if (LLNearbyChat::instance().isChatVisible()) { return false; } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index ab72b4e512..c827b39d0e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -64,6 +64,7 @@ #include "llmessageconfig.h" #include "llmoveview.h" #include "llimfloatercontainer.h" +#include "llnearbychat.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llteleporthistory.h" diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 50735d10bd..927ee8f380 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -192,7 +192,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>); LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>); - LLFloaterReg::add("chat_bar", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>); + LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>); LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>); LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>); diff --git a/indra/newview/llviewergesture.cpp b/indra/newview/llviewergesture.cpp index c7d37e102e..a2dea31d9b 100644 --- a/indra/newview/llviewergesture.cpp +++ b/indra/newview/llviewergesture.cpp @@ -130,7 +130,7 @@ void LLViewerGesture::doTrigger( BOOL send_chat ) { // Don't play nodding animation, since that might not blend // with the gesture animation. - LLNearbyChat::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); + LLNearbyChat::instance().sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); } } diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 385d3cd29a..7105720eb4 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -543,7 +543,7 @@ void start_gesture( EKeystate s ) if (KEYSTATE_UP == s && ! (focus_ctrlp && focus_ctrlp->acceptsTextInput())) { - if (LLNearbyChat::getInstance()->getCurrentChat().empty()) + if (LLNearbyChat::instance().getCurrentChat().empty()) { // No existing chat in chat editor, insert '/' LLNearbyChat::startChat("/"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index b20b86a582..9abd269f0f 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2297,12 +2297,10 @@ void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string m // Treat like a system message and put in chat history. chat.mText = av_name.getCompleteName() + ": " + message; - LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - if(nearby_chat) + if (LLNearbyChat::instanceExists()) { - nearby_chat->addMessage(chat); + LLNearbyChat::instance().addMessage(chat); } - } void process_improved_im(LLMessageSystem *msg, void **user_data) @@ -2897,8 +2895,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Note: lie to Nearby Chat, pretending that this is NOT an IM, because // IMs from obejcts don't open IM sessions. - LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - if(!chat_from_system && nearby_chat) + if(!chat_from_system && LLNearbyChat::instanceExists()) { chat.mOwnerID = from_id; LLSD args; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 1bcf15913f..23d2b1633d 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -198,7 +198,6 @@ #include "llfloaternotificationsconsole.h" -#include "llnearbychat.h" #include "llwindowlistener.h" #include "llviewerwindowlistener.h" #include "llpaneltopinfobar.h" @@ -2497,43 +2496,42 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) // Traverses up the hierarchy if( keyboard_focus ) { - LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("chat_bar"); - - if (nearby_chat) + if (LLNearbyChat::instanceExists()) { - LLChatEntry* chat_editor = nearby_chat->getChatBox(); - - // arrow keys move avatar while chatting hack - if (chat_editor && chat_editor->hasFocus()) - { - // If text field is empty, there's no point in trying to move - // cursor with arrow keys, so allow movement - if (chat_editor->getText().empty() - || gSavedSettings.getBOOL("ArrowKeysAlwaysMove")) + LLChatEntry* chat_editor = LLNearbyChat::instance().getChatBox(); + + // arrow keys move avatar while chatting hack + if (chat_editor && chat_editor->hasFocus()) { - // let Control-Up and Control-Down through for chat line history, - if (!(key == KEY_UP && mask == MASK_CONTROL) - && !(key == KEY_DOWN && mask == MASK_CONTROL)) + // If text field is empty, there's no point in trying to move + // cursor with arrow keys, so allow movement + if (chat_editor->getText().empty() + || gSavedSettings.getBOOL("ArrowKeysAlwaysMove")) { - switch(key) + // let Control-Up and Control-Down through for chat line history, + if (!(key == KEY_UP && mask == MASK_CONTROL) + && !(key == KEY_DOWN && mask == MASK_CONTROL)) { - case KEY_LEFT: - case KEY_RIGHT: - case KEY_UP: - case KEY_DOWN: - case KEY_PAGE_UP: - case KEY_PAGE_DOWN: - case KEY_HOME: - // when chatbar is empty or ArrowKeysAlwaysMove set, - // pass arrow keys on to avatar... - return FALSE; - default: - break; + switch(key) + { + case KEY_LEFT: + case KEY_RIGHT: + case KEY_UP: + case KEY_DOWN: + case KEY_PAGE_UP: + case KEY_PAGE_DOWN: + case KEY_HOME: + // when chatbar is empty or ArrowKeysAlwaysMove set, + // pass arrow keys on to avatar... + return FALSE; + default: + break; + } } } } } - } + if (keyboard_focus->handleKey(key, mask, FALSE)) { return TRUE; @@ -2564,11 +2562,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) { - LLChatEntry* chat_editor = LLNearbyChat::getInstance()->getChatBox(); + LLChatEntry* chat_editor = LLNearbyChat::instance().getChatBox(); if (chat_editor) { // passing NULL here, character will be added later when it is handled by character handler. - LLNearbyChat::getInstance()->startChat(NULL); + LLNearbyChat::instance().startChat(NULL); return TRUE; } } diff --git a/indra/newview/skins/default/xui/da/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/da/panel_nearby_chat_bar.xml index 949cbcbd7b..eb104201f8 100644 --- a/indra/newview/skins/default/xui/da/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/da/panel_nearby_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="chat_bar"> +<panel name="nearby_chat"> <line_editor label="Klik her for at chatte." name="chat_box" tool_tip="Tryk på enter for at tale, Ctrl-Enter for at råbe."/> <button name="show_nearby_chat" tool_tip="Viser/skjuler log for chat nærved"/> </panel> diff --git a/indra/newview/skins/default/xui/de/floater_chat_bar.xml b/indra/newview/skins/default/xui/de/floater_chat_bar.xml index 2464a55665..ab77d4dae5 100644 --- a/indra/newview/skins/default/xui/de/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/de/floater_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="chat_bar" title="CHAT IN DER NÄHE"> +<floater name="nearby_chat" title="CHAT IN DER NÄHE"> <panel name="bottom_panel"> <line_editor label="Zum Chatten hier klicken." name="chat_box" tool_tip="Eingabetaste zum Sprechen, Strg+Eingabe zum Rufen"/> <button name="show_nearby_chat" tool_tip="Chatprotokoll in der Nähe ein-/ausblenden"/> diff --git a/indra/newview/skins/default/xui/de/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/de/panel_nearby_chat_bar.xml index 08cc0b0ec8..69cf6d98de 100644 --- a/indra/newview/skins/default/xui/de/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/de/panel_nearby_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="chat_bar"> +<panel name="nearby_chat"> <line_editor label="Zum Chatten hier klicken." name="chat_box" tool_tip="Eingabe drücken, um zu sprechen, Strg-Eingabe drücken, um zu Rufen."/> <button name="show_nearby_chat" tool_tip="Protokoll des Chats in der Nähe anzeigen/ausblenden"/> </panel> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 1aa55acf2d..aa131035ed 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -225,10 +225,10 @@ use_mac_ctrl="true"> <menu_item_check.on_check function="Floater.Visible" - parameter="chat_bar" /> + parameter="nearby_chat" /> <menu_item_check.on_click function="Floater.Toggle" - parameter="chat_bar" /> + parameter="nearby_chat" /> </menu_item_check> <menu_item_check label="Speak" diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray_lite.xml b/indra/newview/skins/default/xui/en/panel_bottomtray_lite.xml index f4722b05d6..27a27473d8 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray_lite.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray_lite.xml @@ -46,7 +46,7 @@ follows="left|right" top="4" width="310" - name="chat_bar" + name="nearby_chat" mouse_opaque="false"/> </layout_panel> <layout_panel diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml index 6bc9c48729..19143cef89 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml @@ -5,7 +5,7 @@ height="25" layout="topleft" left="0" - name="chat_bar" + name="nearby_chat" top="21" width="308"> <line_editor diff --git a/indra/newview/skins/default/xui/es/floater_chat_bar.xml b/indra/newview/skins/default/xui/es/floater_chat_bar.xml index 2e94805057..02369c9a43 100644 --- a/indra/newview/skins/default/xui/es/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/es/floater_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="chat_bar" title="CHAT"> +<floater name="nearby_chat" title="CHAT"> <panel name="bottom_panel"> <line_editor label="Pulsa aquí para chatear." name="chat_box" tool_tip="Pulsa Enter para decirlo o Ctrl+Enter para gritarlo"/> <button name="show_nearby_chat" tool_tip="Muestra o esconde el registro del chat"/> diff --git a/indra/newview/skins/default/xui/es/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/es/panel_nearby_chat_bar.xml index af2b6e920b..e6ca59f912 100644 --- a/indra/newview/skins/default/xui/es/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/es/panel_nearby_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="chat_bar"> +<panel name="nearby_chat"> <line_editor label="Pulsa aquí para chatear." name="chat_box" tool_tip="Pulsa Enter para decirlo o Ctrl+Enter para gritarlo"/> <button name="show_nearby_chat" tool_tip="Muestra o esconde el registro del chat"/> </panel> diff --git a/indra/newview/skins/default/xui/fr/floater_chat_bar.xml b/indra/newview/skins/default/xui/fr/floater_chat_bar.xml index 890411d091..7dcb9a280d 100644 --- a/indra/newview/skins/default/xui/fr/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/fr/floater_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="chat_bar" title="CHAT PRÈS DE MOI"> +<floater name="nearby_chat" title="CHAT PRÈS DE MOI"> <panel name="bottom_panel"> <line_editor label="Cliquer ici pour chatter." name="chat_box" tool_tip="Appuyer sur Entrée pour dire, Ctrl+Entrée pour crier"/> <button name="show_nearby_chat" tool_tip="Afficher/masquer le journal de chat près de vous."/> diff --git a/indra/newview/skins/default/xui/fr/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/fr/panel_nearby_chat_bar.xml index 82cdf292ab..762dee01bb 100644 --- a/indra/newview/skins/default/xui/fr/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/fr/panel_nearby_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="chat_bar"> +<panel name="nearby_chat"> <line_editor label="Cliquer ici pour chatter." name="chat_box" tool_tip="Appuyer sur Entrée pour dire, Ctrl-Entrée pour crier"/> <button name="show_nearby_chat" tool_tip="Affiche/Masque le journal de chats près de vous"/> </panel> diff --git a/indra/newview/skins/default/xui/it/floater_chat_bar.xml b/indra/newview/skins/default/xui/it/floater_chat_bar.xml index 94c85b50c8..b47e32ce90 100644 --- a/indra/newview/skins/default/xui/it/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/it/floater_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="chat_bar" title="CHAT NEI DINTORNI"> +<floater name="nearby_chat" title="CHAT NEI DINTORNI"> <panel name="bottom_panel"> <line_editor label="Clicca qui per la chat." name="chat_box" tool_tip="Premi Invio per parlare, Ctrl+Invio per gridare"/> <button name="show_nearby_chat" tool_tip="Mostra/Nasconde il registro della chat nei dintorni"/> diff --git a/indra/newview/skins/default/xui/it/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/it/panel_nearby_chat_bar.xml index 6317d3192e..1fef88870a 100644 --- a/indra/newview/skins/default/xui/it/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/it/panel_nearby_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="chat_bar"> +<panel name="nearby_chat"> <string name="min_width"> 192 </string> diff --git a/indra/newview/skins/default/xui/ja/floater_chat_bar.xml b/indra/newview/skins/default/xui/ja/floater_chat_bar.xml index 11f223ade6..9f5df6fb85 100644 --- a/indra/newview/skins/default/xui/ja/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/ja/floater_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="chat_bar" title="近くのチャット"> +<floater name="nearby_chat" title="近くのチャット"> <panel name="bottom_panel"> <line_editor label="ここをクリックしてチャットを開始します。" name="chat_box" tool_tip="Enter キーを押して話し、Ctrl + Enter キーで叫びます。"/> <button name="show_nearby_chat" tool_tip="近くのチャットログを表示/非表示"/> diff --git a/indra/newview/skins/default/xui/ja/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/ja/panel_nearby_chat_bar.xml index 5998206f27..201fb0a376 100644 --- a/indra/newview/skins/default/xui/ja/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/ja/panel_nearby_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="chat_bar"> +<panel name="nearby_chat"> <line_editor label="ここをクリックしてチャットを開始します。" name="chat_box" tool_tip="Enter キーを押して発言し、Ctrl + Enter キーで叫びます。"/> <button name="show_nearby_chat" tool_tip="近くのチャットログを表示・非表示"/> </panel> diff --git a/indra/newview/skins/default/xui/pl/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/pl/panel_nearby_chat_bar.xml index 63cf96b571..4ed3ff669b 100644 --- a/indra/newview/skins/default/xui/pl/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/pl/panel_nearby_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="chat_bar"> +<panel name="nearby_chat"> <string name="min_width"> 192 </string> diff --git a/indra/newview/skins/default/xui/pt/floater_chat_bar.xml b/indra/newview/skins/default/xui/pt/floater_chat_bar.xml index 72016c6b40..2eb2c94940 100644 --- a/indra/newview/skins/default/xui/pt/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/pt/floater_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="chat_bar" title="BATE-PAPO LOCAL"> +<floater name="nearby_chat" title="BATE-PAPO LOCAL"> <panel name="bottom_panel"> <line_editor label="Clique aqui para bater papo." name="chat_box" tool_tip="Tecle Enter para falar, Ctrl+Enter para gritar"/> <button name="show_nearby_chat" tool_tip="Mostra/oculta o histórico do bate-papo local"/> diff --git a/indra/newview/skins/default/xui/pt/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/pt/panel_nearby_chat_bar.xml index 9b993488be..5628a87109 100644 --- a/indra/newview/skins/default/xui/pt/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/pt/panel_nearby_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="chat_bar"> +<panel name="nearby_chat"> <line_editor label="Clique aqui para bater papo." name="chat_box" tool_tip="Tecle Enter para falar, Ctrl+Enter para gritar"/> <button name="show_nearby_chat" tool_tip="Mostra/oculta o histórico do bate-papo local"/> </panel> diff --git a/indra/newview/skins/default/xui/ru/floater_chat_bar.xml b/indra/newview/skins/default/xui/ru/floater_chat_bar.xml index 79b7b033fb..f6b2fc81e1 100644 --- a/indra/newview/skins/default/xui/ru/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/ru/floater_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="chat_bar" title="ЛОКАЛЬНЫЙ ЧАТ"> +<floater name="nearby_chat" title="ЛОКАЛЬНЫЙ ЧАТ"> <panel name="bottom_panel"> <line_editor label="Щелкните здесь для общения." name="chat_box" tool_tip="Нажмите Enter, чтобы сказать, Ctrl+Enter, чтобы прокричать"/> <button name="show_nearby_chat" tool_tip="Показать/скрыть лог локального чата"/> diff --git a/indra/newview/skins/default/xui/ru/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/ru/panel_nearby_chat_bar.xml index 804ba7def7..395c643b0b 100644 --- a/indra/newview/skins/default/xui/ru/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/ru/panel_nearby_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="chat_bar"> +<panel name="nearby_chat"> <line_editor label="Щелкните здесь для общения" name="chat_box" tool_tip="Нажмите Enter, чтобы сказать, Ctrl+Enter, чтобы прокричать"/> <button name="show_nearby_chat" tool_tip="Показать/скрыть лог локального чата"/> </panel> diff --git a/indra/newview/skins/default/xui/tr/floater_chat_bar.xml b/indra/newview/skins/default/xui/tr/floater_chat_bar.xml index 988c845982..cd999b4b7a 100644 --- a/indra/newview/skins/default/xui/tr/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/tr/floater_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="chat_bar" title="YAKINDAKİ SOHBET"> +<floater name="nearby_chat" title="YAKINDAKİ SOHBET"> <panel name="bottom_panel"> <line_editor label="Sohbet etmek için buraya tıklayın." name="chat_box" tool_tip="Söylemek için Enter, bağırmak için Ctrl+Enter yapın"/> <button name="show_nearby_chat" tool_tip="Yakın sohbet günlüğünü gösterir/gizler"/> diff --git a/indra/newview/skins/default/xui/tr/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/tr/panel_nearby_chat_bar.xml index fd954475ac..7d191191c4 100644 --- a/indra/newview/skins/default/xui/tr/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/tr/panel_nearby_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="chat_bar"> +<panel name="nearby_chat"> <line_editor label="Sohbet etmek için buraya tıklayın." name="chat_box" tool_tip="Söylemek için Enter, bağırmak için Ctrl+Enter yapın"/> <button name="show_nearby_chat" tool_tip="yakın sohbet günlüğünü gösterir/gizler"/> </panel> diff --git a/indra/newview/skins/default/xui/zh/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/zh/panel_nearby_chat_bar.xml index 3cabfcfaba..f27f205c44 100644 --- a/indra/newview/skins/default/xui/zh/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/zh/panel_nearby_chat_bar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="chat_bar"> +<panel name="nearby_chat"> <line_editor label="點擊此處開始聊天。" name="chat_box" tool_tip="按下 Enter 鍵來說或按下 Ctrl+Enter 來喊叫"/> <button name="show_nearby_chat" tool_tip="顯示 / 隱藏 附近的聊天紀錄"/> </panel> -- cgit v1.2.3 From 2cf5307c9211b813689f0e441b9f56bc21f63348 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 22 Aug 2012 19:29:22 -0700 Subject: CHUI-282 : WIP : Isolated llconversationview classes and suppressed the dependency of model to widgets --- indra/newview/CMakeLists.txt | 2 ++ indra/newview/llconversationmodel.cpp | 31 ++++------------ indra/newview/llconversationmodel.h | 7 ++-- indra/newview/llconversationview.cpp | 64 ++++++++++++++++++++++++++++++++++ indra/newview/llconversationview.h | 63 +++++++++++++++++++++++++++++++++ indra/newview/llimfloatercontainer.cpp | 10 +++--- 6 files changed, 144 insertions(+), 33 deletions(-) create mode 100644 indra/newview/llconversationview.cpp create mode 100644 indra/newview/llconversationview.h (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9553476aaf..c49c625dbd 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -138,6 +138,7 @@ set(viewer_SOURCE_FILES llconversationloglist.cpp llconversationloglistitem.cpp llconversationmodel.cpp + llconversationview.cpp llcurrencyuimanager.cpp llcylinder.cpp lldateutil.cpp @@ -721,6 +722,7 @@ set(viewer_HEADER_FILES llconversationloglist.h llconversationloglistitem.h llconversationmodel.h + llconversationview.h llcurrencyuimanager.h llcylinder.h lldateutil.h diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 0c23e2654e..923bc7a3a1 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -32,41 +32,22 @@ #include "llimfloatercontainer.h" // Conversation items -LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& uuid, LLIMFloaterContainer* containerp) : - LLFolderViewModelItemCommon(containerp->getRootViewModel()), +LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : + LLFolderViewModelItemCommon(root_view_model), mName(display_name), - mUUID(uuid), - mContainer(containerp) + mUUID(uuid) { } -LLConversationItem::LLConversationItem(LLIMFloaterContainer* containerp) : - LLFolderViewModelItemCommon(containerp->getRootViewModel()), +LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_model) : + LLFolderViewModelItemCommon(root_view_model), mName(""), - mUUID(), - mContainer(NULL) + mUUID() { } // Virtual action callbacks -void LLConversationItem::selectItem(void) -{ - LLFloater* session_floater = LLIMConversation::getConversation(mUUID); - LLMultiFloater* host_floater = session_floater->getHost(); - -// LLIMFloater::show(mUUID); - if (host_floater == mContainer) - { - // Always expand the message pane if the panel is hosted by the container - mContainer->collapseMessagesPane(false); - // Switch to the conversation floater that is being selected - mContainer->selectFloater(session_floater); - } - // Set the focus on the selected floater - session_floater->setFocus(TRUE); -} - void LLConversationItem::setVisibleIfDetached(BOOL visible) { // Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 56a5b73c15..2f7124aec5 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -52,8 +52,8 @@ typedef std::map<LLUUID, LLFolderViewItem*> conversations_widgets_map; class LLConversationItem : public LLFolderViewModelItemCommon { public: - LLConversationItem(std::string display_name, const LLUUID& uuid, LLIMFloaterContainer* containerp); - LLConversationItem(LLIMFloaterContainer* containerp); + LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); + LLConversationItem(LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItem() {} // Stub those things we won't really be using in this conversation context @@ -95,7 +95,7 @@ public: virtual void openItem( void ); virtual void closeItem( void ); virtual void previewItem( void ); - virtual void selectItem(void); + virtual void selectItem(void) { } virtual void showProperties(void); void setVisibleIfDetached(BOOL visible); @@ -114,7 +114,6 @@ public: private: std::string mName; const LLUUID mUUID; - LLIMFloaterContainer* mContainer; }; // We don't want to ever filter conversations but we need to declare that class to create a conversation view model. diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp new file mode 100644 index 0000000000..7d90a154e5 --- /dev/null +++ b/indra/newview/llconversationview.cpp @@ -0,0 +1,64 @@ +/** + * @file llconversationview.cpp + * @brief Implementation of conversations list widgets and views + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" + +#include "llconversationview.h" +#include "llimconversation.h" +#include "llimfloatercontainer.h" + +LLConversationViewSession::Params::Params() : + container() +{} + +LLConversationViewSession::LLConversationViewSession( const LLConversationViewSession::Params& p ): + LLFolderViewFolder(p), + mContainer(p.container) +{ +} + +void LLConversationViewSession::selectItem() +{ + LLFolderViewItem::selectItem(); + + LLConversationItem* item = dynamic_cast<LLConversationItem*>(mViewModelItem); + LLFloater* session_floater = LLIMConversation::getConversation(item->getUUID()); + LLMultiFloater* host_floater = session_floater->getHost(); + + if (host_floater == mContainer) + { + // Always expand the message pane if the panel is hosted by the container + mContainer->collapseMessagesPane(false); + // Switch to the conversation floater that is being selected + mContainer->selectFloater(session_floater); + } + + // Set the focus on the selected floater + session_floater->setFocus(TRUE); +} + +// EOF diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h new file mode 100644 index 0000000000..08f2343aca --- /dev/null +++ b/indra/newview/llconversationview.h @@ -0,0 +1,63 @@ +/** + * @file llconversationview.h + * @brief Implementation of conversations list widgets and views + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLCONVERSATIONVIEW_H +#define LL_LLCONVERSATIONVIEW_H + +#include "llfolderviewitem.h" +#include "llfolderviewmodel.h" + +class LLButton; +class LLFloater; +class LLLayoutPanel; +class LLLayoutStack; +class LLTabContainer; +class LLIMFloaterContainer; + +// Implementation of conversations list widgets + +class LLConversationViewSession : public LLFolderViewFolder +{ +public: + struct Params : public LLInitParam::Block<Params, LLFolderViewItem::Params> + { + Optional<LLIMFloaterContainer*> container; + + Params(); + }; + +protected: + friend class LLUICtrlFactory; + LLConversationViewSession( const Params& p ); + + LLIMFloaterContainer* mContainer; + +public: + virtual ~LLConversationViewSession( void ) { } + virtual void selectItem(); +}; + +#endif // LL_LLCONVERSATIONVIEW_H diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 1e136b721c..29878cfc9e 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -43,6 +43,7 @@ #include "llimview.h" #include "lltransientfloatermgr.h" #include "llviewercontrol.h" +#include "llconversationview.h" // // LLIMFloaterContainer @@ -111,7 +112,7 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsListPanel = getChild<LLPanel>("conversations_list_panel"); // CHUI-98 : View Model for conversations - LLConversationItem* base_item = new LLConversationItem(this); + LLConversationItem* base_item = new LLConversationItem(getRootViewModel()); LLFolderView::Params p; p.view_model = &mConversationViewModel; p.parent_panel = mConversationsListPanel; @@ -470,7 +471,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) removeConversationListItem(uuid,false); // Create a conversation item - LLConversationItem* item = new LLConversationItem(display_name, uuid, this); + LLConversationItem* item = new LLConversationItem(display_name, uuid, getRootViewModel()); mConversationsItems[uuid] = item; // Create a widget from it @@ -524,7 +525,7 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) { - LLFolderViewItem::Params params; + LLConversationViewSession::Params params; params.name = item->getDisplayName(); //params.icon = bridge->getIcon(); @@ -534,8 +535,9 @@ LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversat params.listener = item; params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; + params.container = this; - return LLUICtrlFactory::create<LLFolderViewItem>(params); + return LLUICtrlFactory::create<LLConversationViewSession>(params); } // EOF -- cgit v1.2.3 From 679d0f78f9a4a83e5eb2ec857ceb2d9b8c6f4d91 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 22 Aug 2012 23:14:01 -0700 Subject: CHUI-282 : WIP, Clean up dependencies --- indra/newview/llconversationmodel.cpp | 1 - indra/newview/llconversationmodel.h | 10 ---------- indra/newview/llconversationview.cpp | 1 + indra/newview/llconversationview.h | 6 ------ 4 files changed, 1 insertion(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 923bc7a3a1..42ed7603d1 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -29,7 +29,6 @@ #include "llconversationmodel.h" #include "llimconversation.h" -#include "llimfloatercontainer.h" // Conversation items LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 2f7124aec5..1ce70d754b 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -27,19 +27,9 @@ #ifndef LL_LLCONVERSATIONMODEL_H #define LL_LLCONVERSATIONMODEL_H -//#include <map> -//#include <vector> - #include "llfolderviewitem.h" #include "llfolderviewmodel.h" -class LLButton; -class LLFloater; -class LLLayoutPanel; -class LLLayoutStack; -class LLTabContainer; -class LLIMFloaterContainer; - // Implementation of conversations list class LLConversationItem; diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 7d90a154e5..464d061a82 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -28,6 +28,7 @@ #include "llviewerprecompiledheaders.h" #include "llconversationview.h" +#include "llconversationmodel.h" #include "llimconversation.h" #include "llimfloatercontainer.h" diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 08f2343aca..743efb6384 100644 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -28,13 +28,7 @@ #define LL_LLCONVERSATIONVIEW_H #include "llfolderviewitem.h" -#include "llfolderviewmodel.h" -class LLButton; -class LLFloater; -class LLLayoutPanel; -class LLLayoutStack; -class LLTabContainer; class LLIMFloaterContainer; // Implementation of conversations list widgets -- cgit v1.2.3 From 41c85d357c8793f5119246b79441dd1dad9aa563 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Thu, 23 Aug 2012 18:07:35 +0300 Subject: CHUI-296 FIXED (Unread IM messages icon not showing in conversation log) - Sometimes IM floater with offline unread messages is visible but not in visible chain and the flag of offline unread messages is erroneously reset. So made condition of whether floater is visible more strict. --- indra/newview/llimfloater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 5780ac52a5..1c6445610f 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -789,7 +789,7 @@ void LLIMFloater::setVisible(BOOL visible) } } - if (visible) + if (visible && isInVisibleChain()) { sIMFloaterShowedSignal(mSessionID); } -- cgit v1.2.3 From 02e4068baaa7bcc49186e9a02a022f3d6cb087ac Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Thu, 23 Aug 2012 18:19:13 +0300 Subject: CHUI-306 FIXED (Selecting IM option for Group in conversation log does not start an IM if you did not initiate the conversation) - To start group call or group chat, group_id should be passed as an argument to LLGrupActions, not participant_id. --- indra/newview/llconversationloglist.cpp | 6 +++--- indra/newview/llconversationloglistitem.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 0433719a89..257ec082a5 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -193,7 +193,7 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata) break; case LLIMModel::LLIMSession::GROUP_SESSION: - LLGroupActions::startIM(selected_id); + LLGroupActions::startIM(getSelectedConversation()->getSessionID()); break; default: @@ -209,7 +209,7 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata) break; case LLIMModel::LLIMSession::GROUP_SESSION: - LLGroupActions::startCall(selected_id); + LLGroupActions::startCall(getSelectedConversation()->getSessionID()); break; default: @@ -225,7 +225,7 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata) break; case LLIMModel::LLIMSession::GROUP_SESSION: - LLGroupActions::show(selected_id); + LLGroupActions::show(getSelectedConversation()->getSessionID()); break; default: diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp index 9f7c588989..dddf216592 100644 --- a/indra/newview/llconversationloglistitem.cpp +++ b/indra/newview/llconversationloglistitem.cpp @@ -168,7 +168,7 @@ void LLConversationLogListItem::onDoubleClick() break; case LLIMModel::LLIMSession::GROUP_SESSION: - LLGroupActions::startIM(mConversation->getParticipantID()); + LLGroupActions::startIM(mConversation->getSessionID()); break; default: -- cgit v1.2.3 From 4ea73df484d22815026367771f9d728d755f6274 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 23 Aug 2012 11:32:20 -0700 Subject: CHUI-282 : WIP : Further separate view from model for llconversation items --- indra/newview/llconversationmodel.cpp | 14 -------------- indra/newview/llconversationmodel.h | 2 -- indra/newview/llconversationview.cpp | 13 +++++++++++++ indra/newview/llconversationview.h | 1 + indra/newview/llimfloatercontainer.cpp | 6 +++--- 5 files changed, 17 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 42ed7603d1..832dc3c3e4 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -28,7 +28,6 @@ #include "llviewerprecompiledheaders.h" #include "llconversationmodel.h" -#include "llimconversation.h" // Conversation items LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : @@ -45,20 +44,7 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod { } - // Virtual action callbacks -void LLConversationItem::setVisibleIfDetached(BOOL visible) -{ - // Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized - // Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here - LLFloater* session_floater = LLIMConversation::getConversation(mUUID); - - if (session_floater && !session_floater->getHost() && !session_floater->isMinimized()) - { - session_floater->setVisible(visible); - } -} - void LLConversationItem::performAction(LLInventoryModel* model, std::string action) { } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 1ce70d754b..cb03128cac 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -88,8 +88,6 @@ public: virtual void selectItem(void) { } virtual void showProperties(void); - void setVisibleIfDetached(BOOL visible); - // This method will be called to determine if a drop can be // performed, and will set drop to TRUE if a drop is // requested. diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 464d061a82..6cc911ecef 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -62,4 +62,17 @@ void LLConversationViewSession::selectItem() session_floater->setFocus(TRUE); } +void LLConversationViewSession::setVisibleIfDetached(BOOL visible) +{ + // Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized + // Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here + LLConversationItem* item = dynamic_cast<LLConversationItem*>(mViewModelItem); + LLFloater* session_floater = LLIMConversation::getConversation(item->getUUID()); + + if (session_floater && !session_floater->getHost() && !session_floater->isMinimized()) + { + session_floater->setVisible(visible); + } +} + // EOF diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 743efb6384..6a51e719c8 100644 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -52,6 +52,7 @@ protected: public: virtual ~LLConversationViewSession( void ) { } virtual void selectItem(); + void setVisibleIfDetached(BOOL visible); }; #endif // LL_LLCONVERSATIONVIEW_H diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 29878cfc9e..38ac3eb9e4 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -328,10 +328,10 @@ void LLIMFloaterContainer::setVisible(BOOL visible) // We need to show/hide all the associated conversations that have been torn off // (and therefore, are not longer managed by the multifloater), // so that they show/hide with the conversations manager. - conversations_items_map::iterator item_it = mConversationsItems.begin(); - for (;item_it != mConversationsItems.end(); ++item_it) + conversations_widgets_map::iterator item_it = mConversationsWidgets.begin(); + for (;item_it != mConversationsWidgets.end(); ++item_it) { - LLConversationItem* item = item_it->second; + LLConversationViewSession* item = dynamic_cast<LLConversationViewSession*>(item_it->second); item->setVisibleIfDetached(visible); } -- cgit v1.2.3 From 42701ad3233bfeddf42fb1163f2b83d810b27131 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 23 Aug 2012 15:14:04 -0700 Subject: CHUI-303: Problem: When pasting the item, the item's filtering flag was not updated. The filtering flag determines visibility. Resolution: Upon pasting the item to the folder from the clipboard, update the filtering flag so that visibility can properly be determined. --- indra/newview/llinventorybridge.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 215a08b34a..ac9f087d11 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3194,6 +3194,16 @@ void LLFolderBridge::pasteFromClipboard() llassert(vicat); if (vicat) { + //Set the pasted folder to dirty, could do this in changeCategoryParent() but only need to set dirty + //when pasting from the clipboard. Setting dirty allows updating the filter state, which determines + //visibility in the new pasted location. + + LLFolderViewFolder * folderViewItem = mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(item_id) : NULL; + if(folderViewItem && folderViewItem->getViewModelItem()) + { + folderViewItem->getViewModelItem()->dirtyFilter(); + } + changeCategoryParent(model, vicat, parent_id, FALSE); } } @@ -3203,6 +3213,7 @@ void LLFolderBridge::pasteFromClipboard() llassert(viitem); if (viitem) { + //changeItemParent() implicity calls dirtyFilter changeItemParent(model, viitem, parent_id, FALSE); } } -- cgit v1.2.3 From 15d957616ebac22a9f4633b6d806f8519423593b Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 23 Aug 2012 16:11:08 -0700 Subject: CHUI-282 : Use views for UI manipulation, not models --- indra/newview/llimfloatercontainer.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 35b9f404c3..32ef292763 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -328,11 +328,11 @@ void LLIMFloaterContainer::setVisible(BOOL visible) // We need to show/hide all the associated conversations that have been torn off // (and therefore, are not longer managed by the multifloater), // so that they show/hide with the conversations manager. - conversations_widgets_map::iterator item_it = mConversationsWidgets.begin(); - for (;item_it != mConversationsWidgets.end(); ++item_it) + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + for (;widget_it != mConversationsWidgets.end(); ++widget_it) { - LLConversationViewSession* item = dynamic_cast<LLConversationViewSession*>(item_it->second); - item->setVisibleIfDetached(visible); + LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); + widget->setVisibleIfDetached(visible); } // Now, do the normal multifloater show/hide @@ -513,11 +513,11 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c if (change_focus) { setFocus(TRUE); - conversations_items_map::iterator item_it = mConversationsItems.begin(); - if (item_it != mConversationsItems.end()) + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + if (widget_it != mConversationsWidgets.end()) { - LLConversationItem* item = item_it->second; - item->selectItem(); + LLFolderViewItem* widget = widget_it->second; + widget->selectItem(); } } } -- cgit v1.2.3 From e537d6477dfa1eea86dc16c767b793fb530d1ebc Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 23 Aug 2012 19:44:10 -0700 Subject: CHUI-98 : Defining the various llconversation sub classes in their respective file --- indra/newview/llconversationmodel.cpp | 33 ++++++++++++++++++++++++++++++++- indra/newview/llconversationmodel.h | 16 ++++++++++++++++ indra/newview/llconversationview.cpp | 13 +++++++++++++ indra/newview/llconversationview.h | 14 +++++++++++++- indra/newview/llimfloatercontainer.cpp | 2 +- 5 files changed, 75 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 832dc3c3e4..f54e6d2d48 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -29,7 +29,10 @@ #include "llconversationmodel.h" -// Conversation items +// +// Conversation items : common behaviors +// + LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(display_name), @@ -73,4 +76,32 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL return (compare < 0); } +// +// LLConversationItemSession +// + +LLConversationItemSession::LLConversationItemSession(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : + LLConversationItem(display_name,uuid,root_view_model) +{ +} + +LLConversationItemSession::LLConversationItemSession(LLFolderViewModelInterface& root_view_model) : + LLConversationItem(root_view_model) +{ +} + +// +// LLConversationItemParticipant +// + +LLConversationItemParticipant::LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : + LLConversationItem(display_name,uuid,root_view_model) +{ +} + +LLConversationItemParticipant::LLConversationItemParticipant(LLFolderViewModelInterface& root_view_model) : + LLConversationItem(root_view_model) +{ +} + // EOF diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index cb03128cac..fc2c600364 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -104,6 +104,22 @@ private: const LLUUID mUUID; }; +class LLConversationItemSession : public LLConversationItem +{ +public: + LLConversationItemSession(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); + LLConversationItemSession(LLFolderViewModelInterface& root_view_model); + virtual ~LLConversationItemSession() {} +}; + +class LLConversationItemParticipant : public LLConversationItem +{ +public: + LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); + LLConversationItemParticipant(LLFolderViewModelInterface& root_view_model); + virtual ~LLConversationItemParticipant() {} +}; + // We don't want to ever filter conversations but we need to declare that class to create a conversation view model. // We just stubb everything for the moment. class LLConversationFilter : public LLFolderViewFilter diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 6cc911ecef..fefb7e9cac 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -32,6 +32,10 @@ #include "llimconversation.h" #include "llimfloatercontainer.h" +// +// Implementation of conversations list session widgets +// + LLConversationViewSession::Params::Params() : container() {} @@ -75,4 +79,13 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible) } } +// +// Implementation of conversations list participant (avatar) widgets +// + +LLConversationViewParticipant::LLConversationViewParticipant( const LLFolderViewItem::Params& p ): + LLFolderViewItem(p) +{ +} + // EOF diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 6a51e719c8..5695925f43 100644 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -31,7 +31,7 @@ class LLIMFloaterContainer; -// Implementation of conversations list widgets +// Implementation of conversations list session widgets class LLConversationViewSession : public LLFolderViewFolder { @@ -55,4 +55,16 @@ public: void setVisibleIfDetached(BOOL visible); }; +// Implementation of conversations list participant (avatar) widgets + +class LLConversationViewParticipant : public LLFolderViewItem +{ +protected: + friend class LLUICtrlFactory; + LLConversationViewParticipant( const LLFolderViewItem::Params& p ); + +public: + virtual ~LLConversationViewParticipant( void ) { } +}; + #endif // LL_LLCONVERSATIONVIEW_H diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 32ef292763..4d0bd623f8 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -471,7 +471,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) removeConversationListItem(uuid,false); // Create a conversation item - LLConversationItem* item = new LLConversationItem(display_name, uuid, getRootViewModel()); + LLConversationItem* item = new LLConversationItemSession(display_name, uuid, getRootViewModel()); mConversationsItems[uuid] = item; // Create a widget from it -- cgit v1.2.3 From 6e92b96e88401aaca203b627e84ce311b7f75e4a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 24 Aug 2012 13:53:17 -0700 Subject: kicking off another build (whitespace change) --- indra/newview/llinventorybridge.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index ac9f087d11..91798e0f10 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3197,7 +3197,6 @@ void LLFolderBridge::pasteFromClipboard() //Set the pasted folder to dirty, could do this in changeCategoryParent() but only need to set dirty //when pasting from the clipboard. Setting dirty allows updating the filter state, which determines //visibility in the new pasted location. - LLFolderViewFolder * folderViewItem = mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(item_id) : NULL; if(folderViewItem && folderViewItem->getViewModelItem()) { -- cgit v1.2.3 From fd62242dd6e5fa464db07e0b8ebf3ab54a6067a2 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 24 Aug 2012 17:31:12 -0700 Subject: CHUI-280 : Make LLParticipantList derives from LLConversationItemSession --- indra/newview/llcallfloater.cpp | 2 +- indra/newview/llcallfloater.h | 2 ++ indra/newview/llconversationmodel.cpp | 15 +++++++++++---- indra/newview/llconversationmodel.h | 5 +++-- indra/newview/llimconversation.cpp | 4 ++-- indra/newview/llimconversation.h | 2 ++ indra/newview/llparticipantlist.cpp | 2 ++ indra/newview/llparticipantlist.h | 4 +++- 8 files changed, 26 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index f2375bfa4f..38b755004c 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -334,7 +334,7 @@ void LLCallFloater::refreshParticipantList() if (!non_avatar_caller) { llassert(mParticipants == NULL); // check for possible memory leak - mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT, false); + mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, mConversationViewModel, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT, false); mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1)); const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder"); mParticipants->setSortOrder(LLParticipantList::EParticipantSortOrder(speaker_sort_order)); diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index 00a3f76e56..181c92276d 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -31,6 +31,7 @@ #include "lltransientdockablefloater.h" #include "llvoicechannel.h" #include "llvoiceclient.h" +#include "llconversationmodel.h" class LLAvatarList; class LLAvatarListItem; @@ -228,6 +229,7 @@ private: LLSpeakerMgr* mSpeakerManager; LLParticipantList* mParticipants; LLAvatarList* mAvatarList; + LLConversationViewModel mConversationViewModel; LLNonAvatarCaller* mNonAvatarCaller; EVoiceControls mVoiceType; LLPanel* mAgentPanel; diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index f54e6d2d48..a5c0244bd4 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -40,6 +40,13 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& u { } +LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : + LLFolderViewModelItemCommon(root_view_model), + mName(""), + mUUID(uuid) +{ +} + LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(""), @@ -85,8 +92,8 @@ LLConversationItemSession::LLConversationItemSession(std::string display_name, c { } -LLConversationItemSession::LLConversationItemSession(LLFolderViewModelInterface& root_view_model) : - LLConversationItem(root_view_model) +LLConversationItemSession::LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : + LLConversationItem(uuid,root_view_model) { } @@ -99,8 +106,8 @@ LLConversationItemParticipant::LLConversationItemParticipant(std::string display { } -LLConversationItemParticipant::LLConversationItemParticipant(LLFolderViewModelInterface& root_view_model) : - LLConversationItem(root_view_model) +LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : + LLConversationItem(uuid,root_view_model) { } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index fc2c600364..1a63230e41 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -43,6 +43,7 @@ class LLConversationItem : public LLFolderViewModelItemCommon { public: LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); + LLConversationItem(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItem(LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItem() {} @@ -108,7 +109,7 @@ class LLConversationItemSession : public LLConversationItem { public: LLConversationItemSession(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); - LLConversationItemSession(LLFolderViewModelInterface& root_view_model); + LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItemSession() {} }; @@ -116,7 +117,7 @@ class LLConversationItemParticipant : public LLConversationItem { public: LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); - LLConversationItemParticipant(LLFolderViewModelInterface& root_view_model); + LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItemParticipant() {} }; diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index ee7f58b01f..f214003947 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -165,7 +165,7 @@ void LLIMConversation::buildParticipantList() if (mIsNearbyChat) { LLLocalSpeakerMgr* speaker_manager = LLLocalSpeakerMgr::getInstance(); - mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false); + mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), mConversationViewModel, true, false); } else { @@ -174,7 +174,7 @@ void LLIMConversation::buildParticipantList() if(!mIsP2PChat && mSessionID.notNull() && speaker_manager) { delete mParticipantList; // remove the old list and create a new one if the session id has changed - mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false); + mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), mConversationViewModel, true, false); } } updateHeaderAndToolbar(); diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index f21be94ee2..26151ad1be 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -33,6 +33,7 @@ #include "lltransientdockablefloater.h" #include "llviewercontrol.h" #include "lleventtimer.h" +#include "llconversationmodel.h" class LLPanelChatControlPanel; class LLChatEntry; @@ -104,6 +105,7 @@ protected: LLLayoutPanel* mParticipantListPanel; LLParticipantList* mParticipantList; LLUUID mSessionID; + LLConversationViewModel mConversationViewModel; LLChatHistory* mChatHistory; LLChatEntry* mInputEditor; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 47518a365f..552ae196dd 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -200,9 +200,11 @@ private: LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, + LLFolderViewModelInterface& root_view_model, bool use_context_menu/* = true*/, bool exclude_agent /*= true*/, bool can_toggle_icons /*= true*/) : + LLConversationItemSession(data_source->getSessionID(), root_view_model), mSpeakerMgr(data_source), mAvatarList(avatar_list), mParticipantListMenu(NULL), diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 53966c15fe..f8165aa292 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -31,13 +31,14 @@ #include "llevent.h" #include "llavatarlist.h" // for LLAvatarItemRecentSpeakerComparator #include "lllistcontextmenu.h" +#include "llconversationmodel.h" class LLSpeakerMgr; class LLAvatarList; class LLUICtrl; class LLAvalineUpdater; -class LLParticipantList +class LLParticipantList : public LLConversationItemSession { LOG_CLASS(LLParticipantList); public: @@ -46,6 +47,7 @@ public: LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, + LLFolderViewModelInterface& root_view_model, bool use_context_menu = true, bool exclude_agent = true, bool can_toggle_icons = true); -- cgit v1.2.3 From 0804ecb3551514d3321dfd4e3b17c3dab9693444 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 27 Aug 2012 17:41:37 +0300 Subject: removed debug messages --- indra/newview/llimconversation.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 2212673d3a..1f4522a96c 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -366,7 +366,6 @@ void LLIMConversation::processChatHistoryStyleUpdate() void LLIMConversation::updateCallBtnState(bool callIsActive) { -llwarns<<(this->getName())<<llendl; getChild<LLButton>("voice_call_btn")->setImageOverlay( callIsActive? getString("call_btn_stop") : getString("call_btn_start")); enableDisableCallBtn(); -- cgit v1.2.3 From a1a1410d25c3e4ff87e33344b416b7a827cdb1c2 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Mon, 27 Aug 2012 18:16:47 -0700 Subject: Skipping the realloc alignment test on Linux as the ll_aligned_malloc_16() function is not implemented to ensure alignment on Linux. --- indra/llcommon/llmemory.h | 2 ++ indra/llmath/tests/alignment_test.cpp | 4 ++++ 2 files changed, 6 insertions(+) (limited to 'indra') diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 9dd776ff57..08e2a2caa6 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -65,6 +65,8 @@ inline void* ll_aligned_realloc_16(void* ptr, size_t size) // returned hunk MUST #elif defined(LL_DARWIN) return realloc(ptr,size); // default osx malloc is 16 byte aligned. #else + // The realloc alignment test is skipped on Linux because the ll_aligned_realloc_16() + // function is not implemented to ensure alignment (see alignment_test.cpp) return realloc(ptr,size); // FIXME not guaranteed to be aligned. #endif } diff --git a/indra/llmath/tests/alignment_test.cpp b/indra/llmath/tests/alignment_test.cpp index ac0c45ae6f..49c668d737 100644 --- a/indra/llmath/tests/alignment_test.cpp +++ b/indra/llmath/tests/alignment_test.cpp @@ -78,8 +78,12 @@ void alignment_test_object_t::test<1>() align_ptr = ll_aligned_malloc_16(sizeof(MyVector4a)); ensure("ll_aligned_malloc_16 failed", is_aligned(align_ptr,16)); +#if !LL_LINUX + // Skipping realloc alignment test on Linux because the ll_aligned_realloc_16() + // function is not implemented to ensure alignment on Linux (see llmemory.h) align_ptr = ll_aligned_realloc_16(align_ptr,2*sizeof(MyVector4a)); ensure("ll_aligned_realloc_16 failed", is_aligned(align_ptr,16)); +#endif // LL_LINUX ll_aligned_free_16(align_ptr); -- cgit v1.2.3 From d4ee17e533d652e90989e60bcbc097c81e73d081 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Tue, 28 Aug 2012 14:48:32 +0300 Subject: CHUI-275 FIXED (Chat history viewer does not show entire user.txt IM log file) - Renamed LLLogChat::loadAllHistory to LLLogChat::loadChatHistory because it doesn't actually loads all history. Also added parameter to the function which is a flag whether to load all file's content or not. - Implemented displaying history by pages (as was decided on meeting page): Added showHistory() method to the LLFloaterConversationPreview which shows the chat history page by page starting from the last conversation (or may say starting from the last page). One page contains 100 entries. Added "More history..." button to display next page of history. --- indra/newview/app_settings/settings.xml | 11 +++ indra/newview/llfloaterconversationpreview.cpp | 90 +++++++++++++--------- indra/newview/llfloaterconversationpreview.h | 7 +- indra/newview/llimview.cpp | 2 +- indra/newview/lllogchat.cpp | 6 +- indra/newview/lllogchat.h | 4 +- indra/newview/llnearbychat.cpp | 2 +- .../xui/en/floater_conversation_preview.xml | 12 ++- 8 files changed, 88 insertions(+), 46 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 61bc58b1df..ab1ea6bdbc 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1639,6 +1639,17 @@ <key>Value</key> <string /> </map> + <key>ConversationHistoryPageSize</key> + <map> + <key>Comment</key> + <string>Chat history of conversation opened from call log is displayed by pages. So this is number of entries per page.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>100</integer> + </map> <key>NearbyChatIsNotTornOff</key> <map> <key>Comment</key> diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index e8554bb066..2c34029c5c 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -33,12 +33,15 @@ LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id) : LLFloater(session_id), mChatHistory(NULL), - mSessionID(session_id.asUUID()) + mSessionID(session_id.asUUID()), + mCurrentPage(0), + mPageSize(gSavedSettings.getS32("ConversationHistoryPageSize")) {} BOOL LLFloaterConversationPreview::postBuild() { mChatHistory = getChild<LLChatHistory>("chat_history"); + getChild<LLUICtrl>("more_history")->setCommitCallback(boost::bind(&LLFloaterConversationPreview::onMoreHistoryBtnClick, this)); const LLConversation* conv = LLConversationLog::instance().getConversation(mSessionID); if (conv) @@ -52,6 +55,11 @@ BOOL LLFloaterConversationPreview::postBuild() getChild<LLLineEditor>("description")->setValue(name); } + std::string file = conv->getHistoryFileName(); + LLLogChat::loadChatHistory(file, mMessages, true); + + mCurrentPage = mMessages.size() / mPageSize; + return LLFloater::postBuild(); } @@ -62,51 +70,59 @@ void LLFloaterConversationPreview::draw() void LLFloaterConversationPreview::onOpen(const LLSD& session_id) { - const LLConversation* conv = LLConversationLog::instance().getConversation(session_id); - if (!conv) + showHistory(); +} + +void LLFloaterConversationPreview::showHistory() +{ + if (!mMessages.size()) { return; } - std::list<LLSD> messages; - std::string file = conv->getHistoryFileName(); - LLLogChat::loadAllHistory(file, messages); - if (messages.size()) + mChatHistory->clear(); + + std::ostringstream message; + std::list<LLSD>::const_iterator iter = mMessages.begin(); + + int delta = 0; + if (mCurrentPage) { - std::ostringstream message; - std::list<LLSD>::const_iterator iter = messages.begin(); - for (; iter != messages.end(); ++iter) - { - LLSD msg = *iter; - - std::string time = msg["time"].asString(); - LLUUID from_id = msg["from_id"].asUUID(); - std::string from = msg["from"].asString(); - std::string message = msg["message"].asString(); - bool is_history = msg["is_history"].asBoolean(); - - LLChat chat; - chat.mFromID = from_id; - chat.mSessionID = session_id; - chat.mFromName = from; - chat.mTimeStr = time; - chat.mChatStyle = is_history ? CHAT_STYLE_HISTORY : chat.mChatStyle; - chat.mText = message; - - appendMessage(chat); - } + double num_of_pages = (double)mMessages.size() / mPageSize; + delta = (ceil(num_of_pages) - num_of_pages) * mPageSize; } -} -void LLFloaterConversationPreview::appendMessage(const LLChat& chat) -{ - if (!chat.mMuted) + std::advance(iter, (mCurrentPage * mPageSize) - delta); + + for (int msg_num = 0; (iter != mMessages.end() && msg_num < mPageSize); ++iter, ++msg_num) { - LLSD args; - args["use_plain_text_chat_history"] = true; - args["show_time"] = true; - args["show_names_for_p2p_conv"] = true; + LLSD msg = *iter; + + std::string time = msg["time"].asString(); + LLUUID from_id = msg["from_id"].asUUID(); + std::string from = msg["from"].asString(); + std::string message = msg["message"].asString(); + bool is_history = msg["is_history"].asBoolean(); + + LLChat chat; + chat.mFromID = from_id; + chat.mSessionID = mSessionID; + chat.mFromName = from; + chat.mTimeStr = time; + chat.mChatStyle = is_history ? CHAT_STYLE_HISTORY : chat.mChatStyle; + chat.mText = message; mChatHistory->appendMessage(chat); } + +} + +void LLFloaterConversationPreview::onMoreHistoryBtnClick() +{ + if (--mCurrentPage < 0) + { + return; + } + + showHistory(); } diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h index cfc7c34485..5105ef3702 100644 --- a/indra/newview/llfloaterconversationpreview.h +++ b/indra/newview/llfloaterconversationpreview.h @@ -42,10 +42,15 @@ public: virtual void onOpen(const LLSD& session_id); private: - void appendMessage(const LLChat& chat); + void onMoreHistoryBtnClick(); + void showHistory(); LLChatHistory* mChatHistory; LLUUID mSessionID; + int mCurrentPage; + int mPageSize; + + std::list<LLSD> mMessages; }; #endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */ diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 216db15c94..effcc9a826 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -263,7 +263,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& std::list<LLSD> chat_history; //involves parsing of a chat history - LLLogChat::loadAllHistory(mHistoryFileName, chat_history); + LLLogChat::loadChatHistory(mHistoryFileName, chat_history); addMessagesFromHistory(chat_history); } diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index ebb5912ace..073f5f00c5 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -387,7 +387,7 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line) } // static -void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& messages) +void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, bool load_all_history/*= false*/) { if (file_name.empty()) { @@ -412,8 +412,8 @@ void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& me S32 len; bool firstline = TRUE; - if (fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END)) - { //File is smaller than recall size. Get it all. + if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END)) + { //We need to load the whole historyFile or it's smaller than recall size, so get it all. firstline = FALSE; if (fseek(fptr, 0, SEEK_SET)) { diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index 27752452c9..95f83e64e5 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -50,12 +50,12 @@ public: const LLUUID& from_id, const std::string& line); - /** @deprecated @see loadAllHistory() */ + /** @deprecated @see loadChatHistory() */ static void loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata); - static void loadAllHistory(const std::string& file_name, std::list<LLSD>& messages); + static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, bool load_all_history = false); private: static std::string cleanFileName(std::string filename); }; diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a723748094..f1518fe825 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -262,7 +262,7 @@ void LLNearbyChat::loadHistory() do_not_log["do_not_log"] = true; std::list<LLSD> history; - LLLogChat::loadAllHistory("chat", history); + LLLogChat::loadChatHistory("chat", history); std::list<LLSD>::const_iterator it = history.begin(); while (it != history.end()) diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml index 27b744aefb..c837a0ee57 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -3,7 +3,7 @@ legacy_header_height="18" can_resize="true" default_tab_group="1" - height="361" + height="391" layout="topleft" min_height="243" min_width="234" @@ -50,4 +50,14 @@ left="5" width="390"> </chat_history> + <button + follows="bottom|right" + height="22" + layout="topleft" + name="more_history" + label="More history..." + right="-15" + top_pad="5" + width="100"> + </button> </floater> -- cgit v1.2.3 From 11e9f66e6217c22373f5d47518f6d1f9885f1793 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Tue, 28 Aug 2012 12:41:57 -0700 Subject: BUILDFIX: Correcting a linux build error. --- indra/newview/llfloaterconversationpreview.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index 2c34029c5c..ae6f1441eb 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -88,8 +88,13 @@ void LLFloaterConversationPreview::showHistory() int delta = 0; if (mCurrentPage) { - double num_of_pages = (double)mMessages.size() / mPageSize; - delta = (ceil(num_of_pages) - num_of_pages) * mPageSize; + // stinson 08/28/2012 : This operation could be simplified using integer math with the mod (%) operator. + // e.g. The following code should give the same output. + // int remainder = mMessages.size() % mPageSize; + // delta = (remainder == 0) ? 0 : (mPageSize - remainder); + // Though without examining further, the remainder might be a more appropriate value. + double num_of_pages = static_cast<double>(mMessages.size()) / static_cast<double>(mPageSize); + delta = static_cast<int>((ceil(num_of_pages) - num_of_pages) * static_cast<double>(mPageSize)); } std::advance(iter, (mCurrentPage * mPageSize) - delta); -- cgit v1.2.3 From 051bc99573d7c571cea0e2e1df332c1e5e97ff19 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Tue, 28 Aug 2012 20:08:17 +0300 Subject: CHUI-287 FIX IM toast panel is closed upon mouse up and doesn't pass the mouse click that activates "click to walk". --- indra/newview/lltoastimpanel.cpp | 4 ++-- indra/newview/lltoastimpanel.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index e0cb200ef5..75e6e3d13a 100644 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -104,9 +104,9 @@ LLToastIMPanel::~LLToastIMPanel() } //virtual -BOOL LLToastIMPanel::handleMouseDown(S32 x, S32 y, MASK mask) +BOOL LLToastIMPanel::handleMouseUp(S32 x, S32 y, MASK mask) { - if (LLPanel::handleMouseDown(x,y,mask) == FALSE) + if (LLPanel::handleMouseUp(x,y,mask) == FALSE) { mNotification->respond(mNotification->getResponseTemplate()); } diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index 279dd69bc7..3eb11fb3bc 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -52,7 +52,7 @@ public: LLToastIMPanel(LLToastIMPanel::Params &p); virtual ~LLToastIMPanel(); - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask); private: void showInspector(); -- cgit v1.2.3 From c4638d1dca7f3292d7ce48ddb2f5598f86282c88 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 28 Aug 2012 19:09:57 -0700 Subject: CHUI-280 : WIP : Implement update of LLConversationModel in LLParticipantList --- indra/llui/llfolderviewmodel.h | 9 +++ indra/newview/llconversationmodel.cpp | 47 ++++++++++++- indra/newview/llconversationmodel.h | 31 ++++++++- indra/newview/llparticipantlist.cpp | 125 ++++++++++++++++++++++------------ 4 files changed, 163 insertions(+), 49 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 41660c6e1e..16d9c86fd7 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -262,6 +262,15 @@ public: child->setParent(NULL); dirtyFilter(); } + + virtual void clearChildren() + { + // As this is cleaning the whole list of children wholesale, we do need to delete the pointed objects + // This is different and not equivalent to calling removeChild() on each child + std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); + mChildren.clear(); + dirtyFilter(); + } void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) { diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index a5c0244bd4..9b353809db 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -88,7 +88,8 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL // LLConversationItemSession::LLConversationItemSession(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : - LLConversationItem(display_name,uuid,root_view_model) + LLConversationItem(display_name,uuid,root_view_model), + mIsLoaded(false) { } @@ -97,12 +98,54 @@ LLConversationItemSession::LLConversationItemSession(const LLUUID& uuid, LLFolde { } +void LLConversationItemSession::addParticipant(LLConversationItemParticipant* item) +{ + addChild(item); + mIsLoaded = true; +} + +void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* item) +{ + removeChild(item); +} + +void LLConversationItemSession::clearParticipants() +{ + clearChildren(); + mIsLoaded = false; +} + +LLConversationItemParticipant* LLConversationItemSession::findParticipant(const LLUUID& participant_id) +{ + // This is *not* a general tree parsing algorithm. It assumes that a session contains only + // items (LLConversationItemParticipant) that have themselve no children. + LLConversationItemParticipant* participant = NULL; + child_list_t::iterator iter; + for (iter = mChildren.begin(); iter != mChildren.end(); iter++) + { + participant = dynamic_cast<LLConversationItemParticipant*>(*iter); + if (participant->hasSameValue(participant_id)) + { + break; + } + } + return (iter == mChildren.end() ? NULL : participant); +} + +void LLConversationItemSession::setParticipantIsMuted(const LLUUID& participant_id, bool is_muted) +{ + LLConversationItemParticipant* participant = findParticipant(participant_id); + participant->setIsMuted(is_muted); +} + // // LLConversationItemParticipant // LLConversationItemParticipant::LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : - LLConversationItem(display_name,uuid,root_view_model) + LLConversationItem(display_name,uuid,root_view_model), + mIsMuted(false), + mIsModerator(false) { } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 1a63230e41..484c0feb36 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -33,6 +33,8 @@ // Implementation of conversations list class LLConversationItem; +class LLConversationItemSession; +class LLConversationItemParticipant; typedef std::map<LLUUID, LLConversationItem*> conversations_items_map; typedef std::map<LLUUID, LLFolderViewItem*> conversations_widgets_map; @@ -100,9 +102,10 @@ public: // bool hasSameValues(std::string name, const LLUUID& uuid) { return ((name == mName) && (uuid == mUUID)); } bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } -private: - std::string mName; - const LLUUID mUUID; + +protected: + std::string mName; // Name of the session or the participant + LLUUID mUUID; // UUID of the session or the participant }; class LLConversationItemSession : public LLConversationItem @@ -111,6 +114,19 @@ public: LLConversationItemSession(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItemSession() {} + + void setSessionID(const LLUUID& session_id) { mUUID = session_id; } + void addParticipant(LLConversationItemParticipant* item); + void removeParticipant(LLConversationItemParticipant* item); + void clearParticipants(); + LLConversationItemParticipant* findParticipant(const LLUUID& participant_id); + + void setParticipantIsMuted(const LLUUID& participant_id, bool is_muted); + + bool isLoaded() { return mIsLoaded; } + +private: + bool mIsLoaded; // true if at least one participant has been added to the session, false otherwise }; class LLConversationItemParticipant : public LLConversationItem @@ -119,6 +135,15 @@ public: LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItemParticipant() {} + + bool isMuted() { return mIsMuted; } + bool isModerator() {return mIsModerator; } + void setIsMuted(bool is_muted) { mIsMuted = is_muted; } + void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; } + +private: + bool mIsMuted; // default is false + bool mIsModerator; // default is false }; // We don't want to ever filter conversations but we need to declare that class to create a conversation view model. diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 552ae196dd..6511b0a1a6 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -29,6 +29,8 @@ // common includes #include "lltrans.h" #include "llavataractions.h" +#include "llavatarnamecache.h" +#include "llavatarname.h" #include "llagent.h" #include "llimview.h" @@ -226,29 +228,34 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, mSpeakerMgr->addListener(mSpeakerClearListener, "clear"); mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator"); - mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData")); - LL_DEBUGS("SpeakingIndicator") << "Set session for speaking indicators: " << mSpeakerMgr->getSessionID() << LL_ENDL; - mAvatarList->setSessionID(mSpeakerMgr->getSessionID()); - mAvatarListDoubleClickConnection = mAvatarList->setItemDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, _1)); - mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2)); - // Set onAvatarListDoubleClicked as default on_return action. - mAvatarListReturnConnection = mAvatarList->setReturnCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); - - if (use_context_menu) - { - //mParticipantListMenu = new LLParticipantListMenu(*this); - //mAvatarList->setContextMenu(mParticipantListMenu); - mAvatarList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); - } - else + setSessionID(mSpeakerMgr->getSessionID()); + + if (mAvatarList) { - mAvatarList->setContextMenu(NULL); - } + mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData")); + LL_DEBUGS("SpeakingIndicator") << "Set session for speaking indicators: " << mSpeakerMgr->getSessionID() << LL_ENDL; + mAvatarList->setSessionID(mSpeakerMgr->getSessionID()); + mAvatarListDoubleClickConnection = mAvatarList->setItemDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, _1)); + mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2)); + // Set onAvatarListDoubleClicked as default on_return action. + mAvatarListReturnConnection = mAvatarList->setReturnCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); + + if (use_context_menu) + { + //mParticipantListMenu = new LLParticipantListMenu(*this); + //mAvatarList->setContextMenu(mParticipantListMenu); + mAvatarList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); + } + else + { + mAvatarList->setContextMenu(NULL); + } - if (use_context_menu && can_toggle_icons) - { - mAvatarList->setShowIcons("ParticipantListShowIcons"); - mAvatarListToggleIconsConnection = gSavedSettings.getControl("ParticipantListShowIcons")->getSignal()->connect(boost::bind(&LLAvatarList::toggleIcons, mAvatarList)); + if (use_context_menu && can_toggle_icons) + { + mAvatarList->setShowIcons("ParticipantListShowIcons"); + mAvatarListToggleIconsConnection = gSavedSettings.getControl("ParticipantListShowIcons")->getSignal()->connect(boost::bind(&LLAvatarList::toggleIcons, mAvatarList)); + } } //Lets fill avatarList with existing speakers @@ -396,6 +403,7 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) { + setParticipantIsMuted(speakerp->mID, speakerp->mModeratorMutedVoice); update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); } } @@ -415,30 +423,39 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) */ void LLParticipantList::onAvalineCallerFound(const LLUUID& participant_id) { - LLPanel* item = mAvatarList->getItemByValue(participant_id); - - if (NULL == item) + if (mAvatarList) { - LL_WARNS("Avaline") << "Something wrong. Unable to find item for: " << participant_id << LL_ENDL; - return; - } + LLPanel* item = mAvatarList->getItemByValue(participant_id); - if (typeid(*item) == typeid(LLAvalineListItem)) - { - LL_DEBUGS("Avaline") << "Avaline caller has already correct class type for: " << participant_id << LL_ENDL; - // item representing an Avaline caller has a correct type already. - return; - } + if (NULL == item) + { + LL_WARNS("Avaline") << "Something wrong. Unable to find item for: " << participant_id << LL_ENDL; + return; + } - LL_DEBUGS("Avaline") << "remove item from the list and re-add it: " << participant_id << LL_ENDL; + if (typeid(*item) == typeid(LLAvalineListItem)) + { + LL_DEBUGS("Avaline") << "Avaline caller has already correct class type for: " << participant_id << LL_ENDL; + // item representing an Avaline caller has a correct type already. + return; + } - // remove UUID from LLAvatarList::mIDs to be able add it again. - uuid_vec_t& ids = mAvatarList->getIDs(); - uuid_vec_t::iterator pos = std::find(ids.begin(), ids.end(), participant_id); - ids.erase(pos); + LL_DEBUGS("Avaline") << "remove item from the list and re-add it: " << participant_id << LL_ENDL; - // remove item directly - mAvatarList->removeItem(item); + // remove UUID from LLAvatarList::mIDs to be able add it again. + uuid_vec_t& ids = mAvatarList->getIDs(); + uuid_vec_t::iterator pos = std::find(ids.begin(), ids.end(), participant_id); + ids.erase(pos); + + // remove item directly + mAvatarList->removeItem(item); + } + + LLConversationItemParticipant* participant = findParticipant(participant_id); + if (participant) + { + removeParticipant(participant); + } // re-add avaline caller with a correct class instance. addAvatarIDExceptAgent(participant_id); @@ -562,6 +579,7 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event // update UI on confirmation of moderator mutes if (event->getValue().asString() == "voice") { + setParticipantIsMuted(speakerp->mID, speakerp->mModeratorMutedVoice); update_speaker_indicator(mAvatarList, speakerp->mID, speakerp->mModeratorMutedVoice); } return true; @@ -601,21 +619,40 @@ void LLParticipantList::sort() void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) { if (mExcludeAgent && gAgent.getID() == avatar_id) return; - if (mAvatarList->contains(avatar_id)) return; + if (mAvatarList && mAvatarList->contains(avatar_id)) return; bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(avatar_id); + LLConversationItemParticipant* participant = NULL; + if (is_avatar) { - mAvatarList->getIDs().push_back(avatar_id); - mAvatarList->setDirty(); + // Create a participant view model instance and add it to the linked list + LLAvatarName avatar_name; + bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name); + participant = new LLConversationItemParticipant(!has_name ? "Avatar" : avatar_name.mDisplayName , avatar_id, mRootViewModel); + if ( mAvatarList) + { + mAvatarList->getIDs().push_back(avatar_id); + mAvatarList->setDirty(); + } } else { std::string display_name = LLVoiceClient::getInstance()->getDisplayName(avatar_id); - mAvatarList->addAvalineItem(avatar_id, mSpeakerMgr->getSessionID(), display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name); + // Create a participant view model instance and add it to the linked list + participant = new LLConversationItemParticipant(display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name, avatar_id, mRootViewModel); + if ( mAvatarList) + { + mAvatarList->addAvalineItem(avatar_id, mSpeakerMgr->getSessionID(), display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name); + } mAvalineUpdater->watchAvalineCaller(avatar_id); } + + // *TODO : Merov : need to declare and bind a name update callback on that "participant" instance. See LLAvatarListItem::updateAvatarName() for pattern. + // For the moment, we'll get the correct name only if it's already in the name cache (see call to LLAvatarNameCache::get() here above) + addParticipant(participant); + adjustParticipant(avatar_id); } -- cgit v1.2.3 From ad070b9155e2fddfc746319003253248ceb0eba3 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 28 Aug 2012 23:13:10 -0700 Subject: CHUI-280 : Implement all LLConversationModel updates in LLParticipantList. Allow mAvatarList to be NULL. --- indra/newview/llconversationmodel.cpp | 31 +++++- indra/newview/llconversationmodel.h | 6 +- indra/newview/llparticipantlist.cpp | 193 +++++++++++++++++++--------------- 3 files changed, 137 insertions(+), 93 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 9b353809db..dbf5ac6e03 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -98,15 +98,24 @@ LLConversationItemSession::LLConversationItemSession(const LLUUID& uuid, LLFolde { } -void LLConversationItemSession::addParticipant(LLConversationItemParticipant* item) +void LLConversationItemSession::addParticipant(LLConversationItemParticipant* participant) { - addChild(item); + addChild(participant); mIsLoaded = true; } -void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* item) +void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* participant) { - removeChild(item); + removeChild(participant); +} + +void LLConversationItemSession::removeParticipant(const LLUUID& participant_id) +{ + LLConversationItemParticipant* participant = findParticipant(participant_id); + if (participant) + { + removeParticipant(participant); + } } void LLConversationItemSession::clearParticipants() @@ -135,7 +144,19 @@ LLConversationItemParticipant* LLConversationItemSession::findParticipant(const void LLConversationItemSession::setParticipantIsMuted(const LLUUID& participant_id, bool is_muted) { LLConversationItemParticipant* participant = findParticipant(participant_id); - participant->setIsMuted(is_muted); + if (participant) + { + participant->setIsMuted(is_muted); + } +} + +void LLConversationItemSession::setParticipantIsModerator(const LLUUID& participant_id, bool is_moderator) +{ + LLConversationItemParticipant* participant = findParticipant(participant_id); + if (participant) + { + participant->setIsModerator(is_moderator); + } } // diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 484c0feb36..aa79e5aeb0 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -116,12 +116,14 @@ public: virtual ~LLConversationItemSession() {} void setSessionID(const LLUUID& session_id) { mUUID = session_id; } - void addParticipant(LLConversationItemParticipant* item); - void removeParticipant(LLConversationItemParticipant* item); + void addParticipant(LLConversationItemParticipant* participant); + void removeParticipant(LLConversationItemParticipant* participant); + void removeParticipant(const LLUUID& participant_id); void clearParticipants(); LLConversationItemParticipant* findParticipant(const LLUUID& participant_id); void setParticipantIsMuted(const LLUUID& participant_id, bool is_muted); + void setParticipantIsModerator(const LLUUID& participant_id, bool is_moderator); bool isLoaded() { return mIsLoaded; } diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 6511b0a1a6..35c1a34a26 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -52,11 +52,14 @@ static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR; // helper function to update AvatarList Item's indicator in the voice participant list static void update_speaker_indicator(const LLAvatarList* const avatar_list, const LLUUID& avatar_uuid, bool is_muted) { - LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(avatar_list->getItemByValue(avatar_uuid)); - if (item) + if (avatar_list) { - LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("speaking_indicator"); - indicator->setIsMuted(is_muted); + LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(avatar_list->getItemByValue(avatar_uuid)); + if (item) + { + LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("speaking_indicator"); + indicator->setIsMuted(is_muted); + } } } @@ -281,10 +284,13 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLParticipantList::~LLParticipantList() { - mAvatarListDoubleClickConnection.disconnect(); - mAvatarListRefreshConnection.disconnect(); - mAvatarListReturnConnection.disconnect(); - mAvatarListToggleIconsConnection.disconnect(); + if (mAvatarList) + { + mAvatarListDoubleClickConnection.disconnect(); + mAvatarListRefreshConnection.disconnect(); + mAvatarListReturnConnection.disconnect(); + mAvatarListToggleIconsConnection.disconnect(); + } // It is possible Participant List will be re-created from LLCallFloater::onCurrentChannelChanged() // See ticket EXT-3427 @@ -300,16 +306,22 @@ LLParticipantList::~LLParticipantList() mParticipantListMenu = NULL; } - mAvatarList->setContextMenu(NULL); - mAvatarList->setComparator(NULL); + if (mAvatarList) + { + mAvatarList->setContextMenu(NULL); + mAvatarList->setComparator(NULL); + } delete mAvalineUpdater; } void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible) { - mAvatarList->setSpeakingIndicatorsVisible(visible); -}; + if (mAvatarList) + { + mAvatarList->setSpeakingIndicatorsVisible(visible); + } +} void LLParticipantList::onAvatarListDoubleClicked(LLUICtrl* ctrl) { @@ -330,82 +342,81 @@ void LLParticipantList::onAvatarListDoubleClicked(LLUICtrl* ctrl) void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) { LLAvatarList* list = dynamic_cast<LLAvatarList*>(ctrl); - if (list) + const std::string moderator_indicator(LLTrans::getString("IM_moderator_label")); + const std::size_t moderator_indicator_len = moderator_indicator.length(); + + // Firstly remove moderators indicator + std::set<LLUUID>::const_iterator + moderator_list_it = mModeratorToRemoveList.begin(), + moderator_list_end = mModeratorToRemoveList.end(); + for (;moderator_list_it != moderator_list_end; ++moderator_list_it) { - const std::string moderator_indicator(LLTrans::getString("IM_moderator_label")); - const std::size_t moderator_indicator_len = moderator_indicator.length(); - - // Firstly remove moderators indicator - std::set<LLUUID>::const_iterator - moderator_list_it = mModeratorToRemoveList.begin(), - moderator_list_end = mModeratorToRemoveList.end(); - for (;moderator_list_it != moderator_list_end; ++moderator_list_it) + LLAvatarListItem* item = (list ? dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it)) : NULL); + if ( item ) { - LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it)); - if ( item ) + std::string name = item->getAvatarName(); + std::string tooltip = item->getAvatarToolTip(); + size_t found = name.find(moderator_indicator); + if (found != std::string::npos) { - std::string name = item->getAvatarName(); - std::string tooltip = item->getAvatarToolTip(); - size_t found = name.find(moderator_indicator); - if (found != std::string::npos) - { - name.erase(found, moderator_indicator_len); - item->setAvatarName(name); - } - found = tooltip.find(moderator_indicator); - if (found != tooltip.npos) - { - tooltip.erase(found, moderator_indicator_len); - item->setAvatarToolTip(tooltip); - } + name.erase(found, moderator_indicator_len); + item->setAvatarName(name); + } + found = tooltip.find(moderator_indicator); + if (found != tooltip.npos) + { + tooltip.erase(found, moderator_indicator_len); + item->setAvatarToolTip(tooltip); } } + setParticipantIsModerator(*moderator_list_it,false); + } - mModeratorToRemoveList.clear(); + mModeratorToRemoveList.clear(); - // Add moderators indicator - moderator_list_it = mModeratorList.begin(); - moderator_list_end = mModeratorList.end(); - for (;moderator_list_it != moderator_list_end; ++moderator_list_it) + // Add moderators indicator + moderator_list_it = mModeratorList.begin(); + moderator_list_end = mModeratorList.end(); + for (;moderator_list_it != moderator_list_end; ++moderator_list_it) + { + LLAvatarListItem* item = (list ? dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it)) : NULL); + if ( item ) { - LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it)); - if ( item ) + std::string name = item->getAvatarName(); + std::string tooltip = item->getAvatarToolTip(); + size_t found = name.find(moderator_indicator); + if (found == std::string::npos) { - std::string name = item->getAvatarName(); - std::string tooltip = item->getAvatarToolTip(); - size_t found = name.find(moderator_indicator); - if (found == std::string::npos) - { - name += " "; - name += moderator_indicator; - item->setAvatarName(name); - } - found = tooltip.find(moderator_indicator); - if (found == std::string::npos) - { - tooltip += " "; - tooltip += moderator_indicator; - item->setAvatarToolTip(tooltip); - } + name += " "; + name += moderator_indicator; + item->setAvatarName(name); + } + found = tooltip.find(moderator_indicator); + if (found == std::string::npos) + { + tooltip += " "; + tooltip += moderator_indicator; + item->setAvatarToolTip(tooltip); } } + setParticipantIsModerator(*moderator_list_it,true); + } - // update voice mute state of all items. See EXT-7235 - LLSpeakerMgr::speaker_list_t speaker_list; + // update voice mute state of all items. See EXT-7235 + LLSpeakerMgr::speaker_list_t speaker_list; - // Use also participants which are not in voice session now (the second arg is TRUE). - // They can already have mModeratorMutedVoice set from the previous voice session - // and LLSpeakerVoiceModerationEvent will not be sent when speaker manager is updated next time. - mSpeakerMgr->getSpeakerList(&speaker_list, TRUE); - for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++) - { - const LLPointer<LLSpeaker>& speakerp = *it; + // Use also participants which are not in voice session now (the second arg is TRUE). + // They can already have mModeratorMutedVoice set from the previous voice session + // and LLSpeakerVoiceModerationEvent will not be sent when speaker manager is updated next time. + mSpeakerMgr->getSpeakerList(&speaker_list, TRUE); + for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++) + { + const LLPointer<LLSpeaker>& speakerp = *it; - if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) - { - setParticipantIsMuted(speakerp->mID, speakerp->mModeratorMutedVoice); - update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); - } + if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) + { + setParticipantIsMuted(speakerp->mID, speakerp->mModeratorMutedVoice); + update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); } } } @@ -506,7 +517,7 @@ bool LLParticipantList::isHovered() { S32 x, y; LLUI::getMousePositionScreen(&x, &y); - return mAvatarList->calcScreenRect().pointInRect(x, y); + return (mAvatarList ? mAvatarList->calcScreenRect().pointInRect(x, y) : false); } bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) @@ -525,21 +536,30 @@ bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, co bool LLParticipantList::onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) { - uuid_vec_t& group_members = mAvatarList->getIDs(); - uuid_vec_t::iterator pos = std::find(group_members.begin(), group_members.end(), event->getValue().asUUID()); - if(pos != group_members.end()) + LLUUID avatar_id = event->getValue().asUUID(); + if (mAvatarList) { - group_members.erase(pos); - mAvatarList->setDirty(); + uuid_vec_t& group_members = mAvatarList->getIDs(); + uuid_vec_t::iterator pos = std::find(group_members.begin(), group_members.end(), avatar_id); + if(pos != group_members.end()) + { + group_members.erase(pos); + mAvatarList->setDirty(); + } } + removeParticipant(avatar_id); return true; } bool LLParticipantList::onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) { - uuid_vec_t& group_members = mAvatarList->getIDs(); - group_members.clear(); - mAvatarList->setDirty(); + if (mAvatarList) + { + uuid_vec_t& group_members = mAvatarList->getIDs(); + group_members.clear(); + mAvatarList->setDirty(); + } + clearParticipants(); return true; } @@ -587,6 +607,7 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event void LLParticipantList::sort() { + // *TODO : Merov : Need to plan for sort() for LLConversationModel if ( !mAvatarList ) return; @@ -631,7 +652,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) LLAvatarName avatar_name; bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name); participant = new LLConversationItemParticipant(!has_name ? "Avatar" : avatar_name.mDisplayName , avatar_id, mRootViewModel); - if ( mAvatarList) + if (mAvatarList) { mAvatarList->getIDs().push_back(avatar_id); mAvatarList->setDirty(); @@ -642,7 +663,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) std::string display_name = LLVoiceClient::getInstance()->getDisplayName(avatar_id); // Create a participant view model instance and add it to the linked list participant = new LLConversationItemParticipant(display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name, avatar_id, mRootViewModel); - if ( mAvatarList) + if (mAvatarList) { mAvatarList->addAvalineItem(avatar_id, mSpeakerMgr->getSessionID(), display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name); } @@ -808,7 +829,7 @@ void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata, LL_WARNS("Speakers") << "Speaker " << speaker_id << " not found" << llendl; return; } - LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(mParent.mAvatarList->getItemByValue(speaker_id)); + LLAvatarListItem* item = (mParent.mAvatarList ? dynamic_cast<LLAvatarListItem*>(mParent.mAvatarList->getItemByValue(speaker_id)) : NULL); if (NULL == item) return; name = item->getAvatarName(); -- cgit v1.2.3 From ca7abc4c3be9310f4e5fec00b7d6ffadaba58ff0 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 29 Aug 2012 10:07:55 -0700 Subject: CHUI-280 : Add print out debug methods --- indra/newview/llconversationmodel.cpp | 16 ++++++++++++++++ indra/newview/llconversationmodel.h | 4 ++++ 2 files changed, 20 insertions(+) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index dbf5ac6e03..d7f9093a4a 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -159,6 +159,18 @@ void LLConversationItemSession::setParticipantIsModerator(const LLUUID& particip } } +void LLConversationItemSession::dumpDebugData() +{ + llinfos << "Merov debug : session, uuid = " << mUUID << ", name = " << mName << ", is loaded = " << mIsLoaded << llendl; + LLConversationItemParticipant* participant = NULL; + child_list_t::iterator iter; + for (iter = mChildren.begin(); iter != mChildren.end(); iter++) + { + participant = dynamic_cast<LLConversationItemParticipant*>(*iter); + participant->dumpDebugData(); + } +} + // // LLConversationItemParticipant // @@ -175,4 +187,8 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, { } +void LLConversationItemParticipant::dumpDebugData() +{ + llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; +} // EOF diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index aa79e5aeb0..af3756c45d 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -127,6 +127,8 @@ public: bool isLoaded() { return mIsLoaded; } + void dumpDebugData(); + private: bool mIsLoaded; // true if at least one participant has been added to the session, false otherwise }; @@ -143,6 +145,8 @@ public: void setIsMuted(bool is_muted) { mIsMuted = is_muted; } void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; } + void dumpDebugData(); + private: bool mIsMuted; // default is false bool mIsModerator; // default is false -- cgit v1.2.3 From 9ff67f4a040fae53f28aa981309bce2356df1445 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 29 Aug 2012 18:27:21 -0700 Subject: CHUI-285 : WIP : Get the conversation floater to use the same LLParticipantList as the IM and call dialog --- indra/newview/llconversationmodel.h | 4 ++-- indra/newview/llimfloatercontainer.cpp | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index af3756c45d..1a2e09dfab 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -59,8 +59,8 @@ public: virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } virtual std::string getLabelSuffix() const { return LLStringUtil::null; } - virtual BOOL isItemRenameable() const { return FALSE; } - virtual BOOL renameItem(const std::string& new_name) { return FALSE; } + virtual BOOL isItemRenameable() const { return TRUE; } + virtual BOOL renameItem(const std::string& new_name) { mName = new_name; return TRUE; } virtual BOOL isItemMovable( void ) const { return FALSE; } virtual BOOL isItemRemovable( void ) const { return FALSE; } virtual BOOL isItemInTrash( void) const { return FALSE; } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index a3f5e357c9..55cbf0b266 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -456,7 +456,9 @@ void LLIMFloaterContainer::repositioningWidgets() // CHUI-137 : Temporary implementation of conversations list void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) { - std::string display_name = uuid.isNull()? LLTrans::getString("NearbyChatTitle") : LLIMModel::instance().getName(uuid); + bool is_nearby_chat = uuid.isNull(); + + std::string display_name = is_nearby_chat ? LLTrans::getString("NearbyChatTitle") : LLIMModel::instance().getName(uuid); // Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do) // Note: this happens often, when reattaching a torn off conversation for instance @@ -470,8 +472,21 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) // and nothing wrong will happen removing it if it doesn't exist removeConversationListItem(uuid,false); - // Create a conversation item - LLConversationItem* item = new LLConversationItemSession(display_name, uuid, getRootViewModel()); + // Create a conversation session model + LLConversationItem* item = NULL; + LLSpeakerMgr* speaker_manager = (is_nearby_chat ? (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()) : LLIMModel::getInstance()->getSpeakerManager(uuid)); + if (speaker_manager) + { + item = new LLParticipantList(speaker_manager, NULL, getRootViewModel(), true, false); + } + if (!item) + { + llinfos << "Merov debug : Couldn't create conversation session item : " << display_name << llendl; + return; + } + // *TODO: Should we flag LLConversationItemSession with a mIsNearbyChat? + item->renameItem(display_name); + mConversationsItems[uuid] = item; // Create a widget from it -- cgit v1.2.3 From be61b5be2f4089e12ca25ca1ece13bd0fdaea543 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 29 Aug 2012 19:18:25 -0700 Subject: CHUI-305: Problem: The 'resident picker' had multiple parents and due to the design of the resident picker it can have only one parent. Having multiple parents caused both parents to fight for depth ordering...which caused the flickering. Resolution: Now multiple 'resident pickers' can exist and they are coupled to the floater that spawned then. Meaning that when the parent floater closes, the 'resident picker' floater will also close. In addition, a shadow frustum eminates from the button that opened the 'resident picker'. --- indra/llui/llfloater.cpp | 7 +++ indra/newview/llavataractions.cpp | 10 +++- indra/newview/llavataractions.h | 3 +- indra/newview/llfloateravatarpicker.cpp | 79 ++++++++++++++++++++++++++++++-- indra/newview/llfloateravatarpicker.h | 9 +++- indra/newview/llfloatercolorpicker.cpp | 2 +- indra/newview/llfloatergodtools.cpp | 6 ++- indra/newview/llfloaterland.cpp | 12 +++-- indra/newview/llfloaterregioninfo.cpp | 26 +++++++++-- indra/newview/llfloaterreporter.cpp | 7 ++- indra/newview/llfloatersellland.cpp | 3 +- indra/newview/llimfloater.cpp | 6 ++- indra/newview/llimfloatercontainer.cpp | 4 +- indra/newview/llinventorypanel.cpp | 2 +- indra/newview/llpanelblockedlist.cpp | 26 +++++++++-- indra/newview/llpanelblockedlist.h | 2 + indra/newview/llpanelgroupinvite.cpp | 6 ++- indra/newview/llpanelmaininventory.cpp | 2 +- indra/newview/llpanelobjectinventory.cpp | 2 +- indra/newview/llpanelpeople.cpp | 20 +++++++- indra/newview/llpanelpeople.h | 3 ++ indra/newview/llsidepanelinventory.cpp | 2 +- 22 files changed, 201 insertions(+), 38 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 8145d6d347..52812dc050 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -713,6 +713,13 @@ void LLFloater::closeFloater(bool app_quitting) make_ui_sound("UISndWindowClose"); } + //If floater is a dependent, remove it from parent (dependee) + LLFloater* dependee = mDependeeHandle.get(); + if (dependee) + { + dependee->removeDependentFloater(this); + } + // now close dependent floater for(handle_set_iter_t dependent_it = mDependents.begin(); dependent_it != mDependents.end(); ) diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 93e8b9ca40..9a0c517ee0 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -744,12 +744,13 @@ std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs() } //static -void LLAvatarActions::shareWithAvatars() +void LLAvatarActions::shareWithAvatars(LLPanel * panel) { using namespace action_give_inventory; + LLFloater* root_floater = gFloaterView->getParentFloater(panel); LLFloaterAvatarPicker* picker = - LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2), TRUE, FALSE); + LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2), TRUE, FALSE, FALSE, root_floater->getName()); if (!picker) { return; @@ -757,6 +758,11 @@ void LLAvatarActions::shareWithAvatars() picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable)); picker->openFriendsTab(); + + if (root_floater) + { + root_floater->addDependentFloater(picker); + } LLNotificationsUtil::add("ShareNotification"); } diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 259e87c336..9d9ce966b5 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -37,6 +37,7 @@ class LLAvatarName; class LLInventoryPanel; class LLFloater; +class LLPanel; /** * Friend-related actions (add, remove, offer teleport, etc) @@ -117,7 +118,7 @@ public: /** * Share items with the picked avatars. */ - static void shareWithAvatars(); + static void shareWithAvatars(LLPanel * panel); /** * Block/unblock the avatar. diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 47acdf7057..4ac022e350 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -49,6 +49,8 @@ #include "llscrolllistcell.h" #include "lltabcontainer.h" #include "lluictrlfactory.h" +#include "llfocusmgr.h" +#include "lldraghandle.h" #include "message.h" //#include "llsdserialize.h" @@ -56,14 +58,20 @@ //put it back as a member once the legacy path is out? static std::map<LLUUID, LLAvatarName> sAvatarNameMap; +const F32 CONTEXT_CONE_IN_ALPHA = 0.0f; +const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; +const F32 CONTEXT_FADE_TIME = 0.08f; + LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback, BOOL allow_multiple, BOOL closeOnSelect, - BOOL skip_agent) + BOOL skip_agent, + const std::string& name, + LLView * frustumOrigin) { // *TODO: Use a key to allow this not to be an effective singleton LLFloaterAvatarPicker* floater = - LLFloaterReg::showTypedInstance<LLFloaterAvatarPicker>("avatar_picker"); + LLFloaterReg::showTypedInstance<LLFloaterAvatarPicker>("avatar_picker", LLSD(name)); if (!floater) { llwarns << "Cannot instantiate avatar picker" << llendl; @@ -85,6 +93,11 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback, floater->getChild<LLButton>("cancel_btn")->setLabel(close_string); } + if(frustumOrigin) + { + floater->mFrustumOrigin = frustumOrigin->getHandle(); + } + return floater; } @@ -93,7 +106,8 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key) : LLFloater(key), mNumResultsReturned(0), mNearMeListComplete(FALSE), - mCloseOnSelect(FALSE) + mCloseOnSelect(FALSE), + mContextConeOpacity ( 0.f ) { mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this)); } @@ -340,8 +354,67 @@ void LLFloaterAvatarPicker::populateFriend() friends_scroller->sortByColumnIndex(0, TRUE); } +void LLFloaterAvatarPicker::drawFrustum() +{ + if(mFrustumOrigin.get()) + { + LLView * frustumOrigin = mFrustumOrigin.get(); + LLRect origin_rect; + frustumOrigin->localRectToOtherView(frustumOrigin->getLocalRect(), &origin_rect, this); + // draw context cone connecting color picker with color swatch in parent floater + LLRect local_rect = getLocalRect(); + if (hasFocus() && frustumOrigin->isInVisibleChain() && mContextConeOpacity > 0.001f) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLEnable(GL_CULL_FACE); + gGL.begin(LLRender::QUADS); + { + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop); + gGL.vertex2i(origin_rect.mRight, origin_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mRight, local_rect.mTop); + gGL.vertex2i(local_rect.mLeft, local_rect.mTop); + + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mTop); + gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom); + gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop); + + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mRight, local_rect.mBottom); + gGL.vertex2i(local_rect.mRight, local_rect.mTop); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(origin_rect.mRight, origin_rect.mTop); + gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom); + + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); + gGL.vertex2i(local_rect.mRight, local_rect.mBottom); + gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom); + gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom); + } + gGL.end(); + } + + if (gFocusMgr.childHasMouseCapture(getDragHandle())) + { + mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + } + else + { + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + } + } +} + void LLFloaterAvatarPicker::draw() { + drawFrustum(); + // sometimes it is hard to determine when Select/Ok button should be disabled (see LLAvatarActions::shareWithAvatars). // lets check this via mOkButtonValidateSignal callback periodically. static LLFrameTimer timer; diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index 7067cd7b3e..46b685ad02 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -34,7 +34,7 @@ class LLAvatarName; class LLScrollListCtrl; -class LLFloaterAvatarPicker : public LLFloater +class LLFloaterAvatarPicker :public LLFloater { public: typedef boost::signals2::signal<bool(const uuid_vec_t&), boost_boolean_combiner> validate_signal_t; @@ -46,7 +46,9 @@ public: static LLFloaterAvatarPicker* show(select_callback_t callback, BOOL allow_multiple = FALSE, BOOL closeOnSelect = FALSE, - BOOL skip_agent = FALSE); + BOOL skip_agent = FALSE, + const std::string& name = "", + LLView * frustumOrigin = NULL); LLFloaterAvatarPicker(const LLSD& key); virtual ~LLFloaterAvatarPicker(); @@ -86,6 +88,7 @@ private: void setAllowMultiple(BOOL allow_multiple); LLScrollListCtrl* getActiveList(); + void drawFrustum(); virtual void draw(); virtual BOOL handleKeyHere(KEY key, MASK mask); @@ -94,6 +97,8 @@ private: BOOL mNearMeListComplete; BOOL mCloseOnSelect; BOOL mExcludeAgentFromSearchResults; + LLHandle <LLView> mFrustumOrigin; + F32 mContextConeOpacity; validate_signal_t mOkButtonValidateSignal; select_callback_t mSelectionCallback; diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 05d73c2416..1cebdcffca 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -486,7 +486,7 @@ void LLFloaterColorPicker::draw() mSwatch->localRectToOtherView(mSwatch->getLocalRect(), &swatch_rect, this); // draw context cone connecting color picker with color swatch in parent floater LLRect local_rect = getLocalRect(); - if (gFocusMgr.childHasKeyboardFocus(this) && mSwatch->isInVisibleChain() && mContextConeOpacity > 0.001f) + if (hasFocus() && mSwatch->isInVisibleChain() && mContextConeOpacity > 0.001f) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLGLEnable(GL_CULL_FACE); diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index fb905eae11..51745fb191 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -1123,11 +1123,13 @@ bool LLPanelObjectTools::callbackSimWideDeletes( const LLSD& notification, const void LLPanelObjectTools::onClickSet() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelObjectTools::callbackAvatarID, this, _1,_2)); + LLView * button = getChildView("Set Target"); + LLFloater * root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelObjectTools::callbackAvatarID, this, _1,_2), FALSE, FALSE, FALSE, root_floater->getName(), button); // grandparent is a floater, which can have a dependent if (picker) { - gFloaterView->getParentFloater(this)->addDependentFloater(picker); + root_floater->addDependentFloater(picker); } } diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 55f3d548ec..64336b5cf7 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2733,11 +2733,13 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata) void LLPanelLandAccess::onClickAddAccess() { + LLView * button = getChildView("add_allowed"); + LLFloater * root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( - boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1)); + boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1), FALSE, FALSE, FALSE, root_floater->getName(), button); if (picker) { - gFloaterView->getParentFloater(this)->addDependentFloater(picker); + root_floater->addDependentFloater(picker); } } @@ -2782,11 +2784,13 @@ void LLPanelLandAccess::onClickRemoveAccess(void* data) // static void LLPanelLandAccess::onClickAddBanned() { + LLView * button = getChildView("add_banned"); + LLFloater * root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( - boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1)); + boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1), FALSE, FALSE, FALSE, root_floater->getName(), button); if (picker) { - gFloaterView->getParentFloater(this)->addDependentFloater(picker); + root_floater->addDependentFloater(picker); } } diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index fe29bb38c7..4aebd9a4f4 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -648,7 +648,7 @@ void LLPanelRegionGeneralInfo::onClickKick() // this depends on the grandparent view being a floater // in order to set up floater dependency LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), FALSE, TRUE); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), FALSE, TRUE, FALSE, parent_floater->getName()); if (child_floater) { parent_floater->addDependentFloater(child_floater); @@ -924,7 +924,12 @@ BOOL LLPanelRegionDebugInfo::sendUpdate() void LLPanelRegionDebugInfo::onClickChooseAvatar() { - LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, this, _1, _2), FALSE, TRUE); + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + LLFloater * child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, this, _1, _2), FALSE, TRUE, FALSE, parent_floater->getName()); + if (child_floater) + { + parent_floater->addDependentFloater(child_floater); + } } @@ -1471,7 +1476,7 @@ void LLPanelEstateInfo::onClickKickUser() // this depends on the grandparent view being a floater // in order to set up floater dependency LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1), FALSE, TRUE); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1), FALSE, TRUE, FALSE, parent_floater->getName()); if (child_floater) { parent_floater->addDependentFloater(child_floater); @@ -1646,8 +1651,21 @@ bool LLPanelEstateInfo::accessAddCore2(const LLSD& notification, const LLSD& res } LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo(notification["payload"]); + //Get parent floater name + LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate(); + LLFloater* parent_floater = panel ? gFloaterView->getParentFloater(panel) : NULL; + const std::string& parent_floater_name = parent_floater ? parent_floater->getName() : ""; + // avatar picker yes multi-select, yes close-on-select - LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, (void*)change_info), TRUE, TRUE); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, (void*)change_info), + TRUE, TRUE, FALSE, parent_floater_name); + + //Allows the closed parent floater to close the child floater (avatar picker) + if (child_floater) + { + parent_floater->addDependentFloater(child_floater); + } + return false; } diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 3ec1e372eb..206bcb2c7e 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -285,10 +285,13 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id) void LLFloaterReporter::onClickSelectAbuser() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE ); + LLView * button = getChildView("select_abuser", TRUE); + + LLFloater * root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE, FALSE, root_floater->getName(), button); if (picker) { - gFloaterView->getParentFloater(this)->addDependentFloater(picker); + root_floater->addDependentFloater(picker); } } diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 64c0dfa023..2ac82c553b 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -392,7 +392,8 @@ void LLFloaterSellLandUI::onChangeValue(LLUICtrl *ctrl, void *userdata) void LLFloaterSellLandUI::doSelectAgent() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, this, _1, _2), FALSE, TRUE); + LLView * button = getChildView("sell_to_select_agent"); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, this, _1, _2), FALSE, TRUE, FALSE, this->getName(), button); // grandparent is a floater, in order to set up dependency if (picker) { diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 1c6445610f..732a204ddf 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -359,7 +359,9 @@ BOOL LLIMFloater::postBuild() void LLIMFloater::onAddButtonClicked() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE); + LLView * button = getChildView("toolbar_panel")->getChildView("add_btn"); + LLFloater* root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE, FALSE, root_floater->getName(), button); if (!picker) { return; @@ -367,7 +369,7 @@ void LLIMFloater::onAddButtonClicked() // Need to disable 'ok' button when selected users are already in conversation. picker->setOkBtnEnableCb(boost::bind(&LLIMFloater::canAddSelectedToChat, this, _1)); - LLFloater* root_floater = gFloaterView->getParentFloater(this); + if (root_floater) { root_floater->addDependentFloater(picker); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 4d0bd623f8..bfe4afe80b 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -415,8 +415,10 @@ void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) void LLIMFloaterContainer::onAddButtonClicked() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloaterContainer::onAvatarPicked, this, _1), TRUE, TRUE, TRUE); + LLView * button = getChildView("conversations_pane_buttons_expanded")->getChildView("add_btn"); LLFloater* root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloaterContainer::onAvatarPicked, this, _1), TRUE, TRUE, TRUE, root_floater->getName(), button); + if (picker && root_floater) { root_floater->addDependentFloater(picker); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 03dfada77c..2a84616ddf 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -147,7 +147,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLInventoryPanel::doCreate, this, _2)); mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2)); mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this)); - mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars)); + mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, this)); } diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index 35cda14f8d..8d03930699 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -66,10 +66,19 @@ LLPanelBlockedList::LLPanelBlockedList() mEnableCallbackRegistrar.add("Block.Check", boost::bind(&LLPanelBlockedList::isActionChecked, this, _2)); } +void LLPanelBlockedList::removePicker() +{ + if(mPicker.get()) + { + mPicker.get()->closeFloater(); + } +} + BOOL LLPanelBlockedList::postBuild() { mBlockedList = getChild<LLBlockList>("blocked"); mBlockedList->setCommitOnSelectionChange(TRUE); + this->setVisibleCallback(boost::bind(&LLPanelBlockedList::removePicker, this)); switch (gSavedSettings.getU32("BlockPeopleSortOrder")) { @@ -185,11 +194,18 @@ void LLPanelBlockedList::blockResidentByName() { const BOOL allow_multiple = FALSE; const BOOL close_on_select = TRUE; - /*LLFloaterAvatarPicker* picker = */LLFloaterAvatarPicker::show(boost::bind(&LLPanelBlockedList::callbackBlockPicked, this, _1, _2), allow_multiple, close_on_select); - - // *TODO: mantipov: should LLFloaterAvatarPicker be closed when panel is closed? - // old Floater dependency is not enable in panel - // addDependentFloater(picker); + + LLView * button = getChildView("plus_btn", TRUE); + LLFloater* root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker * picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelBlockedList::callbackBlockPicked, this, _1, _2), + allow_multiple, close_on_select, FALSE, root_floater->getName(), button); + + if (root_floater) + { + root_floater->addDependentFloater(picker); + } + + mPicker = picker->getHandle(); } void LLPanelBlockedList::blockObjectByName() diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h index 332349dfc0..07f0437656 100644 --- a/indra/newview/llpanelblockedlist.h +++ b/indra/newview/llpanelblockedlist.h @@ -61,6 +61,7 @@ private: E_SORT_BY_TYPE = 1, } ESortOrder; + void removePicker(); void updateButtons(); // UI callbacks @@ -78,6 +79,7 @@ private: private: LLBlockList* mBlockedList; + LLHandle<LLFloater> mPicker; }; //----------------------------------------------------------------------------- diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index 00dd206571..290e38ee1f 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -301,11 +301,13 @@ void LLPanelGroupInvite::impl::callbackClickAdd(void* userdata) //Soon the avatar picker will be embedded into this panel //instead of being it's own separate floater. But that is next week. //This will do for now. -jwolk May 10, 2006 + LLView * button = panelp->getChildView("add_button"); + LLFloater * root_floater = gFloaterView->getParentFloater(panelp); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( - boost::bind(impl::callbackAddUsers, _1, panelp->mImplementation), TRUE); + boost::bind(impl::callbackAddUsers, _1, panelp->mImplementation), TRUE, FALSE, FALSE, root_floater->getName(), button); if (picker) { - gFloaterView->getParentFloater(panelp)->addDependentFloater(picker); + root_floater->addDependentFloater(picker); } } } diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index eb3877da5a..35cb3d59c5 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -118,7 +118,7 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p) mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLPanelMainInventory::toggleFindOptions, this)); mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLPanelMainInventory::resetFilters, this)); mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2)); - mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars)); + mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, this)); mSavedFolderState = new LLSaveFolderState(); mSavedFolderState->setApply(FALSE); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 82956beb3d..de12826452 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1498,7 +1498,7 @@ LLPanelObjectInventory::LLPanelObjectInventory(const LLPanelObjectInventory::Par mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&do_nothing)); mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&do_nothing)); mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&do_nothing)); - mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars)); + mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, this)); } // Destroys the object diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 260de40eef..14045df42e 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -556,6 +556,15 @@ void LLPanelPeople::onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LL } } + +void LLPanelPeople::removePicker() +{ + if(mPicker.get()) + { + mPicker.get()->closeFloater(); + } +} + BOOL LLPanelPeople::postBuild() { getChild<LLFilterEditor>("nearby_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); @@ -571,6 +580,7 @@ BOOL LLPanelPeople::postBuild() LLPanel* friends_tab = getChild<LLPanel>(FRIENDS_TAB_NAME); // updater is active only if panel is visible to user. friends_tab->setVisibleCallback(boost::bind(&Updater::setActive, mFriendListUpdater, _2)); + friends_tab->setVisibleCallback(boost::bind(&LLPanelPeople::removePicker, this)); mOnlineFriendList = friends_tab->getChild<LLAvatarList>("avatars_online"); mAllFriendList = friends_tab->getChild<LLAvatarList>("avatars_all"); mOnlineFriendList->setNoItemsCommentText(getString("no_friends_online")); @@ -1079,8 +1089,12 @@ bool LLPanelPeople::isItemsFreeOfFriends(const uuid_vec_t& uuids) void LLPanelPeople::onAddFriendWizButtonClicked() { + LLPanel* cur_panel = mTabContainer->getCurrentPanel(); + LLView * button = cur_panel->getChildView("friends_add_btn", TRUE); + // Show add friend wizard. - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelPeople::onAvatarPicked, _1, _2), FALSE, TRUE); + LLFloater* root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelPeople::onAvatarPicked, _1, _2), FALSE, TRUE, FALSE, root_floater->getName(), button); if (!picker) { return; @@ -1088,11 +1102,13 @@ void LLPanelPeople::onAddFriendWizButtonClicked() // Need to disable 'ok' button when friend occurs in selection picker->setOkBtnEnableCb(boost::bind(&LLPanelPeople::isItemsFreeOfFriends, this, _1)); - LLFloater* root_floater = gFloaterView->getParentFloater(this); + if (root_floater) { root_floater->addDependentFloater(picker); } + + mPicker = picker->getHandle(); } void LLPanelPeople::onDeleteFriendButtonClicked() diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index da27f83074..4740964dee 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -68,6 +68,8 @@ private: E_SORT_BY_RECENT_SPEAKERS = 4, } ESortOrder; + void removePicker(); + // methods indirectly called by the updaters void updateFriendListHelpText(); void updateFriendList(); @@ -139,6 +141,7 @@ private: Updater* mNearbyListUpdater; Updater* mRecentListUpdater; Updater* mButtonsUpdater; + LLHandle< LLFloater > mPicker; }; #endif //LL_LLPANELPEOPLE_H diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index acb232c77f..8915bb2fef 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -448,7 +448,7 @@ void LLSidepanelInventory::onInfoButtonClicked() void LLSidepanelInventory::onShareButtonClicked() { - LLAvatarActions::shareWithAvatars(); + LLAvatarActions::shareWithAvatars(this); } void LLSidepanelInventory::onShopButtonClicked() -- cgit v1.2.3 From d67c295d8bb6cfd58655bf961dcf835157abb3e7 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 30 Aug 2012 16:20:27 -0700 Subject: CHUI-305: Minor changes after code review. Using templated findChild() instead of getChildView(). Also using settings.xml to store common custom variables. --- indra/newview/app_settings/settings.xml | 33 +++++++++++++++++++++++++++++++ indra/newview/llavataractions.cpp | 2 +- indra/newview/llavataractions.h | 4 ++-- indra/newview/llfloateravatarpicker.cpp | 35 ++++++++++++++++++--------------- indra/newview/llfloateravatarpicker.h | 3 +++ indra/newview/llfloatercolorpicker.cpp | 34 ++++++++++++++++++-------------- indra/newview/llfloatercolorpicker.h | 4 ++++ indra/newview/llfloatergodtools.cpp | 2 +- indra/newview/llfloaterland.cpp | 4 ++-- indra/newview/llfloaterreporter.cpp | 2 +- indra/newview/llfloatersellland.cpp | 2 +- indra/newview/llimfloater.cpp | 2 +- indra/newview/llimfloatercontainer.cpp | 2 +- indra/newview/llpanelblockedlist.cpp | 2 +- indra/newview/llpanelgroupinvite.cpp | 2 +- indra/newview/llpanelpeople.cpp | 2 +- 16 files changed, 91 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ab1ea6bdbc..b98fea7032 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1639,6 +1639,39 @@ <key>Value</key> <string /> </map> + <key>ContextConeInAlpha</key> + <map> + <key>Comment</key> + <string>Cone In Alpha</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.0</real> + </map> + <key>ContextConeOutAlpha</key> + <map> + <key>Comment</key> + <string>Cone Out Alpha</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.0</real> + </map> + <key>ContextConeFadeTime</key> + <map> + <key>Comment</key> + <string>Cone Fade Time</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>.08</real> + </map> <key>ConversationHistoryPageSize</key> <map> <key>Comment</key> diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 9a0c517ee0..42a0376774 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -744,7 +744,7 @@ std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs() } //static -void LLAvatarActions::shareWithAvatars(LLPanel * panel) +void LLAvatarActions::shareWithAvatars(LLView * panel) { using namespace action_give_inventory; diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 9d9ce966b5..473b9cecc3 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -37,7 +37,7 @@ class LLAvatarName; class LLInventoryPanel; class LLFloater; -class LLPanel; +class LLView; /** * Friend-related actions (add, remove, offer teleport, etc) @@ -118,7 +118,7 @@ public: /** * Share items with the picked avatars. */ - static void shareWithAvatars(LLPanel * panel); + static void shareWithAvatars(LLView * panel); /** * Block/unblock the avatar. diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 4ac022e350..3d6441553d 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -58,10 +58,6 @@ //put it back as a member once the legacy path is out? static std::map<LLUUID, LLAvatarName> sAvatarNameMap; -const F32 CONTEXT_CONE_IN_ALPHA = 0.0f; -const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; -const F32 CONTEXT_FADE_TIME = 0.08f; - LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback, BOOL allow_multiple, BOOL closeOnSelect, @@ -106,10 +102,17 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key) : LLFloater(key), mNumResultsReturned(0), mNearMeListComplete(FALSE), - mCloseOnSelect(FALSE), - mContextConeOpacity ( 0.f ) + mCloseOnSelect(FALSE),a + mContextConeOpacity (0.f), + mContextConeInAlpha(0.f), + mContextConeOutAlpha(0.f), + mContextConeFadeTime(0.f) { mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this)); + + mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha"); + mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha"); + mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime"); } BOOL LLFloaterAvatarPicker::postBuild() @@ -369,31 +372,31 @@ void LLFloaterAvatarPicker::drawFrustum() LLGLEnable(GL_CULL_FACE); gGL.begin(LLRender::QUADS); { - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop); gGL.vertex2i(origin_rect.mRight, origin_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); gGL.vertex2i(local_rect.mRight, local_rect.mTop); gGL.vertex2i(local_rect.mLeft, local_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); gGL.vertex2i(local_rect.mLeft, local_rect.mTop); gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom); gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); gGL.vertex2i(local_rect.mRight, local_rect.mBottom); gGL.vertex2i(local_rect.mRight, local_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(origin_rect.mRight, origin_rect.mTop); gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); gGL.vertex2i(local_rect.mRight, local_rect.mBottom); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom); gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom); } @@ -402,11 +405,11 @@ void LLFloaterAvatarPicker::drawFrustum() if (gFocusMgr.childHasMouseCapture(getDragHandle())) { - mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(mContextConeFadeTime)); } else { - mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime)); } } } diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index 46b685ad02..ed3e51c56f 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -99,6 +99,9 @@ private: BOOL mExcludeAgentFromSearchResults; LLHandle <LLView> mFrustumOrigin; F32 mContextConeOpacity; + F32 mContextConeInAlpha; + F32 mContextConeOutAlpha; + F32 mContextConeFadeTime; validate_signal_t mOkButtonValidateSignal; select_callback_t mSelectionCallback; diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 1cebdcffca..3c230bc58c 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -62,10 +62,6 @@ #include <sstream> #include <iomanip> -const F32 CONTEXT_CONE_IN_ALPHA = 0.0f; -const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; -const F32 CONTEXT_FADE_TIME = 0.08f; - ////////////////////////////////////////////////////////////////////////////// // // Class LLFloaterColorPicker @@ -105,7 +101,10 @@ LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show mSwatch ( swatch ), mActive ( TRUE ), mCanApplyImmediately ( show_apply_immediate ), - mContextConeOpacity ( 0.f ) + mContextConeOpacity ( 0.f ), + mContextConeInAlpha ( 0.f ), + mContextConeOutAlpha ( 0.f ), + mContextConeFadeTime ( 0.f ) { buildFromFile ( "floater_color_picker.xml"); @@ -117,6 +116,10 @@ LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show mApplyImmediateCheck->setEnabled(FALSE); mApplyImmediateCheck->set(FALSE); } + + mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha"); + mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha"); + mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime"); } LLFloaterColorPicker::~LLFloaterColorPicker() @@ -492,31 +495,31 @@ void LLFloaterColorPicker::draw() LLGLEnable(GL_CULL_FACE); gGL.begin(LLRender::QUADS); { - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop); gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); gGL.vertex2i(local_rect.mRight, local_rect.mTop); gGL.vertex2i(local_rect.mLeft, local_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); gGL.vertex2i(local_rect.mLeft, local_rect.mTop); gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom); gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); gGL.vertex2i(local_rect.mRight, local_rect.mBottom); gGL.vertex2i(local_rect.mRight, local_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop); gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity); gGL.vertex2i(local_rect.mLeft, local_rect.mBottom); gGL.vertex2i(local_rect.mRight, local_rect.mBottom); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom); gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom); } @@ -525,11 +528,12 @@ void LLFloaterColorPicker::draw() if (gFocusMgr.childHasMouseCapture(getDragHandle())) { - mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), + LLCriticalDamp::getInterpolant(mContextConeFadeTime)); } else { - mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime)); } mPipetteBtn->setToggleState(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()); diff --git a/indra/newview/llfloatercolorpicker.h b/indra/newview/llfloatercolorpicker.h index 8e387c4f7c..bab0617712 100644 --- a/indra/newview/llfloatercolorpicker.h +++ b/indra/newview/llfloatercolorpicker.h @@ -189,6 +189,10 @@ class LLFloaterColorPicker LLButton* mPipetteBtn; F32 mContextConeOpacity; + F32 mContextConeInAlpha; + F32 mContextConeOutAlpha; + F32 mContextConeFadeTime; + }; #endif // LL_LLFLOATERCOLORPICKER_H diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index 51745fb191..38abdcc830 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -1123,7 +1123,7 @@ bool LLPanelObjectTools::callbackSimWideDeletes( const LLSD& notification, const void LLPanelObjectTools::onClickSet() { - LLView * button = getChildView("Set Target"); + LLView * button = findChild<LLButton>("Set Target"); LLFloater * root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelObjectTools::callbackAvatarID, this, _1,_2), FALSE, FALSE, FALSE, root_floater->getName(), button); // grandparent is a floater, which can have a dependent diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 64336b5cf7..4fc6684e8e 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2733,7 +2733,7 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata) void LLPanelLandAccess::onClickAddAccess() { - LLView * button = getChildView("add_allowed"); + LLView * button = findChild<LLButton>("add_allowed"); LLFloater * root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1), FALSE, FALSE, FALSE, root_floater->getName(), button); @@ -2784,7 +2784,7 @@ void LLPanelLandAccess::onClickRemoveAccess(void* data) // static void LLPanelLandAccess::onClickAddBanned() { - LLView * button = getChildView("add_banned"); + LLView * button = findChild<LLButton>("add_banned"); LLFloater * root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1), FALSE, FALSE, FALSE, root_floater->getName(), button); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 206bcb2c7e..cf2481f99a 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -285,7 +285,7 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id) void LLFloaterReporter::onClickSelectAbuser() { - LLView * button = getChildView("select_abuser", TRUE); + LLView * button = findChild<LLButton>("select_abuser", TRUE); LLFloater * root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE, FALSE, root_floater->getName(), button); diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 2ac82c553b..484ecbcd04 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -392,7 +392,7 @@ void LLFloaterSellLandUI::onChangeValue(LLUICtrl *ctrl, void *userdata) void LLFloaterSellLandUI::doSelectAgent() { - LLView * button = getChildView("sell_to_select_agent"); + LLView * button = findChild<LLView>("sell_to_select_agent"); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, this, _1, _2), FALSE, TRUE, FALSE, this->getName(), button); // grandparent is a floater, in order to set up dependency if (picker) diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 732a204ddf..a601561c62 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -359,7 +359,7 @@ BOOL LLIMFloater::postBuild() void LLIMFloater::onAddButtonClicked() { - LLView * button = getChildView("toolbar_panel")->getChildView("add_btn"); + LLView * button = findChild<LLView>("toolbar_panel")->findChild<LLButton>("add_btn"); LLFloater* root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE, FALSE, root_floater->getName(), button); if (!picker) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index fe00f70a28..d382b61921 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -415,7 +415,7 @@ void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) void LLIMFloaterContainer::onAddButtonClicked() { - LLView * button = getChildView("conversations_pane_buttons_expanded")->getChildView("add_btn"); + LLView * button = findChild<LLView>("conversations_pane_buttons_expanded")->findChild<LLButton>("add_btn"); LLFloater* root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloaterContainer::onAvatarPicked, this, _1), TRUE, TRUE, TRUE, root_floater->getName(), button); diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index 8d03930699..7612af8f5e 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -195,7 +195,7 @@ void LLPanelBlockedList::blockResidentByName() const BOOL allow_multiple = FALSE; const BOOL close_on_select = TRUE; - LLView * button = getChildView("plus_btn", TRUE); + LLView * button = findChild<LLButton>("plus_btn", TRUE); LLFloater* root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker * picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelBlockedList::callbackBlockPicked, this, _1, _2), allow_multiple, close_on_select, FALSE, root_floater->getName(), button); diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index 290e38ee1f..36bd5d9b77 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -301,7 +301,7 @@ void LLPanelGroupInvite::impl::callbackClickAdd(void* userdata) //Soon the avatar picker will be embedded into this panel //instead of being it's own separate floater. But that is next week. //This will do for now. -jwolk May 10, 2006 - LLView * button = panelp->getChildView("add_button"); + LLView * button = panelp->findChild<LLButton>("add_button"); LLFloater * root_floater = gFloaterView->getParentFloater(panelp); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( boost::bind(impl::callbackAddUsers, _1, panelp->mImplementation), TRUE, FALSE, FALSE, root_floater->getName(), button); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 14045df42e..90e857265d 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -1090,7 +1090,7 @@ bool LLPanelPeople::isItemsFreeOfFriends(const uuid_vec_t& uuids) void LLPanelPeople::onAddFriendWizButtonClicked() { LLPanel* cur_panel = mTabContainer->getCurrentPanel(); - LLView * button = cur_panel->getChildView("friends_add_btn", TRUE); + LLView * button = cur_panel->findChild<LLButton>("friends_add_btn", TRUE); // Show add friend wizard. LLFloater* root_floater = gFloaterView->getParentFloater(this); -- cgit v1.2.3 From 1aadf94fe44036d6012eb7d4f8a0b9288a719f37 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 30 Aug 2012 17:24:19 -0700 Subject: CHUI-305: Now the Region/Estate floater displays the frustum shadow when opening the Resident Picker. --- indra/newview/llfloateravatarpicker.cpp | 2 +- indra/newview/llfloaterregioninfo.cpp | 32 ++++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 3d6441553d..2152de1035 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -102,7 +102,7 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key) : LLFloater(key), mNumResultsReturned(0), mNearMeListComplete(FALSE), - mCloseOnSelect(FALSE),a + mCloseOnSelect(FALSE), mContextConeOpacity (0.f), mContextConeInAlpha(0.f), mContextConeOutAlpha(0.f), diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 4aebd9a4f4..e6b76159a1 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -647,8 +647,10 @@ void LLPanelRegionGeneralInfo::onClickKick() // this depends on the grandparent view being a floater // in order to set up floater dependency + LLView * button = findChild<LLButton>("kick_btn"); LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), FALSE, TRUE, FALSE, parent_floater->getName()); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), + FALSE, TRUE, FALSE, parent_floater->getName(), button); if (child_floater) { parent_floater->addDependentFloater(child_floater); @@ -924,8 +926,10 @@ BOOL LLPanelRegionDebugInfo::sendUpdate() void LLPanelRegionDebugInfo::onClickChooseAvatar() { + LLView * button = findChild<LLButton>("choose_avatar_btn"); LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloater * child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, this, _1, _2), FALSE, TRUE, FALSE, parent_floater->getName()); + LLFloater * child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, this, _1, _2), + FALSE, TRUE, FALSE, parent_floater->getName(), button); if (child_floater) { parent_floater->addDependentFloater(child_floater); @@ -1475,8 +1479,10 @@ void LLPanelEstateInfo::onClickKickUser() { // this depends on the grandparent view being a floater // in order to set up floater dependency + LLView * button = findChild<LLButton>("kick_user_from_estate_btn"); LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1), FALSE, TRUE, FALSE, parent_floater->getName()); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1), + FALSE, TRUE, FALSE, parent_floater->getName(), button); if (child_floater) { parent_floater->addDependentFloater(child_floater); @@ -1656,9 +1662,27 @@ bool LLPanelEstateInfo::accessAddCore2(const LLSD& notification, const LLSD& res LLFloater* parent_floater = panel ? gFloaterView->getParentFloater(panel) : NULL; const std::string& parent_floater_name = parent_floater ? parent_floater->getName() : ""; + //Determine the button that triggered opening of the avatar picker + //(so that a shadow frustum from the button to the avatar picker can be created) + LLView * button = NULL; + switch(change_info->mOperationFlag) + { + case ESTATE_ACCESS_ALLOWED_AGENT_ADD: + button = panel->findChild<LLButton>("add_allowed_avatar_btn"); + break; + + case ESTATE_ACCESS_BANNED_AGENT_ADD: + button = panel->findChild<LLButton>("add_banned_avatar_btn"); + break; + + case ESTATE_ACCESS_MANAGER_ADD: + button = panel->findChild<LLButton>("add_estate_manager_btn"); + break; + } + // avatar picker yes multi-select, yes close-on-select LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, (void*)change_info), - TRUE, TRUE, FALSE, parent_floater_name); + TRUE, TRUE, FALSE, parent_floater_name, button); //Allows the closed parent floater to close the child floater (avatar picker) if (child_floater) -- cgit v1.2.3 From ab37263a5cda14227724181c771ac1d3ef55f467 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 30 Aug 2012 21:34:48 -0700 Subject: CHUI-285 : LLIMFloaterContainer is now using LLParticipantList fully --- indra/llui/llfolderviewmodel.h | 11 +++-- indra/newview/llimfloatercontainer.cpp | 85 +++++++++++++++++++++++++++++++--- indra/newview/llimfloatercontainer.h | 4 +- indra/newview/llparticipantlist.cpp | 13 ++++-- 4 files changed, 99 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 16d9c86fd7..22bfc4dfb4 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -209,6 +209,7 @@ protected: }; + class LLFolderViewModelItemCommon : public LLFolderViewModelItem { public: @@ -249,6 +250,8 @@ public: std::string::size_type getFilterStringOffset(); std::string::size_type getFilterStringSize(); + typedef std::list<LLFolderViewModelItem*> child_list_t; + virtual void addChild(LLFolderViewModelItem* child) { mChildren.push_back(child); @@ -271,7 +274,11 @@ public: mChildren.clear(); dirtyFilter(); } - + + child_list_t::const_iterator getChildrenBegin() const { return mChildren.begin(); } + child_list_t::const_iterator getChildrenEnd() const { return mChildren.end(); } + child_list_t::size_type getChildrenCount() const { return mChildren.size(); } + void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) { mPassedFilter = passed; @@ -325,8 +332,6 @@ protected: S32 mLastFolderFilterGeneration; S32 mMostFilteredDescendantGeneration; - - typedef std::list<LLFolderViewModelItem*> child_list_t; child_list_t mChildren; LLFolderViewModelItem* mParent; LLFolderViewModelInterface& mRootViewModel; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 55cbf0b266..aa85e5023d 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -442,14 +442,36 @@ void LLIMFloaterContainer::repositioningWidgets() int index = 0; for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); widget_it != mConversationsWidgets.end(); - widget_it++, ++index) + widget_it++) { - LLFolderViewItem* widget = widget_it->second; + LLFolderViewFolder* widget = dynamic_cast<LLFolderViewFolder*>(widget_it->second); widget->setVisible(TRUE); widget->setRect(LLRect(0, panel_rect.getHeight() - item_height*index, panel_rect.getWidth(), panel_rect.getHeight() - item_height*(index+1))); + index++; + // Reposition the children as well + // Merov : This is highly suspiscious but gets the debug hack to work. This needs to be revised though. + if (widget->getItemsCount() != 0) + { + BOOL is_open = widget->isOpen(); + widget->setOpen(TRUE); + LLFolderViewFolder::items_t::const_iterator current = widget->getItemsBegin(); + LLFolderViewFolder::items_t::const_iterator end = widget->getItemsEnd(); + while (current != end) + { + LLFolderViewItem* item = (*current); + item->setVisible(TRUE); + item->setRect(LLRect(0, + panel_rect.getHeight() - item_height*index, + panel_rect.getWidth(), + panel_rect.getHeight() - item_height*(index+1))); + index++; + current++; + } + widget->setOpen(is_open); + } } } @@ -490,19 +512,51 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) mConversationsItems[uuid] = item; // Create a widget from it - LLFolderViewItem* widget = createConversationItemWidget(item); + LLConversationViewSession* widget = createConversationItemWidget(item); mConversationsWidgets[uuid] = widget; - // Add a new conversation widget to the root folder of a folder view. + // Add a new conversation widget to the root folder of the folder view widget->addToFolder(mConversationsRoot); // Add it to the UI + mConversationsListPanel->addChild(widget); widget->setVisible(TRUE); + + // Create the participants widgets now + // Note: usually, we do not get an updated avatar list at that point + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); + llinfos << "Merov debug : create participant, children size = " << item->getChildrenCount() << llendl; + while (current_participant_model != end_participant_model) + { + LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); + LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(widget); + mConversationsListPanel->addChild(participant_view); + participant_view->setVisible(TRUE); + current_participant_model++; + } + // Debugging hack : uncomment to force the creation of a dummy participant + // This hack is to be eventually deleted + if (item->getChildrenCount() == 0) + { + llinfos << "Merov debug : create dummy participant" << llendl; + // Create a dummy participant : we let that leak but that's just for debugging... + std::string name("Debug Test : "); + name += display_name; + LLUUID test_id; + test_id.generate(name); + LLConversationItemParticipant* participant_model = new LLConversationItemParticipant(name, test_id, getRootViewModel()); + // Create the dummy widget + LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(widget); + mConversationsListPanel->addChild(participant_view); + participant_view->setVisible(TRUE); + } + // End debugging hack repositioningWidgets(); - mConversationsListPanel->addChild(widget); - return; } @@ -537,7 +591,7 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c } } -LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) +LLConversationViewSession* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) { LLConversationViewSession::Params params; @@ -554,4 +608,21 @@ LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversat return LLUICtrlFactory::create<LLConversationViewSession>(params); } +LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParticipant(LLConversationItem* item) +{ + LLConversationViewSession::Params params; + + params.name = item->getDisplayName(); + //params.icon = bridge->getIcon(); + //params.icon_open = bridge->getOpenIcon(); + //params.creation_date = bridge->getCreationDate(); + params.root = mConversationsRoot; + params.listener = item; + params.rect = LLRect (0, 0, 0, 0); + params.tool_tip = params.name; + params.container = this; + + return LLUICtrlFactory::create<LLConversationViewParticipant>(params); +} + // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index d6dda8ea2d..300a820a26 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -37,6 +37,7 @@ #include "llgroupmgr.h" #include "lltrans.h" #include "llconversationmodel.h" +#include "llconversationview.h" class LLButton; class LLLayoutPanel; @@ -113,7 +114,8 @@ public: void addConversationListItem(const LLUUID& uuid); private: - LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); + LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); + LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item); // Conversation list data LLPanel* mConversationsListPanel; // This is the main widget we add conversation widget to diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 35c1a34a26..fa3432fc89 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -648,10 +648,10 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) if (is_avatar) { - // Create a participant view model instance and add it to the linked list + // Create a participant view model instance LLAvatarName avatar_name; bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name); - participant = new LLConversationItemParticipant(!has_name ? "Avatar" : avatar_name.mDisplayName , avatar_id, mRootViewModel); + participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.mDisplayName , avatar_id, mRootViewModel); if (mAvatarList) { mAvatarList->getIDs().push_back(avatar_id); @@ -661,7 +661,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) else { std::string display_name = LLVoiceClient::getInstance()->getDisplayName(avatar_id); - // Create a participant view model instance and add it to the linked list + // Create a participant view model instance participant = new LLConversationItemParticipant(display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name, avatar_id, mRootViewModel); if (mAvatarList) { @@ -672,6 +672,13 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) // *TODO : Merov : need to declare and bind a name update callback on that "participant" instance. See LLAvatarListItem::updateAvatarName() for pattern. // For the moment, we'll get the correct name only if it's already in the name cache (see call to LLAvatarNameCache::get() here above) + + // *TODO : Merov : need to update the online/offline status of the participant. + // Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id)) + + llinfos << "Merov debug : added participant, name = " << participant->getName() << llendl; + + // Add the participant model to the session's children list addParticipant(participant); adjustParticipant(avatar_id); -- cgit v1.2.3 From dab6788c42260135d298b619ff92a71838bba2b8 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 31 Aug 2012 11:57:36 +0300 Subject: CHUI-157 FIXED (Implement menu bar for conversation floater) - Added View Nearby chat history option - Also replaced menu item "Add Friend / Remove" with two separate menus: Add Friend and Remove Friend. So if user is a Friend the Remove Friend option would be shown there. If the user is not a friend, the Add Friend option would be shown. --- indra/newview/llconversationloglist.cpp | 17 ++++++--- indra/newview/llfloaterconversationlog.cpp | 5 +++ indra/newview/llfloaterconversationpreview.cpp | 40 ++++++++++++---------- indra/newview/llfloaterconversationpreview.h | 2 +- .../default/xui/en/menu_conversation_log_gear.xml | 28 +++++++++------ .../default/xui/en/menu_conversation_log_view.xml | 8 +++++ 6 files changed, 66 insertions(+), 34 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 257ec082a5..94be9055bd 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -241,15 +241,18 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata) { LLAvatarActions::offerTeleport(selected_id); } - else if("add_rem_friend" == command_name) + else if("add_friend" == command_name) { - if (LLAvatarActions::isFriend(selected_id)) + if (!LLAvatarActions::isFriend(selected_id)) { - LLAvatarActions::removeFriendDialog(selected_id); + LLAvatarActions::requestFriendshipDialog(selected_id); } - else + } + else if("remove_friend" == command_name) + { + if (LLAvatarActions::isFriend(selected_id)) { - LLAvatarActions::requestFriendshipDialog(selected_id); + LLAvatarActions::removeFriendDialog(selected_id); } } else if ("invite_to_group" == command_name) @@ -336,6 +339,10 @@ bool LLConversationLogList::isActionChecked(const LLSD& userdata) { return is_p2p && LLAvatarActions::isFriend(selected_id); } + else if ("is_not_friend" == command_name) + { + return is_p2p && !LLAvatarActions::isFriend(selected_id); + } return false; } diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index c77a9e74bb..4375ce5726 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -28,6 +28,7 @@ #include "llconversationloglist.h" #include "llfiltereditor.h" #include "llfloaterconversationlog.h" +#include "llfloaterreg.h" #include "llmenubutton.h" LLFloaterConversationLog::LLFloaterConversationLog(const LLSD& key) @@ -97,6 +98,10 @@ void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) { mConversationLogList->toggleSortFriendsOnTop(); } + else if ("view_nearby_chat_history" == command_name) + { + LLFloaterReg::showInstance("preview_conversation", LLSD(LLUUID::null), true); + } } bool LLFloaterConversationLog::isActionEnabled(const LLSD& userdata) diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index ae6f1441eb..7083fb987d 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -29,6 +29,7 @@ #include "llfloaterconversationpreview.h" #include "llimview.h" #include "lllineeditor.h" +#include "lltrans.h" LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id) : LLFloater(session_id), @@ -44,20 +45,28 @@ BOOL LLFloaterConversationPreview::postBuild() getChild<LLUICtrl>("more_history")->setCommitCallback(boost::bind(&LLFloaterConversationPreview::onMoreHistoryBtnClick, this)); const LLConversation* conv = LLConversationLog::instance().getConversation(mSessionID); - if (conv) - { - std::string name = conv->getConversationName(); - LLStringUtil::format_map_t args; - args["[NAME]"] = name; - std::string title = getString("Title", args); - setTitle(title); + std::string name; + std::string file; - getChild<LLLineEditor>("description")->setValue(name); + if (mSessionID != LLUUID::null && conv) + { + name = conv->getConversationName(); + file = conv->getHistoryFileName(); + } + else + { + name = LLTrans::getString("NearbyChatTitle"); + file = "chat"; } - std::string file = conv->getHistoryFileName(); - LLLogChat::loadChatHistory(file, mMessages, true); + LLStringUtil::format_map_t args; + args["[NAME]"] = name; + std::string title = getString("Title", args); + setTitle(title); + + getChild<LLLineEditor>("description")->setValue(name); + LLLogChat::loadChatHistory(file, mMessages, true); mCurrentPage = mMessages.size() / mPageSize; return LLFloater::postBuild(); @@ -68,7 +77,7 @@ void LLFloaterConversationPreview::draw() LLFloater::draw(); } -void LLFloaterConversationPreview::onOpen(const LLSD& session_id) +void LLFloaterConversationPreview::onOpen(const LLSD& key) { showHistory(); } @@ -88,13 +97,8 @@ void LLFloaterConversationPreview::showHistory() int delta = 0; if (mCurrentPage) { - // stinson 08/28/2012 : This operation could be simplified using integer math with the mod (%) operator. - // e.g. The following code should give the same output. - // int remainder = mMessages.size() % mPageSize; - // delta = (remainder == 0) ? 0 : (mPageSize - remainder); - // Though without examining further, the remainder might be a more appropriate value. - double num_of_pages = static_cast<double>(mMessages.size()) / static_cast<double>(mPageSize); - delta = static_cast<int>((ceil(num_of_pages) - num_of_pages) * static_cast<double>(mPageSize)); + int remainder = mMessages.size() % mPageSize; + delta = (remainder == 0) ? 0 : (mPageSize - remainder); } std::advance(iter, (mCurrentPage * mPageSize) - delta); diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h index 5105ef3702..2246a44761 100644 --- a/indra/newview/llfloaterconversationpreview.h +++ b/indra/newview/llfloaterconversationpreview.h @@ -39,7 +39,7 @@ public: virtual BOOL postBuild(); virtual void draw(); - virtual void onOpen(const LLSD& session_id); + virtual void onOpen(const LLSD& key); private: void onMoreHistoryBtnClick(); diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml index b8d0eef956..8796b87955 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml @@ -57,20 +57,28 @@ parameter="can_offer_teleport"/> </menu_item_call> <menu_item_separator /> - <menu_item_check - label="Add friend/Remove friend" + <menu_item_call + label="Add Friend" layout="topleft" - name="Friend_add_remove"> - <menu_item_check.on_click + name="add_friend"> + <on_click function="Calllog.Action" - parameter="add_rem_friend" /> - <menu_item_check.on_check + parameter="add_friend"/> + <on_visible + function="Calllog.Check" + parameter="is_not_friend" /> + </menu_item_call> + <menu_item_call + label="Remove Friend" + layout="topleft" + name="remove_friend"> + <on_click + function="Calllog.Action" + parameter="remove_friend"/> + <on_visible function="Calllog.Check" parameter="is_friend" /> - <menu_item_check.on_enable - function="Calllog.Enable" - parameter="add_rem_friend" /> - </menu_item_check> + </menu_item_call> <menu_item_call label="Invite to group..." layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml index 4ab8cb4f7d..ce65b23971 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml @@ -34,4 +34,12 @@ function="CallLog.Check" parameter="sort_friends_on_top" /> </menu_item_check> + <menu_item_separator /> + <menu_item_call + label="View Nearby chat history..." + name="view_nearby_chat_history"> + <on_click + function="CallLog.Action" + parameter="view_nearby_chat_history" /> + </menu_item_call> </toggleable_menu> -- cgit v1.2.3 From c2bb1a189c5f4c2367ee38e03371b28948e3ea81 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 31 Aug 2012 12:05:36 +0300 Subject: CHUI-154 FIXED (Add link to chat preferences from Conversation floater) - Added link to chat preferences from Conversation floater --- indra/newview/llimfloatercontainer.cpp | 22 ++++++++++++++++++++++ indra/newview/llimfloatercontainer.h | 2 ++ .../skins/default/xui/en/menu_participant_view.xml | 7 +++++++ 3 files changed, 31 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index aa85e5023d..f85b60cb36 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -40,6 +40,7 @@ #include "llavatarnamecache.h" #include "llgroupiconctrl.h" #include "llfloateravatarpicker.h" +#include "llfloaterpreference.h" #include "llimview.h" #include "lltransientfloatermgr.h" #include "llviewercontrol.h" @@ -53,6 +54,8 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) mExpandCollapseBtn(NULL), mConversationsRoot(NULL) { + mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLIMFloaterContainer::onCustomAction, this, _2)); + // Firstly add our self to IMSession observers, so we catch session events LLIMMgr::getInstance()->addSessionObserver(this); @@ -435,6 +438,25 @@ void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) } } +void LLIMFloaterContainer::onCustomAction(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + if ("chat_preferences" == command) + { + LLFloaterPreference* floater_prefs = LLFloaterReg::showTypedInstance<LLFloaterPreference>("preferences"); + if (floater_prefs) + { + LLTabContainer* tab_container = floater_prefs->getChild<LLTabContainer>("pref core"); + LLPanel* chat_panel = tab_container->getPanelByName("chat"); + if (tab_container && chat_panel) + { + tab_container->selectTabPanel(chat_panel); + } + } + } +} + void LLIMFloaterContainer::repositioningWidgets() { LLRect panel_rect = mConversationsListPanel->getRect(); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 300a820a26..a72a3e2221 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -103,6 +103,8 @@ private: void onAddButtonClicked(); void onAvatarPicked(const uuid_vec_t& ids); + void onCustomAction (const LLSD& userdata); + LLButton* mExpandCollapseBtn; LLLayoutPanel* mMessagesPane; LLLayoutPanel* mConversationsPane; diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml index 6401b0e3b7..df2700c94c 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_view.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -2,6 +2,13 @@ <toggleable_menu layout="topleft" name="participant_manu_view"> + <menu_item_call + label="Chat preferences..." + name="chat_preferences"> + <on_click + function="IMFloaterContainer.Action" + parameter="chat_preferences" /> + </menu_item_call> <menu_item_check label="Open conversation log" name="Conversation" -- cgit v1.2.3 From ae2e611dfb7b712c159ebafabb83ebbc1f7465b6 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 31 Aug 2012 16:52:50 +0300 Subject: CHUI-315 (Nearby chat messages do not appear in conversation floater): cancelled inheritance LLNearbyChat from LLSingleton; set mSingleInstance flag for it. --- indra/llui/llfloater.cpp | 7 ++++++ indra/llui/llfloater.h | 1 + indra/newview/llagent.cpp | 6 +++-- indra/newview/llchatitemscontainerctrl.cpp | 4 ++-- indra/newview/llfloatertranslationsettings.cpp | 3 ++- indra/newview/llgesturemgr.cpp | 4 +++- indra/newview/llimconversation.cpp | 31 +++++++++++++------------- indra/newview/llimview.cpp | 6 +++-- indra/newview/llnearbychat.cpp | 21 +++++++++-------- indra/newview/llnearbychat.h | 4 +--- indra/newview/llnearbychathandler.cpp | 5 +++-- indra/newview/llnotificationhandlerutil.cpp | 5 +++-- indra/newview/llnotificationtiphandler.cpp | 3 ++- indra/newview/llviewergesture.cpp | 4 +++- indra/newview/llviewerkeyboard.cpp | 3 ++- indra/newview/llviewermessage.cpp | 8 ++++--- indra/newview/llviewerwindow.cpp | 10 +++++---- 17 files changed, 76 insertions(+), 49 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 52812dc050..029c47c726 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -627,6 +627,13 @@ void LLFloater::setVisible( BOOL visible ) storeVisibilityControl(); } + +void LLFloater::setIsSingleInstance(BOOL is_single_instance) +{ + mSingleInstance = is_single_instance; +} + + // virtual void LLFloater::handleVisibilityChange ( BOOL new_visibility ) { diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index a1cac64a4a..4b738f88ea 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -217,6 +217,7 @@ public: /*virtual*/ void setFocus( BOOL b ); /*virtual*/ void setIsChrome(BOOL is_chrome); /*virtual*/ void setRect(const LLRect &rect); + void setIsSingleInstance(BOOL is_single_instance); void initFloater(const Params& p); diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index be6901c36a..bb0dbc7ff0 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1911,7 +1911,8 @@ void LLAgent::startTyping() { sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START); } - (LLNearbyChat::instance()).sendChatFromViewer("", CHAT_TYPE_START, FALSE); + (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> + sendChatFromViewer("", CHAT_TYPE_START, FALSE); } //----------------------------------------------------------------------------- @@ -1923,7 +1924,8 @@ void LLAgent::stopTyping() { clearRenderState(AGENT_STATE_TYPING); sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); - (LLNearbyChat::instance()).sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); + (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> + sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); } } diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index e6340e0fa3..f1b5c42ef3 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -323,12 +323,12 @@ BOOL LLNearbyChatToastPanel::handleMouseUp (S32 x, S32 y, MASK mask) return TRUE; else { - LLNearbyChat::instance().showHistory(); + (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))->showHistory(); return FALSE; } } - LLNearbyChat::instance().showHistory(); + (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))->showHistory(); return LLPanel::handleMouseUp(x,y,mask); } diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index b5b86dadc2..29d7732a68 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -293,6 +293,7 @@ void LLFloaterTranslationSettings::onBtnOK() gSavedSettings.setString("TranslationService", getSelectedService()); gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey()); gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); - LLNearbyChat::instance().showTranslationCheckbox(LLTranslate::isTranslationConfigured()); + (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> + showTranslationCheckbox(LLTranslate::isTranslationConfigured()); closeFloater(false); } diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 0377337af6..0996af6125 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -35,6 +35,7 @@ // library #include "llaudioengine.h" #include "lldatapacker.h" +#include "llfloaterreg.h" #include "llinventory.h" #include "llkeyframemotion.h" #include "llmultigesture.h" @@ -997,7 +998,8 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) const BOOL animate = FALSE; - LLNearbyChat::instance().sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); + (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> + sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); gesture->mCurrentStep++; break; diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 7bb29be27b..5a5196fb7e 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -144,7 +144,7 @@ BOOL LLIMConversation::postBuild() updateHeaderAndToolbar(); - mSaveRect = isTornOff(); + mSaveRect = !getHost(); initRectControl(); if (isChatMultiTab()) @@ -267,11 +267,11 @@ void LLIMConversation::hideOrShowTitle() LLView* floater_contents = getChild<LLView>("contents_view"); LLRect floater_rect = getLocalRect(); - S32 top_border_of_contents = floater_rect.mTop - (isTornOff()? floater_header_size : 0); + S32 top_border_of_contents = floater_rect.mTop - (getHost()? 0 : floater_header_size); LLRect handle_rect (0, floater_rect.mTop, floater_rect.mRight, top_border_of_contents); LLRect contents_rect (0, top_border_of_contents, floater_rect.mRight, floater_rect.mBottom); mDragHandle->setShape(handle_rect); - mDragHandle->setVisible(isTornOff()); + mDragHandle->setVisible(!getHost()); floater_contents->setShape(contents_rect); } @@ -289,8 +289,8 @@ void LLIMConversation::hideAllStandardButtons() void LLIMConversation::updateHeaderAndToolbar() { - bool is_torn_off = !getHost(); - if (!is_torn_off) + bool is_hosted = !!getHost(); + if (is_hosted) { hideAllStandardButtons(); } @@ -299,7 +299,7 @@ void LLIMConversation::updateHeaderAndToolbar() // Participant list should be visible only in torn off floaters. bool is_participant_list_visible = - is_torn_off + !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel") && !mIsP2PChat; @@ -307,21 +307,21 @@ void LLIMConversation::updateHeaderAndToolbar() // Display collapse image (<<) if the floater is hosted // or if it is torn off but has an open control panel. - bool is_expanded = !is_torn_off || is_participant_list_visible; + bool is_expanded = is_hosted || is_participant_list_visible; mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); // toggle floater's drag handle and title visibility if (mDragHandle) { - mDragHandle->setTitleVisible(is_torn_off); + mDragHandle->setTitleVisible(!is_hosted); } // The button (>>) should be disabled for torn off P2P conversations. - mExpandCollapseBtn->setEnabled(!is_torn_off || !mIsP2PChat); + mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat); - mTearOffBtn->setImageOverlay(getString(is_torn_off? "return_icon" : "tear_off_icon")); + mTearOffBtn->setImageOverlay(getString(is_hosted? "tear_off_icon" : "return_icon")); - mCloseBtn->setVisible(!is_torn_off && !mIsNearbyChat); + mCloseBtn->setVisible(is_hosted && !mIsNearbyChat); enableDisableCallBtn(); @@ -358,9 +358,10 @@ void LLIMConversation::processChatHistoryStyleUpdate() } } - if (LLNearbyChat::instanceExists()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + if (nearby_chat) { - LLNearbyChat::instance().reloadMessages(); + nearby_chat->reloadMessages(); } } @@ -427,8 +428,8 @@ void LLIMConversation::onClose(bool app_quitting) void LLIMConversation::onTearOffClicked() { - setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); - mSaveRect = isTornOff(); + setFollows(getHost()? FOLLOWS_NONE : FOLLOWS_ALL); + mSaveRect = !getHost(); initRectControl(); LLFloater::onClickTearOff(this); updateHeaderAndToolbar(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index effcc9a826..f5392b442a 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2486,9 +2486,11 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess LLChat chat(message); chat.mSourceType = CHAT_SOURCE_SYSTEM; - if (LLNearbyChat::instanceExists()) + + LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); + if (nearby_chat) { - LLNearbyChat::instance().addMessage(chat); + nearby_chat->addMessage(chat); } } else // going to IM session diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index f1518fe825..25bbc82fee 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -134,6 +134,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd) mKey = LLSD(); mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); setName("nearby_chat"); + setIsSingleInstance(TRUE); } //virtual @@ -780,20 +781,21 @@ void LLNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BO // static void LLNearbyChat::startChat(const char* line) { - if (LLNearbyChat::instanceExists()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + if (nearby_chat) { - (LLNearbyChat::instance()).show(); - (LLNearbyChat::instance()).setVisible(TRUE); - (LLNearbyChat::instance()).setFocus(TRUE); - (LLNearbyChat::instance().mInputEditor)->setFocus(TRUE); + nearby_chat->show(); + nearby_chat->setVisible(TRUE); + nearby_chat->setFocus(TRUE); + nearby_chat->mInputEditor->setFocus(TRUE); if (line) { std::string line_string(line); - (LLNearbyChat::instance().mInputEditor)->setText(line_string); + nearby_chat->mInputEditor->setText(line_string); } - (LLNearbyChat::instance().mInputEditor)->endOfDoc(); + nearby_chat->mInputEditor->endOfDoc(); } } @@ -801,9 +803,10 @@ void LLNearbyChat::startChat(const char* line) // static void LLNearbyChat::stopChat() { - if (LLNearbyChat::instanceExists()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + if (nearby_chat) { - (LLNearbyChat::instance().mInputEditor)->setFocus(FALSE); + nearby_chat->mInputEditor->setFocus(FALSE); gAgent.stopTyping(); } } diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 379bfbee4b..4fc5cb7f76 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -35,15 +35,13 @@ #include "lloutputmonitorctrl.h" #include "llspeakers.h" #include "llscrollbar.h" -#include "llsingleton.h" #include "llviewerchat.h" #include "llpanel.h" class LLResizeBar; class LLNearbyChat - : public LLIMConversation, - public LLSingleton<LLNearbyChat> + : public LLIMConversation { public: // constructor for inline chat-bars (e.g. hosted in chat history window) diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 37f4cc4c19..ca3fffeffd 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -537,7 +537,8 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, } } - LLNearbyChat::instance().addMessage(chat_msg, true, args); + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + nearby_chat->addMessage(chat_msg, true, args); if(chat_msg.mSourceType == CHAT_SOURCE_AGENT && chat_msg.mFromID.notNull() @@ -553,7 +554,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, // Send event on to LLEventStream sChatWatcher->post(chat); - if( LLNearbyChat::instance().isInVisibleChain() + if( nearby_chat->isInVisibleChain() || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT && gSavedSettings.getBOOL("UseChatBubbles") ) || mChannel.isDead() diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index db8e917435..2484040ac4 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -181,13 +181,14 @@ void LLHandlerUtil::logGroupNoticeToIMGroup( // static void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type) { - if (LLNearbyChat::instanceExists()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + if (nearby_chat) { LLChat chat_msg(notification->getMessage()); chat_msg.mSourceType = type; chat_msg.mFromName = SYSTEM_FROM; chat_msg.mFromID = LLUUID::null; - LLNearbyChat::instance().addMessage(chat_msg); + nearby_chat->addMessage(chat_msg); } } diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 67fc9b27dc..ef6668247c 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -85,7 +85,8 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); // don't show toast if Nearby Chat is opened - if (LLNearbyChat::instance().isChatVisible()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + if (nearby_chat && nearby_chat->isChatVisible()) { return false; } diff --git a/indra/newview/llviewergesture.cpp b/indra/newview/llviewergesture.cpp index a2dea31d9b..71608b5280 100644 --- a/indra/newview/llviewergesture.cpp +++ b/indra/newview/llviewergesture.cpp @@ -33,6 +33,7 @@ #include "llviewerinventory.h" #include "sound_ids.h" // for testing +#include "llfloaterreg.h" #include "llkeyboard.h" // for key shortcuts for testing #include "llinventorymodel.h" #include "llvoavatar.h" @@ -130,7 +131,8 @@ void LLViewerGesture::doTrigger( BOOL send_chat ) { // Don't play nodding animation, since that might not blend // with the gesture animation. - LLNearbyChat::instance().sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); + (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> + sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); } } diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 7105720eb4..f8e988bc0c 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llappviewer.h" +#include "llfloaterreg.h" #include "llviewerkeyboard.h" #include "llmath.h" #include "llagent.h" @@ -543,7 +544,7 @@ void start_gesture( EKeystate s ) if (KEYSTATE_UP == s && ! (focus_ctrlp && focus_ctrlp->acceptsTextInput())) { - if (LLNearbyChat::instance().getCurrentChat().empty()) + if ((LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))->getCurrentChat().empty()) { // No existing chat in chat editor, insert '/' LLNearbyChat::startChat("/"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 9abd269f0f..81cbc3b6c3 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2297,9 +2297,10 @@ void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string m // Treat like a system message and put in chat history. chat.mText = av_name.getCompleteName() + ": " + message; - if (LLNearbyChat::instanceExists()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + if (nearby_chat) { - LLNearbyChat::instance().addMessage(chat); + nearby_chat->addMessage(chat); } } @@ -2895,7 +2896,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Note: lie to Nearby Chat, pretending that this is NOT an IM, because // IMs from obejcts don't open IM sessions. - if(!chat_from_system && LLNearbyChat::instanceExists()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + if(!chat_from_system && nearby_chat) { chat.mOwnerID = from_id; LLSD args; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 23d2b1633d..791cadaee4 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2493,12 +2493,14 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) return TRUE; } + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + // Traverses up the hierarchy if( keyboard_focus ) { - if (LLNearbyChat::instanceExists()) + if (nearby_chat) { - LLChatEntry* chat_editor = LLNearbyChat::instance().getChatBox(); + LLChatEntry* chat_editor = nearby_chat->getChatBox(); // arrow keys move avatar while chatting hack if (chat_editor && chat_editor->hasFocus()) @@ -2562,11 +2564,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) { - LLChatEntry* chat_editor = LLNearbyChat::instance().getChatBox(); + LLChatEntry* chat_editor = nearby_chat->getChatBox(); if (chat_editor) { // passing NULL here, character will be added later when it is handled by character handler. - LLNearbyChat::instance().startChat(NULL); + nearby_chat->startChat(NULL); return TRUE; } } -- cgit v1.2.3 From 73769180f363556d5517e3070fc4a2ac61e713d6 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 31 Aug 2012 19:22:41 +0300 Subject: CHUI-298 FIXED (Conversation started as an IM and then goes to voice call does not show as call in conversation log) - Show voice icon when call is started - Added flag LLConversation::mIsConversationPast which means that this conversation is finished and any of its data can't be changed. I.e. it cannot be reused. - When session removed (i.e. finished) corresponding conversation is marked as Past conversation. I.e. mIsConversationPast is true. - Added changed(const LLUUID& session_id, U32 mask) method to LLConversationLog to notify particular conversation. This is used in LLConversationLogList to update its particular item and not to rebuild the whole list. --- indra/newview/llconversationlog.cpp | 54 ++++++++++++++++++++++++++++++- indra/newview/llconversationlog.h | 25 ++++++++++---- indra/newview/llconversationloglist.cpp | 22 +++++++++++++ indra/newview/llconversationloglist.h | 1 + indra/newview/llconversationloglistitem.h | 4 +-- indra/newview/llvoicechannel.cpp | 2 +- indra/newview/llvoicechannel.h | 2 +- 7 files changed, 99 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 486cea4064..23ccc78a0f 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -33,7 +33,8 @@ struct Conversation_params { Conversation_params(time_t time) : mTime(time), - mTimestamp(LLConversation::createTimestamp(time)) + mTimestamp(LLConversation::createTimestamp(time)), + mIsConversationPast(true) {} time_t mTime; @@ -44,6 +45,7 @@ struct Conversation_params LLUUID mSessionID; LLUUID mParticipantID; bool mIsVoice; + bool mIsConversationPast; bool mHasOfflineIMs; }; @@ -60,6 +62,7 @@ LLConversation::LLConversation(const Conversation_params& params) mSessionID(params.mSessionID), mParticipantID(params.mParticipantID), mIsVoice(params.mIsVoice), + mIsConversationPast(params.mIsConversationPast), mHasOfflineIMs(params.mHasOfflineIMs) { setListenIMFloaterOpened(); @@ -74,6 +77,7 @@ LLConversation::LLConversation(const LLIMModel::LLIMSession& session) mSessionID(session.mSessionID), mParticipantID(session.mOtherParticipantID), mIsVoice(session.mStartedAsIMCall), + mIsConversationPast(false), mHasOfflineIMs(session.mHasOfflineMessage) { setListenIMFloaterOpened(); @@ -89,6 +93,7 @@ LLConversation::LLConversation(const LLConversation& conversation) mSessionID = conversation.getSessionID(); mParticipantID = conversation.getParticipantID(); mIsVoice = conversation.isVoice(); + mIsConversationPast = conversation.isConversationPast(); mHasOfflineIMs = conversation.hasOfflineMessages(); setListenIMFloaterOpened(); @@ -99,6 +104,14 @@ LLConversation::~LLConversation() mIMFloaterShowedConnection.disconnect(); } +void LLConversation::setIsVoice(bool is_voice) +{ + if (mIsConversationPast) + return; + + mIsVoice = is_voice; +} + void LLConversation::onIMFloaterShown(const LLUUID& session_id) { if (mSessionID == session_id) @@ -228,6 +241,21 @@ void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string { LLConversation conversation(*session); LLConversationLog::instance().logConversation(conversation); + session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2)); + } +} + +void LLConversationLog::sessionRemoved(const LLUUID& session_id) +{ + conversations_vec_t::reverse_iterator rev_iter = mConversations.rbegin(); + + for (; rev_iter != mConversations.rend(); ++rev_iter) + { + if (rev_iter->getSessionID() == session_id && !rev_iter->isConversationPast()) + { + rev_iter->setIsPast(true); + return; // return here because only one session with session_id may be active + } } } @@ -350,3 +378,27 @@ void LLConversationLog::notifyObservers() (*iter)->changed(); } } + +void LLConversationLog::notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask) +{ + std::set<LLConversationLogObserver*>::const_iterator iter = mObservers.begin(); + for (; iter != mObservers.end(); ++iter) + { + (*iter)->changed(session_id, mask); + } +} + +void LLConversationLog::onVoiceChannelConnected(const LLUUID& session_id, const LLVoiceChannel::EState& state) +{ + conversations_vec_t::reverse_iterator rev_iter = mConversations.rbegin(); + + for (; rev_iter != mConversations.rend(); ++rev_iter) + { + if (rev_iter->getSessionID() == session_id && !rev_iter->isConversationPast() && LLVoiceChannel::STATE_CALL_STARTED == state) + { + rev_iter->setIsVoice(true); + notifyPrticularConversationObservers(session_id, LLConversationLogObserver::VOICE_STATE); + return; // return here because only one session with session_id may be active + } + } +} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index a7457d55e3..f2b6a67c92 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -57,8 +57,12 @@ public: const std::string& getTimestamp() const { return mTimestamp; } const time_t& getTime() const { return mTime; } bool isVoice() const { return mIsVoice; } + bool isConversationPast() const { return mIsConversationPast; } bool hasOfflineMessages() const { return mHasOfflineIMs; } + void setIsVoice(bool is_voice); + void setIsPast (bool is_past) { mIsConversationPast = is_past; } + /* * Resets flag of unread offline message to false when im floater with this conversation is opened. */ @@ -87,6 +91,7 @@ private: LLUUID mParticipantID; bool mIsVoice; bool mHasOfflineIMs; + bool mIsConversationPast; // once session is finished conversation became past forever std::string mTimestamp; // conversation start time in form of: mm/dd/yyyy hh:mm }; @@ -122,12 +127,14 @@ public: // LLIMSessionObserver triggers virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); - virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){} // Stub - virtual void sessionRemoved(const LLUUID& session_id){} // Stub - virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){} // Stub + virtual void sessionRemoved(const LLUUID& session_id); + virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){}; // Stub + virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){}; // Stub - // Triggered by LLFriendObserver change void notifyObservers(); + void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask); + + void onVoiceChannelConnected(const LLUUID& session_id, const LLVoiceChannel::EState& state); /** * public method which is called on viewer exit to save conversation log @@ -140,8 +147,7 @@ private: /** * constructs file name in which conversations log will be saved - * file name template: agentID.call_log. - * For example: a086icaa-782d-88d0-ae29-987a55c99sss.call_log + * file name is conversation.log */ std::string getFileName(); @@ -158,8 +164,15 @@ private: class LLConversationLogObserver { public: + + enum EConversationChange + { + VOICE_STATE = 1 + }; + virtual ~LLConversationLogObserver(){} virtual void changed() = 0; + virtual void changed(const LLUUID& session_id, U32 mask){}; }; #endif /* LLCONVERSATIONLOG_H_ */ diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 94be9055bd..d39e090c22 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -141,6 +141,28 @@ void LLConversationLogList::changed() refresh(); } +void LLConversationLogList::changed(const LLUUID& session_id, U32 mask) +{ + if (mask & LLConversationLogObserver::VOICE_STATE) + { + std::vector<LLPanel*> panels; + LLFlatListViewEx::getItems(panels); + + std::vector<LLPanel*>::iterator iter = panels.begin(); + + for (; iter != panels.end(); ++iter) + { + LLConversationLogListItem* item = dynamic_cast<LLConversationLogListItem*>(*iter); + + if (item && session_id == item->getConversation()->getSessionID() && !item->getConversation()->isConversationPast()) + { + item->initIcons(); + return; + } + } + } +} + void LLConversationLogList::addNewItem(const LLConversation* conversation) { LLConversationLogListItem* item = new LLConversationLogListItem(&*conversation); diff --git a/indra/newview/llconversationloglist.h b/indra/newview/llconversationloglist.h index dff34a74c6..5e7fc0a9fb 100644 --- a/indra/newview/llconversationloglist.h +++ b/indra/newview/llconversationloglist.h @@ -68,6 +68,7 @@ public: * Changes from LLConversationLogObserver */ virtual void changed(); + virtual void changed(const LLUUID& session_id, U32 mask); private: diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h index 8943e11604..2aaafa0fba 100644 --- a/indra/newview/llconversationloglistitem.h +++ b/indra/newview/llconversationloglistitem.h @@ -64,10 +64,10 @@ public: void onDoubleClick(); -private: - void initIcons(); +private: + const LLConversation* mConversation; LLTextBox* mConversationName; diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index bd12328a6b..ceff75a0cc 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -414,7 +414,7 @@ void LLVoiceChannel::doSetState(const EState& new_state) mState = new_state; if (!mStateChangedCallback.empty()) - mStateChangedCallback(old_state, mState, mCallDirection, mCallEndedByAgent); + mStateChangedCallback(old_state, mState, mCallDirection, mCallEndedByAgent, mSessionID); } //static diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index b8597ee5cb..fed44974fd 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -52,7 +52,7 @@ public: OUTGOING_CALL } EDirection; - typedef boost::signals2::signal<void(const EState& old_state, const EState& new_state, const EDirection& direction, bool ended_by_agent)> state_changed_signal_t; + typedef boost::signals2::signal<void(const EState& old_state, const EState& new_state, const EDirection& direction, bool ended_by_agent, const LLUUID& session_id)> state_changed_signal_t; // on current channel changed signal typedef boost::function<void(const LLUUID& session_id)> channel_changed_callback_t; -- cgit v1.2.3 From eb13b2b4680ab80e8a20d341a481b8c1d62ca156 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Mon, 3 Sep 2012 17:42:20 +0300 Subject: CHUI-307 FIXED (LLInitParam::Parser::parserWarnings in log when adding conversations or deleting entries from conversation log ) - removed redundant incorrect attributes --- indra/newview/skins/default/xui/en/panel_blocked_list_item.xml | 1 - .../newview/skins/default/xui/en/panel_conversation_log_list_item.xml | 3 --- 2 files changed, 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml index 84e7e467b1..752321b949 100644 --- a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml @@ -60,7 +60,6 @@ <text follows="left|right" font="SansSerifSmall" - font.color="DkGray" height="15" layout="topleft" left_pad="5" diff --git a/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml index cee7d8581a..8a58eb1ca6 100644 --- a/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml @@ -28,7 +28,6 @@ visible="false" width="380" /> <icon - default_icon_name="voice_session_icon" follows="top|left" height="20" layout="topleft" @@ -72,7 +71,6 @@ <text follows="left|right" font="SansSerifSmall" - font.color="DkGray" height="15" layout="topleft" left_pad="5" @@ -84,7 +82,6 @@ <text follows="right" font="SansSerifSmall" - font.color="DkGray" height="15" layout="topleft" left_pad="5" -- cgit v1.2.3 From 7bad109c3d7e6d70649839634586a09033cfb207 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Mon, 3 Sep 2012 17:52:54 +0300 Subject: CHUI-314 FIXED (Update Save IM logs on my computer setting to also control populatoin of conversation log) - Now LLConversationLog is optionally listener of IMSession, dependently on "LogInstantMessages" per account setting, saving of call log to file also depends on this setting. Which means that with the Save IM logs on my computer disabled: IM logs for the user will not be saved to their computer and conversations will not be logged to the conversation log. --- indra/newview/llappviewer.cpp | 5 ++++- indra/newview/llconversationlog.cpp | 27 +++++++++++++++++++++++++-- indra/newview/llconversationlog.h | 2 ++ 3 files changed, 31 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 08a1a237f5..4dacde4792 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1834,7 +1834,10 @@ bool LLAppViewer::cleanup() LLMuteList::getInstance()->cache(gAgent.getID()); //save call log list - LLConversationLog::instance().cache(); + if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + { + LLConversationLog::instance().cache(); + } if (mPurgeOnExit) { diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 23ccc78a0f..7db6a93709 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -185,11 +185,34 @@ LLConversationLog::LLConversationLog() { loadFromFile(getFileName()); - LLIMMgr::instance().addSessionObserver(this); - + LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); + if (ctrl) + { + ctrl->getSignal()->connect(boost::bind(&LLConversationLog::observeIMSession, this)); + + if (ctrl->getValue().asBoolean()) + { + LLIMMgr::instance().addSessionObserver(this); + } + } + mFriendObserver = new LLConversationLogFriendObserver; LLAvatarTracker::instance().addObserver(mFriendObserver); + } + +void LLConversationLog::observeIMSession() +{ + if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + { + LLIMMgr::instance().addSessionObserver(this); + } + else + { + LLIMMgr::instance().removeSessionObserver(this); + } +} + void LLConversationLog::logConversation(const LLConversation& conversation) { mConversations.push_back(conversation); diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index f2b6a67c92..9fd54c61c9 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -145,6 +145,8 @@ private: LLConversationLog(); + void observeIMSession(); + /** * constructs file name in which conversations log will be saved * file name is conversation.log -- cgit v1.2.3 From 681406427fab95167cb87b54e8315600176bf218 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 4 Sep 2012 20:39:49 +0300 Subject: CHUI-311 FIXED (Make conversation list panel size persist between sessions): save current width in the setting_per_account.xml --- indra/newview/llimfloatercontainer.cpp | 23 ++++++++++++++++++++++- indra/newview/llimfloatercontainer.h | 2 ++ 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 56648d09b5..480f964939 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -52,7 +52,8 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) : LLMultiFloater(seed), mExpandCollapseBtn(NULL), - mConversationsRoot(NULL) + mConversationsRoot(NULL), + mInitialized(false) { mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLIMFloaterContainer::onCustomAction, this, _2)); @@ -139,6 +140,16 @@ BOOL LLIMFloaterContainer::postBuild() LLAvatarNameCache::addUseDisplayNamesCallback( boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); + if (! mMessagesPane->isCollapsed()) + { + S32 list_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"); + LLRect list_size = mConversationsPane->getRect(); + S32 left_pad = mConversationsListPanel->getRect().mLeft; + list_size.mRight = list_size.mLeft + list_width - left_pad; + + mConversationsPane->handleReshape(list_size, TRUE); + } + mInitialized = true; return TRUE; } @@ -514,6 +525,16 @@ void LLIMFloaterContainer::onCustomAction(const LLSD& userdata) void LLIMFloaterContainer::repositioningWidgets() { + if (!mInitialized) + { + return; + } + + if (!mConversationsPane->isCollapsed()) + { + S32 list_width = (mConversationsPane->getRect()).getWidth(); + gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", list_width); + } LLRect panel_rect = mConversationsListPanel->getRect(); S32 item_height = 16; int index = 0; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index a72a3e2221..53e3849600 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -110,6 +110,8 @@ private: LLLayoutPanel* mConversationsPane; LLLayoutStack* mConversationsStack; + bool mInitialized; + // Conversation list implementation public: void removeConversationListItem(const LLUUID& uuid, bool change_focus = true); -- cgit v1.2.3 From 5fbb161ba0a28e64474efc295b12bccffdcdb0e0 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 4 Sep 2012 13:34:33 -0700 Subject: CHUI-305: Now searching in the resident picker works. Problem: The resident picker search results were being sent to the old global resident picker. Now resident pickers are non-global and coupled to their parent floater. --- indra/newview/llfloateravatarpicker.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 2152de1035..6ada809cdb 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -460,8 +460,9 @@ class LLAvatarPickerResponder : public LLHTTPClient::Responder { public: LLUUID mQueryID; + std::string mName; - LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { } + LLAvatarPickerResponder(const LLUUID& id, const std::string& name) : mQueryID(id), mName(name) { } /*virtual*/ void completed(U32 status, const std::string& reason, const LLSD& content) { @@ -474,7 +475,7 @@ public: if (isGoodStatus(status) || status == 400) { LLFloaterAvatarPicker* floater = - LLFloaterReg::findTypedInstance<LLFloaterAvatarPicker>("avatar_picker"); + LLFloaterReg::findTypedInstance<LLFloaterAvatarPicker>("avatar_picker", mName); if (floater) { floater->processResponse(mQueryID, content); @@ -517,7 +518,7 @@ void LLFloaterAvatarPicker::find() url += "?page_size=100&names="; url += LLURI::escape(text); llinfos << "avatar picker " << url << llendl; - LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID)); + LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID, getKey().asString())); } else { -- cgit v1.2.3 From d41202336b7c797bc3fe4feffa8be2164518e845 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 4 Sep 2012 14:21:25 -0700 Subject: CHUI-303: Problem was that the prior solution only updated (using dirtyFilter()) the inventory window that the paste occurred in. Resolution: Now each inventory window calls dirtyFilter(), which then determines visibility of the pasted item. --- indra/newview/llinventorybridge.cpp | 12 ++---------- indra/newview/llinventorymodel.cpp | 1 + 2 files changed, 3 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 745375fe3d..72c54e5ce2 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3193,16 +3193,8 @@ void LLFolderBridge::pasteFromClipboard() LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id); llassert(vicat); if (vicat) - { - //Set the pasted folder to dirty, could do this in changeCategoryParent() but only need to set dirty - //when pasting from the clipboard. Setting dirty allows updating the filter state, which determines - //visibility in the new pasted location. - LLFolderViewFolder * folderViewItem = mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(item_id) : NULL; - if(folderViewItem && folderViewItem->getViewModelItem()) - { - folderViewItem->getViewModelItem()->dirtyFilter(); - } - + { + //changeCategoryParent() implicity calls dirtyFilter changeCategoryParent(model, vicat, parent_id, FALSE); } } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 0673970d89..e7d59d92d9 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -986,6 +986,7 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat) cat_array->put(old_cat); } mask |= LLInventoryObserver::STRUCTURE; + mask |= LLInventoryObserver::INTERNAL; } if(old_cat->getName() != cat->getName()) { -- cgit v1.2.3 From 8cd5d361600f34a0a7fa504a721bea3301191644 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 4 Sep 2012 22:11:28 -0700 Subject: CHUI-285 : Create participant widgets in the conversation list --- indra/newview/llconversationmodel.cpp | 12 ++++-- indra/newview/llconversationmodel.h | 14 ++++--- indra/newview/llconversationview.cpp | 38 ++++++++++++++++- indra/newview/llconversationview.h | 20 ++++++++- indra/newview/llimfloatercontainer.cpp | 75 +++++++++++++++++++++++++--------- 5 files changed, 128 insertions(+), 31 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index d7f9093a4a..aa21b08ec8 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -36,21 +36,24 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(display_name), - mUUID(uuid) + mUUID(uuid), + mNeedsRefresh(true) { } LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(""), - mUUID(uuid) + mUUID(uuid), + mNeedsRefresh(true) { } LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(""), - mUUID() + mUUID(), + mNeedsRefresh(true) { } @@ -102,11 +105,13 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa { addChild(participant); mIsLoaded = true; + mNeedsRefresh = true; } void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* participant) { removeChild(participant); + mNeedsRefresh = true; } void LLConversationItemSession::removeParticipant(const LLUUID& participant_id) @@ -122,6 +127,7 @@ void LLConversationItemSession::clearParticipants() { clearChildren(); mIsLoaded = false; + mNeedsRefresh = true; } LLConversationItemParticipant* LLConversationItemSession::findParticipant(const LLUUID& participant_id) diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 1a2e09dfab..5947055e0f 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -60,7 +60,7 @@ public: virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } virtual std::string getLabelSuffix() const { return LLStringUtil::null; } virtual BOOL isItemRenameable() const { return TRUE; } - virtual BOOL renameItem(const std::string& new_name) { mName = new_name; return TRUE; } + virtual BOOL renameItem(const std::string& new_name) { mName = new_name; mNeedsRefresh = true; return TRUE; } virtual BOOL isItemMovable( void ) const { return FALSE; } virtual BOOL isItemRemovable( void ) const { return FALSE; } virtual BOOL isItemInTrash( void) const { return FALSE; } @@ -102,10 +102,14 @@ public: // bool hasSameValues(std::string name, const LLUUID& uuid) { return ((name == mName) && (uuid == mUUID)); } bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } - + + void resetRefresh() { mNeedsRefresh = false; } + bool needsRefresh() { return mNeedsRefresh; } + protected: std::string mName; // Name of the session or the participant LLUUID mUUID; // UUID of the session or the participant + bool mNeedsRefresh; // Flag signaling to the view that something changed for this item }; class LLConversationItemSession : public LLConversationItem @@ -115,7 +119,7 @@ public: LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItemSession() {} - void setSessionID(const LLUUID& session_id) { mUUID = session_id; } + void setSessionID(const LLUUID& session_id) { mUUID = session_id; mNeedsRefresh = true; } void addParticipant(LLConversationItemParticipant* participant); void removeParticipant(LLConversationItemParticipant* participant); void removeParticipant(const LLUUID& participant_id); @@ -142,8 +146,8 @@ public: bool isMuted() { return mIsMuted; } bool isModerator() {return mIsModerator; } - void setIsMuted(bool is_muted) { mIsMuted = is_muted; } - void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; } + void setIsMuted(bool is_muted) { mIsMuted = is_muted; mNeedsRefresh = true; } + void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; } void dumpDebugData(); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index fefb7e9cac..2f71e92a7d 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -79,12 +79,46 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible) } } +LLConversationViewParticipant* LLConversationViewSession::findParticipant(const LLUUID& participant_id) +{ + // This is *not* a general tree parsing algorithm. We search only in the mItems list + // assuming there is no mFolders which makes sense for sessions (sessions don't contain + // sessions). + LLConversationViewParticipant* participant = NULL; + items_t::const_iterator iter; + for (iter = getItemsBegin(); iter != getItemsEnd(); iter++) + { + participant = dynamic_cast<LLConversationViewParticipant*>(*iter); + if (participant->hasSameValue(participant_id)) + { + break; + } + } + return (iter == getItemsEnd() ? NULL : participant); +} + +void LLConversationViewSession::refresh() +{ + // Refresh the session view from its model data + // LLConversationItemSession* vmi = dynamic_cast<LLConversationItemSession*>(getViewModelItem()); + + // Note: for the moment, all that needs to be done is done by LLFolderViewItem::refresh() + + // Do the regular upstream refresh + LLFolderViewFolder::refresh(); +} + // // Implementation of conversations list participant (avatar) widgets // -LLConversationViewParticipant::LLConversationViewParticipant( const LLFolderViewItem::Params& p ): - LLFolderViewItem(p) +LLConversationViewParticipant::Params::Params() : + participant_id() +{} + +LLConversationViewParticipant::LLConversationViewParticipant( const LLConversationViewParticipant::Params& p ): + LLFolderViewItem(p), + mUUID(p.participant_id) { } diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 5695925f43..27ceb2af3b 100644 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -30,6 +30,8 @@ #include "llfolderviewitem.h" class LLIMFloaterContainer; +class LLConversationViewSession; +class LLConversationViewParticipant; // Implementation of conversations list session widgets @@ -53,18 +55,34 @@ public: virtual ~LLConversationViewSession( void ) { } virtual void selectItem(); void setVisibleIfDetached(BOOL visible); + LLConversationViewParticipant* findParticipant(const LLUUID& participant_id); + + virtual void refresh(); }; // Implementation of conversations list participant (avatar) widgets class LLConversationViewParticipant : public LLFolderViewItem { +public: + struct Params : public LLInitParam::Block<Params, LLFolderViewItem::Params> + { + Optional<LLUUID> participant_id; + + Params(); + }; + protected: friend class LLUICtrlFactory; - LLConversationViewParticipant( const LLFolderViewItem::Params& p ); + LLConversationViewParticipant( const Params& p ); public: virtual ~LLConversationViewParticipant( void ) { } + + bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } + +private: + LLUUID mUUID; // UUID of the participant }; #endif // LL_LLCONVERSATIONVIEW_H diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index aa85e5023d..dfe9e6491d 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -289,6 +289,59 @@ void LLIMFloaterContainer::setMinimized(BOOL b) void LLIMFloaterContainer::draw() { + // CHUI Notes + // Currently, the model is not responsible for creating the view which is a good thing. This means that + // the model could change substantially and the view could decide to echo only a portion of this model. + // Consequently, the participant views need to be created either by the session view or by the container panel. + // For the moment, we create them here (which makes for complicated code...) to conform to the pattern + // implemented in llinventorypanel.cpp (see LLInventoryPanel::buildNewViews()). + // The best however would be to have an observer on the model so that we would not pool on each draw to know + // if the view needs refresh. The current implementation (testing for change on draw) is less + // efficient perf wise than a listener/observer scheme. We will implement that shortly. + + // On each session in mConversationsItems + for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) + { + // Get the current session descriptors + LLConversationItem* session_model = it_session->second; + LLUUID session_id = it_session->first; + LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[session_id]); + // If the session model has been changed, refresh the corresponding view + if (session_model->needsRefresh()) + { + session_view->refresh(); + } + // Iterate through each model participant child + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = session_model->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = session_model->getChildrenEnd(); + while (current_participant_model != end_participant_model) + { + LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); + LLUUID participant_id = participant_model->getUUID(); + LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); + // Is there a corresponding view? If not create it + if (!participant_view) + { + participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(session_view); + mConversationsListPanel->addChild(participant_view); + participant_view->setVisible(TRUE); + } + else + // Else, see if it needs refresh + { + if (participant_model->needsRefresh()) + { + participant_view->refresh(); + } + } + // Reset the need for refresh + session_model->resetRefresh(); + // Next participant + current_participant_model++; + } + } + if (mTabContainer->getTabCount() == 0) { // Do not close the container when every conversation is torn off because the user @@ -536,24 +589,6 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) participant_view->setVisible(TRUE); current_participant_model++; } - // Debugging hack : uncomment to force the creation of a dummy participant - // This hack is to be eventually deleted - if (item->getChildrenCount() == 0) - { - llinfos << "Merov debug : create dummy participant" << llendl; - // Create a dummy participant : we let that leak but that's just for debugging... - std::string name("Debug Test : "); - name += display_name; - LLUUID test_id; - test_id.generate(name); - LLConversationItemParticipant* participant_model = new LLConversationItemParticipant(name, test_id, getRootViewModel()); - // Create the dummy widget - LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); - participant_view->addToFolder(widget); - mConversationsListPanel->addChild(participant_view); - participant_view->setVisible(TRUE); - } - // End debugging hack repositioningWidgets(); @@ -610,7 +645,7 @@ LLConversationViewSession* LLIMFloaterContainer::createConversationItemWidget(LL LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParticipant(LLConversationItem* item) { - LLConversationViewSession::Params params; + LLConversationViewParticipant::Params params; params.name = item->getDisplayName(); //params.icon = bridge->getIcon(); @@ -620,7 +655,7 @@ LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParti params.listener = item; params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; - params.container = this; + params.participant_id = item->getUUID(); return LLUICtrlFactory::create<LLConversationViewParticipant>(params); } -- cgit v1.2.3 From 3cf624b371eace5ec382796d7bd811d181d5e877 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 5 Sep 2012 18:48:07 +0300 Subject: CHUI-268 (Transfer the common functionality from LLNearbyChat and LLIMFloater to LLIMConversation): moved focusLost(), focusReceived and enable/disable of the call button to base class --- indra/newview/llimconversation.cpp | 42 ++++++++++++++++++++++++++++++++++++++ indra/newview/llimconversation.h | 14 +++++++++---- indra/newview/llimfloater.cpp | 39 ----------------------------------- indra/newview/llimfloater.h | 9 -------- indra/newview/llnearbychat.cpp | 23 +-------------------- indra/newview/llnearbychat.h | 7 ------- 6 files changed, 53 insertions(+), 81 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 5a5196fb7e..d8c81a7849 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -31,6 +31,8 @@ #include "llchatentry.h" #include "llchathistory.h" +#include "llchiclet.h" +#include "llchicletbar.h" #include "lldraghandle.h" #include "llfloaterreg.h" #include "llimfloater.h" @@ -53,6 +55,8 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id) , mInputEditorTopPad(0) , mRefreshTimer(new LLTimer()) { + mSession = LLIMModel::getInstance()->findIMSession(mSessionID); + mCommitCallbackRegistrar.add("IMSession.Menu.Action", boost::bind(&LLIMConversation::onIMSessionMenuItemClicked, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", @@ -182,6 +186,44 @@ void LLIMConversation::draw() } } +void LLIMConversation::enableDisableCallBtn() +{ + getChildView("voice_call_btn")->setEnabled( + mSessionID.notNull() + && mSession + && mSession->mSessionInitialized + && LLVoiceClient::getInstance()->voiceEnabled() + && LLVoiceClient::getInstance()->isVoiceWorking() + && mSession->mCallBackEnabled); +} + + +void LLIMConversation::onFocusReceived() +{ + setBackgroundOpaque(true); + + if (mSessionID.notNull()) + { + LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, true); + + if (getVisible()) + { + // suppress corresponding toast only if this floater is visible and have focus + LLIMModel::getInstance()->setActiveSessionID(mSessionID); + LLIMModel::instance().sendNoUnreadMessages(mSessionID); + } + } + + LLTransientDockableFloater::onFocusReceived(); +} + +void LLIMConversation::onFocusLost() +{ + setBackgroundOpaque(false); + LLTransientDockableFloater::onFocusLost(); +} + + void LLIMConversation::buildParticipantList() { if (mIsNearbyChat) diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 26151ad1be..50feb12aed 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -33,6 +33,7 @@ #include "lltransientdockablefloater.h" #include "llviewercontrol.h" #include "lleventtimer.h" +#include "llimview.h" #include "llconversationmodel.h" class LLPanelChatControlPanel; @@ -87,9 +88,6 @@ protected: // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); - // set the enable/disable state for the Call button - virtual void enableDisableCallBtn() = 0; - void buildParticipantList(); void onSortMenuItemClicked(const LLSD& userdata); @@ -99,9 +97,18 @@ protected: /// Update floater header and toolbar buttons when hosted/torn off state is toggled. void updateHeaderAndToolbar(); + // set the enable/disable state for the Call button + virtual void enableDisableCallBtn(); + + // process focus events to set a currently active session + /* virtual */ void onFocusLost(); + /* virtual */ void onFocusReceived(); + bool mIsNearbyChat; bool mIsP2PChat; + LLIMModel::LLIMSession* mSession; + LLLayoutPanel* mParticipantListPanel; LLParticipantList* mParticipantList; LLUUID mSessionID; @@ -119,7 +126,6 @@ private: /// Refreshes the floater at a constant rate. virtual void refresh() = 0; - /** * Adjusts chat history height to fit vertically with input chat field * and avoid overlapping, since input chat field can be vertically expanded. diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index a601561c62..7b475c1e0b 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -92,24 +92,6 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) setDocked(true); } -void LLIMFloater::onFocusLost() -{ - LLIMModel::getInstance()->resetActiveSessionID(); - - LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, false); -} - -void LLIMFloater::onFocusReceived() -{ - LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, true); - - if (getVisible()) - { - // suppress corresponding toast only if this floater is visible and have focus - LLIMModel::getInstance()->setActiveSessionID(mSessionID); - LLIMModel::instance().sendNoUnreadMessages(mSessionID); - } -} // virtual void LLIMFloater::refresh() @@ -513,27 +495,6 @@ void LLIMFloater::boundVoiceChannel() } } -void LLIMFloater::enableDisableCallBtn() -{ - bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() - && LLVoiceClient::getInstance()->isVoiceWorking(); - - if (mSession) - { - bool session_initialized = mSession->mSessionInitialized; - bool callback_enabled = mSession->mCallBackEnabled; - - BOOL enable_connect = - session_initialized && voice_enabled && callback_enabled; - getChildView("voice_call_btn")->setEnabled(enable_connect); - } - else - { - getChildView("voice_call_btn")->setEnabled(false); - } -} - - void LLIMFloater::onCallButtonClicked() { LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 24a8f17feb..7b2c9e7aef 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -134,10 +134,6 @@ public: private: - // process focus events to set a currently active session - /* virtual */ void onFocusLost(); - /* virtual */ void onFocusReceived(); - /*virtual*/ void refresh(); /*virtual*/ void onClickCloseBtn(); @@ -169,9 +165,6 @@ private: void onCallButtonClicked(); - // set the enable/disable state for the Call button - virtual void enableDisableCallBtn(); - void boundVoiceChannel(); // Add the "User is typing..." indicator. @@ -184,8 +177,6 @@ private: static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); - - LLIMModel::LLIMSession* mSession; S32 mLastMessageIndex; EInstantMessage mDialog; diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 25bbc82fee..c2ad8cfda3 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -133,6 +133,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd) setIsChrome(TRUE); mKey = LLSD(); mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); + mSessionID = LLUUID(); setName("nearby_chat"); setIsSingleInstance(TRUE); } @@ -216,21 +217,6 @@ bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata) return false; } -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusReceived() -{ - setBackgroundOpaque(true); - LLIMConversation::onFocusReceived(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusLost() -{ - setBackgroundOpaque(false); - LLIMConversation::onFocusLost(); -} BOOL LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask) { @@ -326,13 +312,6 @@ void LLNearbyChat::setVisible(BOOL visible) } -void LLNearbyChat::enableDisableCallBtn() -{ - // bool btn_enabled = LLAgent::isActionAllowed("speak"); - - getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/); -} - void LLNearbyChat::onTearOffClicked() { LLIMConversation::onTearOffClicked(); diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 4fc5cb7f76..1db7afc01f 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -51,10 +51,6 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); - // focus overrides - /*virtual*/ void onFocusLost(); - /*virtual*/ void onFocusReceived(); - /*virtual*/ void setVisible(BOOL visible); void loadHistory(); @@ -102,9 +98,6 @@ protected: void displaySpeakingIndicator(); - // set the enable/disable state for the Call button - virtual void enableDisableCallBtn(); - // Which non-zero channel did we last chat on? static S32 sLastSpecialChatChannel; -- cgit v1.2.3 From 1229f42ade088f69164b59742305119bacc8f4de Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 5 Sep 2012 18:55:07 -0700 Subject: CHUI-285 : Clear the needs refresh flag when refreshing, comment clean up. --- indra/newview/llconversationview.cpp | 15 ++++++++++++++- indra/newview/llconversationview.h | 1 + indra/newview/llimfloatercontainer.cpp | 1 - 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 2f71e92a7d..9f3df93aba 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -100,7 +100,8 @@ LLConversationViewParticipant* LLConversationViewSession::findParticipant(const void LLConversationViewSession::refresh() { // Refresh the session view from its model data - // LLConversationItemSession* vmi = dynamic_cast<LLConversationItemSession*>(getViewModelItem()); + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); + vmi->resetRefresh(); // Note: for the moment, all that needs to be done is done by LLFolderViewItem::refresh() @@ -122,4 +123,16 @@ LLConversationViewParticipant::LLConversationViewParticipant( const LLConversati { } +void LLConversationViewParticipant::refresh() +{ + // Refresh the participant view from its model data + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); + vmi->resetRefresh(); + + // Note: for the moment, all that needs to be done is done by LLFolderViewItem::refresh() + + // Do the regular upstream refresh + LLFolderViewItem::refresh(); +} + // EOF diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 27ceb2af3b..a3755d9722 100644 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -81,6 +81,7 @@ public: bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } + virtual void refresh(); private: LLUUID mUUID; // UUID of the participant }; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 1be0c5f075..56648d09b5 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -552,7 +552,6 @@ void LLIMFloaterContainer::repositioningWidgets() } } -// CHUI-137 : Temporary implementation of conversations list void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) { bool is_nearby_chat = uuid.isNull(); -- cgit v1.2.3 From 1a913365b594de81de56896a9fbdfd6d8c4f21e0 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Thu, 6 Sep 2012 23:08:10 +0300 Subject: CHUI-319 FIXED ("User has said something new" text shown when navigating chat history with More History button) - Added flag to chat history whether to show notification about unread messages or not --- indra/newview/llchathistory.cpp | 5 +++-- indra/newview/llchathistory.h | 6 +++++- indra/newview/skins/default/xui/en/floater_conversation_preview.xml | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index e3d57ab7ae..3636f9e9d2 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -585,7 +585,8 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) mBottomSeparatorPad(p.bottom_separator_pad), mTopHeaderPad(p.top_header_pad), mBottomHeaderPad(p.bottom_header_pad), - mIsLastMessageFromLog(false) + mIsLastMessageFromLog(false), + mNotifyAboutUnreadMsg(p.notify_unread_msg) { LLTextEditor::Params editor_params(p); editor_params.rect = getLocalRect(); @@ -707,7 +708,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL bool from_me = chat.mFromID == gAgent.getID(); mEditor->setPlainText(use_plain_text_chat_history); - if (!mEditor->scrolledToEnd() && !from_me && !chat.mFromName.empty()) + if (mNotifyAboutUnreadMsg && !mEditor->scrolledToEnd() && !from_me && !chat.mFromName.empty()) { mUnreadChatSources.insert(chat.mFromName); mMoreChatPanel->setVisible(TRUE); diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 28344e6a10..990c52f31b 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -60,6 +60,8 @@ class LLChatHistory : public LLUICtrl Optional<LLTextBox::Params> more_chat_text; + Optional<bool> notify_unread_msg; + Params() : message_header("message_header"), message_separator("message_separator"), @@ -71,7 +73,8 @@ class LLChatHistory : public LLUICtrl bottom_separator_pad("bottom_separator_pad"), top_header_pad("top_header_pad"), bottom_header_pad("bottom_header_pad"), - more_chat_text("more_chat_text") + more_chat_text("more_chat_text"), + notify_unread_msg("notify_unread_msg", true) {} }; @@ -122,6 +125,7 @@ class LLChatHistory : public LLUICtrl LLUUID mLastFromID; LLDate mLastMessageTime; bool mIsLastMessageFromLog; + bool mNotifyAboutUnreadMsg; //std::string mLastMessageTimeStr; std::string mMessageHeaderFilename; diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml index c837a0ee57..28ba03ebe9 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -45,6 +45,7 @@ visible="true" height="310" name="chat_history" + notify_unread_msg="false" parse_highlights="true" parse_urls="true" left="5" -- cgit v1.2.3 From fd17cb601465b3433b647b895baede9b0fd822dd Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Thu, 6 Sep 2012 23:16:22 +0300 Subject: CHUI-320 FIXED (Inconsistent name formatting in conversation log depending if user started conversation or not) - On P2P session started, before creating entry of conversation log, requesting avatar name in form of Display Name (user.name) --- indra/newview/llconversationlog.cpp | 23 ++++++++++++++++++++--- indra/newview/llconversationlog.h | 3 +++ 2 files changed, 23 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 7db6a93709..e80a709203 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -26,6 +26,7 @@ #include "llviewerprecompiledheaders.h" #include "llagent.h" +#include "llavatarnamecache.h" #include "llconversationlog.h" #include "lltrans.h" @@ -152,6 +153,7 @@ void LLConversation::setListenIMFloaterOpened() mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1)); } } + /************************************************************************/ /* LLConversationLogFriendObserver implementation */ /************************************************************************/ @@ -262,9 +264,16 @@ void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); if (session) { - LLConversation conversation(*session); - LLConversationLog::instance().logConversation(conversation); - session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2)); + if (LLIMModel::LLIMSession::P2P_SESSION == session->mSessionType) + { + LLAvatarNameCache::get(session->mOtherParticipantID, boost::bind(&LLConversationLog::onAvatarNameCache, this, _1, _2, session)); + } + else + { + LLConversation conversation(*session); + LLConversationLog::instance().logConversation(conversation); + session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2)); + } } } @@ -425,3 +434,11 @@ void LLConversationLog::onVoiceChannelConnected(const LLUUID& session_id, const } } } + +void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session) +{ + LLConversation conversation(*session); + conversation.setConverstionName(av_name.getCompleteName()); + LLConversationLog::instance().logConversation(conversation); + session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2)); +} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 9fd54c61c9..0d7f0080e5 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -62,6 +62,7 @@ public: void setIsVoice(bool is_voice); void setIsPast (bool is_past) { mIsConversationPast = is_past; } + void setConverstionName(std::string conv_name) { mConversationName = conv_name; } /* * Resets flag of unread offline message to false when im floater with this conversation is opened. @@ -156,6 +157,8 @@ private: bool saveToFile(const std::string& filename); bool loadFromFile(const std::string& filename); + void onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session); + typedef std::vector<LLConversation> conversations_vec_t; std::vector<LLConversation> mConversations; std::set<LLConversationLogObserver*> mObservers; -- cgit v1.2.3 From 973f54ace7706c6e3b12cc3364b4c7ffb1b841c9 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Thu, 6 Sep 2012 23:18:59 +0300 Subject: CHUI-324 FIXED (No sort order field set by default in conversation log) - Corrected value in settings XML --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b98fea7032..593381cb29 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10105,7 +10105,7 @@ <key>Type</key> <string>U32</string> <key>Value</key> - <integer>2</integer> + <integer>1</integer> </map> <key>SortFriendsFirst</key> <map> -- cgit v1.2.3 From 62eb7ec0301c0313cedc2fcb63df8779b22a6d26 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Thu, 6 Sep 2012 23:34:47 +0300 Subject: CHUI-318 FIXED (User cannot navigate forward in chat history viewer once the More History option is selected.) - Added spinner so that user could select desired history page. Also displaying total count of pages. --- indra/newview/llfloaterconversationpreview.cpp | 11 +++++++ indra/newview/llfloaterconversationpreview.h | 3 ++ .../xui/en/floater_conversation_preview.xml | 36 +++++++++++++++++----- 3 files changed, 43 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index 7083fb987d..c9d9d7aa3b 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -29,6 +29,7 @@ #include "llfloaterconversationpreview.h" #include "llimview.h" #include "lllineeditor.h" +#include "llspinctrl.h" #include "lltrans.h" LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id) @@ -69,6 +70,15 @@ BOOL LLFloaterConversationPreview::postBuild() LLLogChat::loadChatHistory(file, mMessages, true); mCurrentPage = mMessages.size() / mPageSize; + mPageSpinner = getChild<LLSpinCtrl>("history_page_spin"); + mPageSpinner->setCommitCallback(boost::bind(&LLFloaterConversationPreview::onMoreHistoryBtnClick, this)); + mPageSpinner->setMinValue(1); + mPageSpinner->setMaxValue(mCurrentPage + 1); + mPageSpinner->set(mCurrentPage + 1); + + std::string total_page_num = llformat("/ %d", mCurrentPage + 1); + getChild<LLTextBox>("page_num_label")->setValue(total_page_num); + return LLFloater::postBuild(); } @@ -128,6 +138,7 @@ void LLFloaterConversationPreview::showHistory() void LLFloaterConversationPreview::onMoreHistoryBtnClick() { + mCurrentPage = mPageSpinner->getValueF32(); if (--mCurrentPage < 0) { return; diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h index 2246a44761..0341e5d2a0 100644 --- a/indra/newview/llfloaterconversationpreview.h +++ b/indra/newview/llfloaterconversationpreview.h @@ -29,6 +29,8 @@ #include "llchathistory.h" #include "llfloater.h" +class LLSpinCtrl; + class LLFloaterConversationPreview : public LLFloater { public: @@ -45,6 +47,7 @@ private: void onMoreHistoryBtnClick(); void showHistory(); + LLSpinCtrl* mPageSpinner; LLChatHistory* mChatHistory; LLUUID mSessionID; int mCurrentPage; diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml index 28ba03ebe9..d74c2c252d 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -51,14 +51,36 @@ left="5" width="390"> </chat_history> - <button + <text follows="bottom|right" + font="SansSerif" height="22" layout="topleft" - name="more_history" - label="More history..." - right="-15" - top_pad="5" - width="100"> - </button> + name="page_label" + right="-110" + top_pad="7" + value="Page" + width="35"> + </text> + <spinner + decimal_digits="0" + follows="bottom|right" + height="23" + increment="1" + label_width="40" + layout="topleft" + left_pad="0" + name="history_page_spin" + top_delta="-3" + width="50"/> + <text + follows="bottom|right" + font="SandSerif" + height="22" + layout="topleft" + name="page_num_label" + left_pad="5" + top_delta="4" + width="40"> + </text> </floater> -- cgit v1.2.3 From ee5e689331ff6ba44cebaf9e9fb48f7bc3f590c4 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 6 Sep 2012 16:32:17 -0700 Subject: CHUI-285 : Completed. Update the names of the participants. --- indra/newview/llconversationmodel.cpp | 8 ++++++++ indra/newview/llconversationmodel.h | 3 +++ indra/newview/llparticipantlist.cpp | 5 ++--- 3 files changed, 13 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index aa21b08ec8..fa49987d15 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -193,6 +193,14 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, { } +void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) +{ + mName = av_name.mDisplayName; + // *TODO : we should also store that one, to be used in the tooltip : av_name.mUsername + // *TODO : we need to request or initiate a list resort + mNeedsRefresh = true; +} + void LLConversationItemParticipant::dumpDebugData() { llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 5947055e0f..26c7a29d76 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -29,6 +29,7 @@ #include "llfolderviewitem.h" #include "llfolderviewmodel.h" +#include "llavatarname.h" // Implementation of conversations list @@ -149,6 +150,8 @@ public: void setIsMuted(bool is_muted) { mIsMuted = is_muted; mNeedsRefresh = true; } void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; } + void onAvatarNameCache(const LLAvatarName& av_name); + void dumpDebugData(); private: diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index fa3432fc89..2282734109 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -652,6 +652,8 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) LLAvatarName avatar_name; bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name); participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.mDisplayName , avatar_id, mRootViewModel); + // Binds avatar's name update callback + LLAvatarNameCache::get(avatar_id, boost::bind(&LLConversationItemParticipant::onAvatarNameCache, participant, _2)); if (mAvatarList) { mAvatarList->getIDs().push_back(avatar_id); @@ -670,9 +672,6 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) mAvalineUpdater->watchAvalineCaller(avatar_id); } - // *TODO : Merov : need to declare and bind a name update callback on that "participant" instance. See LLAvatarListItem::updateAvatarName() for pattern. - // For the moment, we'll get the correct name only if it's already in the name cache (see call to LLAvatarNameCache::get() here above) - // *TODO : Merov : need to update the online/offline status of the participant. // Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id)) -- cgit v1.2.3 From 47fe3b48fe32f9eb810a23d82eb08c11c41ac335 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 10 Sep 2012 13:48:37 +0300 Subject: CHUI-268 (Transfer the common functionality from LLNearbyChat and LLIMFloater to LLIMConversation): moved appendMessage() to base class --- indra/newview/llimconversation.cpp | 40 ++++++++++++++++++++++++++++++++++ indra/newview/llimconversation.h | 5 +++++ indra/newview/llimfloater.cpp | 19 ---------------- indra/newview/llimfloater.h | 1 - indra/newview/llnearbychat.cpp | 44 ++------------------------------------ indra/newview/llnearbychat.h | 2 -- 6 files changed, 47 insertions(+), 64 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index d8c81a7849..ef3b4f7404 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -223,6 +223,46 @@ void LLIMConversation::onFocusLost() LLTransientDockableFloater::onFocusLost(); } +std::string LLIMConversation::appendTime() +{ + time_t utc_time; + utc_time = time_corrected(); + std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" + +LLTrans::getString("TimeMin")+"]"; + + LLSD substitution; + + substitution["datetime"] = (S32) utc_time; + LLStringUtil::format (timeStr, substitution); + + return timeStr; +} + +void LLIMConversation::appendMessage(const LLChat& chat, const LLSD &args) +{ + LLChat& tmp_chat = const_cast<LLChat&>(chat); + + if(tmp_chat.mTimeStr.empty()) + tmp_chat.mTimeStr = appendTime(); + + if (!chat.mMuted) + { + tmp_chat.mFromName = chat.mFromName; + LLSD chat_args; + if (args) chat_args = args; + chat_args["use_plain_text_chat_history"] = + gSavedSettings.getBOOL("PlainTextChatHistory"); + chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); + chat_args["show_names_for_p2p_conv"] = + !mIsP2PChat || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + + if (mChatHistory) + { + mChatHistory->appendMessage(chat, chat_args); + } + } +} + void LLIMConversation::buildParticipantList() { diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 50feb12aed..41a76c206e 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -104,6 +104,11 @@ protected: /* virtual */ void onFocusLost(); /* virtual */ void onFocusReceived(); + // prepare chat's params and out one message to chatHistory + void appendMessage(const LLChat& chat, const LLSD &args = 0); + + std::string appendTime(); + bool mIsNearbyChat; bool mIsP2PChat; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 7b475c1e0b..2474fe0891 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -848,25 +848,6 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) } } -void LLIMFloater::appendMessage(const LLChat& chat, const LLSD &args) -{ - LLChat& tmp_chat = const_cast<LLChat&>(chat); - - if (!chat.mMuted) - { - tmp_chat.mFromName = chat.mFromName; - LLSD chat_args; - if (args) chat_args = args; - chat_args["use_plain_text_chat_history"] = - gSavedSettings.getBOOL("PlainTextChatHistory"); - chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); - chat_args["show_names_for_p2p_conv"] = !mIsP2PChat - || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); - - mChatHistory->appendMessage(chat, chat_args); - } -} - void LLIMFloater::updateMessages() { std::list<LLSD> messages; diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 7b2c9e7aef..e4a67a3d56 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -152,7 +152,6 @@ private: BOOL isInviteAllowed() const; BOOL inviteToSession(const uuid_vec_t& agent_ids); - void appendMessage(const LLChat& chat, const LLSD &args = 0); static void onInputEditorFocusReceived( LLFocusableElement* caller,void* userdata ); static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); static void onInputEditorKeystroke(LLTextEditor* caller, void* userdata); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index c2ad8cfda3..ddd271e23f 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -69,7 +69,7 @@ S32 LLNearbyChat::sLastSpecialChatChannel = 0; -// --- 2 functions in the global namespace :( --- +// --- function in the global namespace :( --- bool isWordsName(const std::string& name) { // checking to see if it's display name plus username in parentheses @@ -89,22 +89,6 @@ bool isWordsName(const std::string& name) } } -std::string appendTime() -{ - time_t utc_time; - utc_time = time_corrected(); - std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" - +LLTrans::getString("TimeMin")+"]"; - - LLSD substitution; - - substitution["datetime"] = (S32) utc_time; - LLStringUtil::format (timeStr, substitution); - - return timeStr; -} - - const S32 EXPANDED_HEIGHT = 266; const S32 COLLAPSED_HEIGHT = 60; const S32 EXPANDED_MIN_HEIGHT = 150; @@ -129,6 +113,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd) mSpeakerMgr(NULL), mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) { + mIsP2PChat = false; mIsNearbyChat = true; setIsChrome(TRUE); mKey = LLSD(); @@ -604,31 +589,6 @@ void LLNearbyChat::sendChat( EChatType type ) } } - -void LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args) -{ - LLChat& tmp_chat = const_cast<LLChat&>(chat); - - if(tmp_chat.mTimeStr.empty()) - tmp_chat.mTimeStr = appendTime(); - - if (!chat.mMuted) - { - tmp_chat.mFromName = chat.mFromName; - LLSD chat_args; - if (args) chat_args = args; - chat_args["use_plain_text_chat_history"] = - gSavedSettings.getBOOL("PlainTextChatHistory"); - chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); - chat_args["show_names_for_p2p_conv"] = true; - - if (mChatHistory) - { - mChatHistory->appendMessage(chat, chat_args); - } - } -} - void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) { appendMessage(chat, args); diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 1db7afc01f..2cbafbfa62 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -108,8 +108,6 @@ protected: private: - // prepare chat's params and out one message to chatHistory - void appendMessage(const LLChat& chat, const LLSD &args = 0); void onNearbySpeakers (); /*virtual*/ void refresh(); -- cgit v1.2.3 From d9309bd16334a7d76da1b02e8fc43117a06ef7b2 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 7 Sep 2012 12:34:21 +0300 Subject: CHUI-323 FIXED (Local chat message panel out of position in Conversation floater): Prevented too early creation LLNearbyChat --- indra/newview/llimconversation.cpp | 28 ++++++++++++++-------------- indra/newview/llnearbychathandler.cpp | 3 ++- indra/newview/llnotificationhandlerutil.cpp | 2 +- indra/newview/llnotificationtiphandler.cpp | 2 +- indra/newview/llviewerwindow.cpp | 6 +++--- 5 files changed, 21 insertions(+), 20 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index ef3b4f7404..216c5bbd70 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -148,7 +148,7 @@ BOOL LLIMConversation::postBuild() updateHeaderAndToolbar(); - mSaveRect = !getHost(); + mSaveRect = isTornOff(); initRectControl(); if (isChatMultiTab()) @@ -349,11 +349,11 @@ void LLIMConversation::hideOrShowTitle() LLView* floater_contents = getChild<LLView>("contents_view"); LLRect floater_rect = getLocalRect(); - S32 top_border_of_contents = floater_rect.mTop - (getHost()? 0 : floater_header_size); + S32 top_border_of_contents = floater_rect.mTop - (isTornOff()? floater_header_size : 0); LLRect handle_rect (0, floater_rect.mTop, floater_rect.mRight, top_border_of_contents); LLRect contents_rect (0, top_border_of_contents, floater_rect.mRight, floater_rect.mBottom); mDragHandle->setShape(handle_rect); - mDragHandle->setVisible(!getHost()); + mDragHandle->setVisible(isTornOff()); floater_contents->setShape(contents_rect); } @@ -371,8 +371,8 @@ void LLIMConversation::hideAllStandardButtons() void LLIMConversation::updateHeaderAndToolbar() { - bool is_hosted = !!getHost(); - if (is_hosted) + bool is_torn_off = !getHost(); + if (!is_torn_off) { hideAllStandardButtons(); } @@ -381,7 +381,7 @@ void LLIMConversation::updateHeaderAndToolbar() // Participant list should be visible only in torn off floaters. bool is_participant_list_visible = - !is_hosted + is_torn_off && gSavedSettings.getBOOL("IMShowControlPanel") && !mIsP2PChat; @@ -389,21 +389,21 @@ void LLIMConversation::updateHeaderAndToolbar() // Display collapse image (<<) if the floater is hosted // or if it is torn off but has an open control panel. - bool is_expanded = is_hosted || is_participant_list_visible; + bool is_expanded = !is_torn_off || is_participant_list_visible; mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); // toggle floater's drag handle and title visibility if (mDragHandle) { - mDragHandle->setTitleVisible(!is_hosted); + mDragHandle->setTitleVisible(is_torn_off); } // The button (>>) should be disabled for torn off P2P conversations. - mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat); + mExpandCollapseBtn->setEnabled(!is_torn_off || !mIsP2PChat); - mTearOffBtn->setImageOverlay(getString(is_hosted? "tear_off_icon" : "return_icon")); + mTearOffBtn->setImageOverlay(getString(is_torn_off? "return_icon" : "tear_off_icon")); - mCloseBtn->setVisible(is_hosted && !mIsNearbyChat); + mCloseBtn->setVisible(!is_torn_off && !mIsNearbyChat); enableDisableCallBtn(); @@ -440,7 +440,7 @@ void LLIMConversation::processChatHistoryStyleUpdate() } } - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); if (nearby_chat) { nearby_chat->reloadMessages(); @@ -510,8 +510,8 @@ void LLIMConversation::onClose(bool app_quitting) void LLIMConversation::onTearOffClicked() { - setFollows(getHost()? FOLLOWS_NONE : FOLLOWS_ALL); - mSaveRect = !getHost(); + setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); + mSaveRect = isTornOff(); initRectControl(); LLFloater::onClickTearOff(this); updateHeaderAndToolbar(); diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index ca3fffeffd..f3e17ea61b 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -487,6 +487,8 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, if(chat_msg.mText.empty()) return;//don't process empty messages + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + // Build notification data LLSD chat; chat["message"] = chat_msg.mText; @@ -537,7 +539,6 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, } } - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); nearby_chat->addMessage(chat_msg, true, args); if(chat_msg.mSourceType == CHAT_SOURCE_AGENT diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 2484040ac4..9fd73746e8 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -181,7 +181,7 @@ void LLHandlerUtil::logGroupNoticeToIMGroup( // static void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type) { - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); if (nearby_chat) { LLChat chat_msg(notification->getMessage()); diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index ef6668247c..a293e6acb6 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -86,7 +86,7 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) // don't show toast if Nearby Chat is opened LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); - if (nearby_chat && nearby_chat->isChatVisible()) + if (nearby_chat->isChatVisible()) { return false; } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 791cadaee4..403288b2fd 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2493,7 +2493,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) return TRUE; } - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); // Traverses up the hierarchy if( keyboard_focus ) @@ -2561,10 +2561,10 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) // If "Pressing letter keys starts local chat" option is selected, we are not in mouselook, // no view has keyboard focus, this is a printable character key (and no modifier key is // pressed except shift), then give focus to nearby chat (STORM-560) - if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && + if ( nearby_chat && gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) { - LLChatEntry* chat_editor = nearby_chat->getChatBox(); + LLChatEntry* chat_editor = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")->getChatBox(); if (chat_editor) { // passing NULL here, character will be added later when it is handled by character handler. -- cgit v1.2.3 From 42dbf23dc56e0ab6842dd14b5701ffdb359f8bb6 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 7 Sep 2012 21:35:08 +0300 Subject: CHUI-325 FIXED (Cap conversation log to 30 days, purge older data on login) - Remove conversations older than 30 days from call log --- indra/newview/llconversationlog.cpp | 22 ++++++++++++++++++++++ indra/newview/llconversationlog.h | 2 ++ 2 files changed, 24 insertions(+) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index e80a709203..cc02e18698 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -30,6 +30,8 @@ #include "llconversationlog.h" #include "lltrans.h" +const int CONVERSATION_LIFETIME = 30; // lifetime of LLConversation is 30 days by spec + struct Conversation_params { Conversation_params(time_t time) @@ -139,6 +141,14 @@ const std::string LLConversation::createTimestamp(const time_t& utc_time) return timeStr; } +bool LLConversation::isOlderThan(U32 days) const +{ + time_t now = time_corrected(); + U32 age = (U32)((now - mTime) / SEC_PER_DAY); // age of conversation in days + + return age > days; +} + void LLConversation::setListenIMFloaterOpened() { LLIMFloater* floater = LLIMFloater::findInstance(mSessionID); @@ -394,10 +404,22 @@ bool LLConversationLog::loadFromFile(const std::string& filename) params.mHistoryFileName = std::string(history_file_name); LLConversation conversation(params); + + // CHUI-325 + // The conversation log should be capped to the last 30 days. Conversations with the last utterance + // being over 30 days old should be purged from the conversation log text file on login. + if (conversation.isOlderThan(CONVERSATION_LIFETIME)) + { + continue; + } + mConversations.push_back(conversation); } fclose(fp); + LLFile::remove(filename); + cache(); + notifyObservers(); return true; } diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 0d7f0080e5..16be37d67a 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -64,6 +64,8 @@ public: void setIsPast (bool is_past) { mIsConversationPast = is_past; } void setConverstionName(std::string conv_name) { mConversationName = conv_name; } + bool isOlderThan(U32 days) const; + /* * Resets flag of unread offline message to false when im floater with this conversation is opened. */ -- cgit v1.2.3 From c26867bb6d1226c82c11f2f386f73b6d8e3ed749 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 7 Sep 2012 19:53:38 -0700 Subject: CHUI-285 : Implement sort, alphabetical only for the moment --- indra/newview/llconversationmodel.cpp | 38 +++++++++++++++++++++++++--------- indra/newview/llconversationmodel.h | 15 +++----------- indra/newview/llimfloatercontainer.cpp | 16 ++++++++++++-- indra/newview/llimfloatercontainer.h | 2 ++ indra/newview/llparticipantlist.cpp | 2 -- 5 files changed, 47 insertions(+), 26 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index fa49987d15..e810bac1d9 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -78,14 +78,6 @@ void LLConversationItem::showProperties(void) { } -bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const -{ - // We compare only by name for the moment - // *TODO : Implement the sorting by date - S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); - return (compare < 0); -} - // // LLConversationItemSession // @@ -197,12 +189,38 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam { mName = av_name.mDisplayName; // *TODO : we should also store that one, to be used in the tooltip : av_name.mUsername - // *TODO : we need to request or initiate a list resort mNeedsRefresh = true; + if (mParent) + { + mParent->requestSort(); + } } void LLConversationItemParticipant::dumpDebugData() { llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; -} +} + +// +// LLConversationSort +// + +bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const +{ + // For the moment, we sort only by name + // *TODO : Implement the sorting by date as well (most recent first) + // *TODO : Check the type of item (session/participants) as order should be different for both (eventually) + S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); + return (compare < 0); +} + +// +// LLConversationViewModel +// + +void LLConversationViewModel::sort(LLFolderViewFolder* folder) +{ + base_t::sort(folder); +} + // EOF diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 26c7a29d76..2775bf8186 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -208,23 +208,14 @@ private: class LLConversationSort { public: - LLConversationSort(U32 order = 0) - : mSortOrder(order), - mByDate(false), - mByName(false) - { - mByDate = (order & LLConversationFilter::SO_DATE); - mByName = (order & LLConversationFilter::SO_NAME); - } + LLConversationSort(U32 order = 0) : mSortOrder(order) { } - bool isByDate() const { return mByDate; } + bool isByDate() const { return (mSortOrder & LLConversationFilter::SO_DATE); } U32 getSortOrder() const { return mSortOrder; } bool operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const; private: U32 mSortOrder; - bool mByDate; - bool mByName; }; class LLConversationViewModel @@ -233,7 +224,7 @@ class LLConversationViewModel public: typedef LLFolderViewModel<LLConversationSort, LLConversationItem, LLConversationItem, LLConversationFilter> base_t; - void sort(LLFolderViewFolder* folder) { } // *TODO : implement conversation sort + void sort(LLFolderViewFolder* folder); bool contentsReady() { return true; } // *TODO : we need to check that participants names are available somewhat bool startDrag(std::vector<LLFolderViewModelItem*>& items) { return false; } // We do not allow drag of conversation items diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 56648d09b5..fa0750c39c 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -45,6 +45,7 @@ #include "lltransientfloatermgr.h" #include "llviewercontrol.h" #include "llconversationview.h" +#include "llcallbacklist.h" // // LLIMFloaterContainer @@ -65,6 +66,8 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) LLIMFloaterContainer::~LLIMFloaterContainer() { + gIdleCallbacks.deleteFunction(idle, this); + mNewMessageConnection.disconnect(); LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); @@ -139,6 +142,9 @@ BOOL LLIMFloaterContainer::postBuild() LLAvatarNameCache::addUseDisplayNamesCallback( boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); + // Add callback: we'll take care of view updates on idle + gIdleCallbacks.addFunction(idle, this); + return TRUE; } @@ -290,6 +296,13 @@ void LLIMFloaterContainer::setMinimized(BOOL b) } } +//static +void LLIMFloaterContainer::idle(void* user_data) +{ + LLIMFloaterContainer* panel = (LLIMFloaterContainer*)user_data; + panel->mConversationsRoot->update(); +} + void LLIMFloaterContainer::draw() { // CHUI Notes @@ -579,7 +592,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) } if (!item) { - llinfos << "Merov debug : Couldn't create conversation session item : " << display_name << llendl; + llwarns << "Couldn't create conversation session item : " << display_name << llendl; return; } // *TODO: Should we flag LLConversationItemSession with a mIsNearbyChat? @@ -602,7 +615,6 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) // Note: usually, we do not get an updated avatar list at that point LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); - llinfos << "Merov debug : create participant, children size = " << item->getChildrenCount() << llendl; while (current_participant_model != end_participant_model) { LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index a72a3e2221..c4dd386d7c 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -75,6 +75,8 @@ public: void collapseMessagesPane(bool collapse); + // Callbacks + static void idle(void* user_data); // LLIMSessionObserver observe triggers /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 2282734109..0d1a37c835 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -675,8 +675,6 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) // *TODO : Merov : need to update the online/offline status of the participant. // Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id)) - llinfos << "Merov debug : added participant, name = " << participant->getName() << llendl; - // Add the participant model to the session's children list addParticipant(participant); -- cgit v1.2.3 From 6df8c2b42066efad4d46a601ecaabbc9bf1dcd91 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Sun, 9 Sep 2012 14:48:06 -0700 Subject: CHUI-285 : Complete. Fix participants repositioning. --- indra/newview/llimfloatercontainer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index fa0750c39c..978b91b598 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -358,6 +358,8 @@ void LLIMFloaterContainer::draw() } } + repositioningWidgets(); + if (mTabContainer->getTabCount() == 0) { // Do not close the container when every conversation is torn off because the user @@ -365,8 +367,6 @@ void LLIMFloaterContainer::draw() collapseMessagesPane(true); } LLFloater::draw(); - - repositioningWidgets(); } void LLIMFloaterContainer::tabClose() -- cgit v1.2.3 From 913375051e2dbe3f1ec68d7b8b86cac613e26ec3 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 10 Sep 2012 16:12:20 +0300 Subject: CHUI-333 (Icons overlap in message panel when maximizing width of conversation list): increaced expanded_min_dim for the message pane --- indra/newview/skins/default/xui/en/floater_im_container.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e439fc9005..413e66738d 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -113,7 +113,7 @@ height="430" name="messages_layout_panel" width="412" - expanded_min_dim="205"> + expanded_min_dim="225"> <panel_container follows="all" height="430" -- cgit v1.2.3 From d79037017e3a1627be848b9162f28ae16fcb6004 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 10 Sep 2012 16:20:47 +0300 Subject: CHUI-332 (Overlap of icons in chrome when collapsing and expanding conversation list) changed expanded_min_dim of the right panel --- indra/newview/skins/default/xui/en/floater_im_container.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 413e66738d..1583add857 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -36,7 +36,7 @@ name="conversations_layout_panel" min_dim="38" width="268" - expanded_min_dim="120"> + expanded_min_dim="165"> <layout_stack animate="false" follows="left|top|right" -- cgit v1.2.3 From 5dc8738076d158aa74a93f7f3630a17d9102fdc4 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 10 Sep 2012 07:40:13 -0700 Subject: CHUI-283: Basic Implementation, just have hard coded avatar icon appearing and profile/info buttons visible. profile/info buttons do not have proper positioning or mouseclick events. --- indra/llcommon/llfoldertype.h | 4 +- indra/llui/llfolderviewitem.cpp | 8 ++- indra/llui/llfolderviewitem.h | 2 +- indra/newview/llconversationmodel.h | 4 +- indra/newview/llconversationview.cpp | 110 ++++++++++++++++++++++++++++++++- indra/newview/llconversationview.h | 42 +++++++++++-- indra/newview/llimfloatercontainer.cpp | 2 +- indra/newview/llviewerfoldertype.cpp | 2 + 8 files changed, 163 insertions(+), 11 deletions(-) mode change 100644 => 100755 indra/llcommon/llfoldertype.h mode change 100644 => 100755 indra/llui/llfolderviewitem.cpp mode change 100644 => 100755 indra/llui/llfolderviewitem.h mode change 100644 => 100755 indra/newview/llconversationmodel.h mode change 100644 => 100755 indra/newview/llconversationview.cpp mode change 100644 => 100755 indra/newview/llconversationview.h mode change 100644 => 100755 indra/newview/llimfloatercontainer.cpp mode change 100644 => 100755 indra/newview/llviewerfoldertype.cpp (limited to 'indra') diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h old mode 100644 new mode 100755 index a0c847914f..6b5ae572a9 --- a/indra/llcommon/llfoldertype.h +++ b/indra/llcommon/llfoldertype.h @@ -89,7 +89,9 @@ public: FT_COUNT, - FT_NONE = -1 + FT_NONE = -1, + + FT_PROFILE = 58 }; static EType lookup(const std::string& type_name); diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp old mode 100644 new mode 100755 index 52923389cd..c46af27a04 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -609,13 +609,14 @@ void LLFolderViewItem::draw() static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + + getViewModelItem()->update(); + const Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); const S32 TOP_PAD = default_params.item_top_pad; const S32 FOCUS_LEFT = 1; const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - getViewModelItem()->update(); - //--------------------------------------------------------------------------------// // Draw open folder arrow // @@ -793,6 +794,9 @@ void LLFolderViewItem::draw() sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, filter_string_length, S32_MAX, &right_x, FALSE ); } + + + LLView::draw(); } const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h old mode 100644 new mode 100755 index 6eacbe8bd0..766d9b3fe3 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -231,7 +231,7 @@ public: virtual void onMouseLeave(S32 x, S32 y, MASK mask); - virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return NULL; } + //virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return LLView::findChildView(name, recurse); } // virtual void handleDropped(); virtual void draw(); diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h old mode 100644 new mode 100755 index 1a2e09dfab..7baabf7f76 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -29,6 +29,7 @@ #include "llfolderviewitem.h" #include "llfolderviewmodel.h" +#include "llviewerfoldertype.h" // Implementation of conversations list @@ -55,7 +56,7 @@ public: virtual const std::string& getSearchableName() const { return mName; } virtual const LLUUID& getUUID() const { return mUUID; } virtual time_t getCreationDate() const { return 0; } - virtual LLPointer<LLUIImage> getIcon() const { return NULL; } + virtual LLPointer<LLUIImage> getIcon() const { return LLUI::getUIImage(LLViewerFolderType::lookupIconName(LLFolderType::FT_PROFILE, FALSE)); } virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } virtual std::string getLabelSuffix() const { return LLStringUtil::null; } @@ -115,6 +116,7 @@ public: LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItemSession() {} + LLPointer<LLUIImage> getIcon() const { return NULL; } void setSessionID(const LLUUID& session_id) { mUUID = session_id; } void addParticipant(LLConversationItemParticipant* participant); void removeParticipant(LLConversationItemParticipant* participant); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp old mode 100644 new mode 100755 index fefb7e9cac..d1a8478697 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -32,9 +32,15 @@ #include "llimconversation.h" #include "llimfloatercontainer.h" + +#include "lluictrlfactory.h" +#include "llavatariconctrl.h" + // // Implementation of conversations list session widgets // + + LLConversationViewSession::Params::Params() : container() @@ -83,9 +89,111 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible) // Implementation of conversations list participant (avatar) widgets // -LLConversationViewParticipant::LLConversationViewParticipant( const LLFolderViewItem::Params& p ): +static LLDefaultChildRegistry::Register<LLConversationViewParticipant> r("conversation_view_participant"); + +LLConversationViewParticipant::Params::Params() : +container(), +view_profile_button("view_profile_button"), +info_button("info_button") +{} + +LLConversationViewParticipant::LLConversationViewParticipant( const LLConversationViewParticipant::Params& p ): LLFolderViewItem(p) +{ + +} + +void LLConversationViewParticipant::initFromParams(const LLConversationViewParticipant::Params& params) +{ + LLButton::Params view_profile_button_params(params.view_profile_button()); + LLButton * button = LLUICtrlFactory::create<LLButton>(view_profile_button_params); + addChild(button); + + LLButton::Params info_button_params(params.info_button()); + button = LLUICtrlFactory::create<LLButton>(info_button_params); + addChild(button); +} + +BOOL LLConversationViewParticipant::postBuild() +{ + mInfoBtn = getChild<LLButton>("info_btn"); + mProfileBtn = getChild<LLButton>("profile_btn"); + + mInfoBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onInfoBtnClick, this)); + mProfileBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onProfileBtnClick, this)); + + + LLFolderViewItem::postBuild(); + return TRUE; +} + +void LLConversationViewParticipant::onInfoBtnClick() +{ + + +} + +void LLConversationViewParticipant::onProfileBtnClick() +{ + +} + +LLButton* LLConversationViewParticipant::createProfileButton() +{ + + LLButton::Params params; + + + //<button + params.follows.flags(FOLLOWS_RIGHT); + //params.height="20"; + LLUIImage * someImage = LLUI::getUIImage("Web_Profile_Off"); + params.image_overlay = someImage; + params.layout="topleft"; + params.left_pad=5; + //params.right="-28"; + params.name="profile_btn"; + params.tab_stop="false"; + params.tool_tip="View profile"; + params.top_delta=-2; + //params.width="20"; + ///> + + + /* + LLConversationViewParticipant::Params params; + + params.name = item->getDisplayName(); + //params.icon = bridge->getIcon(); + //params.icon_open = bridge->getOpenIcon(); + //params.creation_date = bridge->getCreationDate(); + params.root = mConversationsRoot; + params.listener = item; + params.rect = LLRect (0, 0, 0, 0); + params.tool_tip = params.name; + params.container = this; + */ + + LLButton * button = LLUICtrlFactory::create<LLButton>(params); + LLRect someRect; + someRect.setOriginAndSize(30, 0, 20, 20); + button->setShape(someRect); + + //button->follows= "right"; + //button->height = 20; + //button->image_overlay="Web_Profile_Off"; + //button->right = -28; + //button->width = 20; + + + + return button; +} + + +void LLConversationViewParticipant::draw() { + LLFolderViewItem::draw(); } // EOF diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h old mode 100644 new mode 100755 index 5695925f43..a7f468cb27 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -29,6 +29,14 @@ #include "llfolderviewitem.h" + + + +#include "llstyle.h" +#include "llcallbackmap.h" +#include "lltextbox.h" +#include "llbutton.h"; + class LLIMFloaterContainer; // Implementation of conversations list session widgets @@ -57,14 +65,40 @@ public: // Implementation of conversations list participant (avatar) widgets +class LLAvatarIconCtrl; + class LLConversationViewParticipant : public LLFolderViewItem { + +public: + + struct Params : public LLInitParam::Block<Params, LLFolderViewItem::Params> + { + Optional<LLIMFloaterContainer*> container; + Optional<LLButton::Params> view_profile_button, + info_button; + + Params(); + }; + + virtual ~LLConversationViewParticipant( void ) { } + virtual void draw(); + protected: - friend class LLUICtrlFactory; - LLConversationViewParticipant( const LLFolderViewItem::Params& p ); + friend class LLUICtrlFactory; + LLConversationViewParticipant( const Params& p ); + void initFromParams(const Params& params); + BOOL postBuild(); + + void onInfoBtnClick(); + void onProfileBtnClick(); -public: - virtual ~LLConversationViewParticipant( void ) { } +private: + LLButton* createProfileButton(); + LLButton * mInfoBtn; + LLButton * mProfileBtn; + + }; #endif // LL_LLCONVERSATIONVIEW_H diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp old mode 100644 new mode 100755 index 5261d30cd9..9758f5a93e --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -634,7 +634,7 @@ LLConversationViewSession* LLIMFloaterContainer::createConversationItemWidget(LL LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParticipant(LLConversationItem* item) { - LLConversationViewSession::Params params; + LLConversationViewParticipant::Params params; params.name = item->getDisplayName(); //params.icon = bridge->getIcon(); diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp old mode 100644 new mode 100755 index a179b61cff..d470abb8c5 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -147,6 +147,8 @@ LLViewerFolderDictionary::LLViewerFolderDictionary() addEntry((LLFolderType::EType)type, new ViewerFolderEntry("New Folder", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, false)); } #endif + + addEntry(LLFolderType::FT_PROFILE, new ViewerFolderEntry("Profile", "Generic_Person", "Generic_Person", FALSE, false, "default")); } bool LLViewerFolderDictionary::initEnsemblesFromFile() -- cgit v1.2.3 From 8366efc339e7eca3918d7246b3bb7a9ba61ce765 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 10 Sep 2012 08:38:49 -0700 Subject: CHUI-283, fixed a build problem and also added a missing file. --- indra/newview/llconversationview.h | 2 +- .../en/widgets/conversation_view_participant.xml | 33 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100755 indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml (limited to 'indra') diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index a7f468cb27..0a008475a3 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -35,7 +35,7 @@ #include "llstyle.h" #include "llcallbackmap.h" #include "lltextbox.h" -#include "llbutton.h"; +#include "llbutton.h" class LLIMFloaterContainer; diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml new file mode 100755 index 0000000000..0cff25e083 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<conversation_view_participant + folder_arrow_image="ForSale_Badge" + folder_indentation="8" + item_height="20" + item_top_pad="4" + selection_image="Rounded_Square" + mouse_opaque="true" + follows="left|top|right" +> +<view_profile_button + height="20" + image_overlay="Web_Profile_Off" + layout="topleft" + left_pad="5" + right="200" + name="profile_btn" + tab_stop="false" + tool_tip="View profile" + top_delta="-2" + width="20" /> + <info_button + height="16" + image_pressed="Info_Press" + image_unselected="Info_Over" + layout="topleft" + left_pad="3" + right="225" + name="info_btn" + tab_stop="false" + top_delta="0" + width="16" /> +</conversation_view_participant> -- cgit v1.2.3 From be06bebffcc1a08c3018ab3712048599455e025b Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Mon, 10 Sep 2012 20:12:27 +0300 Subject: CHUI-282 WIP Modified conversation view item and IM floater container so that the folder view handles the positioning of items in conversations list. --- indra/llui/llfolderviewitem.h | 1 - indra/newview/llconversationview.cpp | 170 ++++++++++++++++++++- indra/newview/llconversationview.h | 13 +- indra/newview/llimfloatercontainer.cpp | 60 ++++++-- indra/newview/llimfloatercontainer.h | 2 + indra/newview/llinventoryicon.h | 2 +- .../xui/en/panel_conversation_list_item.xml | 78 ++++++++++ 7 files changed, 307 insertions(+), 19 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/panel_conversation_list_item.xml (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 6eacbe8bd0..141956c3f0 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -113,7 +113,6 @@ protected: static LLFontGL* getLabelFontForStyle(U8 style); -private: BOOL mIsSelected; public: diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 9f3df93aba..514bf38b00 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -42,10 +42,173 @@ LLConversationViewSession::Params::Params() : LLConversationViewSession::LLConversationViewSession( const LLConversationViewSession::Params& p ): LLFolderViewFolder(p), - mContainer(p.container) + mContainer(p.container), + mItemPanel(NULL), + mSessionTitle(NULL) { } +BOOL LLConversationViewSession::postBuild() +{ + LLFolderViewItem::postBuild(); + + mItemPanel = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>("panel_conversation_list_item.xml", NULL, LLPanel::child_registry_t::instance()); + + addChild(mItemPanel); + + mSessionTitle = mItemPanel->getChild<LLTextBox>("conversation_title"); + + refresh(); + + return TRUE; +} + +void LLConversationViewSession::draw() +{ + if (mAutoOpenCountdown != 0.f) + { + mControlLabelRotation = mAutoOpenCountdown * -90.f; + } + else if (isOpen()) + { + mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); + } + else + { + mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); + } + + const LLColor4U DEFAULT_WHITE(255, 255, 255); + + static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + + const LLFolderViewItem::Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); + const S32 TOP_PAD = default_params.item_top_pad; + const S32 FOCUS_LEFT = 1; + + getViewModelItem()->update(); + + //--------------------------------------------------------------------------------// + // Draw open folder arrow + // + if (hasVisibleChildren() || getViewModelItem()->hasChildren()) + { + LLUIImage* arrow_image = default_params.folder_arrow_image; + gl_draw_scaled_rotated_image( + mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD - TOP_PAD, + ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, arrow_image->getImage(), sFgColor); + } + + + //--------------------------------------------------------------------------------// + // Draw highlight for selected items + // + const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); + const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled + const S32 focus_top = getRect().getHeight(); + const S32 focus_bottom = getRect().getHeight() - mItemHeight; + const bool folder_open = (getRect().getHeight() > mItemHeight + 4); + if (mIsSelected) // always render "current" item. Only render other selected items if mShowSingleSelection is FALSE + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLColor4 bg_color = sHighlightBgColor; + if (!mIsCurSelection) + { + // do time-based fade of extra objects + F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); + if (getRoot() && getRoot()->getShowSingleSelection()) + { + // fading out + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); + } + else + { + // fading in + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); + } + } + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + bg_color, filled); + if (mIsCurSelection) + { + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + sFocusOutlineColor, FALSE); + } + if (folder_open) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect + getRect().getWidth() - 2, + 0, + sFocusOutlineColor, FALSE); + if (show_context) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, + getRect().getWidth() - 2, + 0, + sHighlightBgColor, TRUE); + } + } + } + else if (mIsMouseOverTitle) + { + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + sMouseOverColor, FALSE); + } + + //--------------------------------------------------------------------------------// + // Draw DragNDrop highlight + // + if (mDragAndDropTarget) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + sHighlightBgColor, FALSE); + if (folder_open) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect + getRect().getWidth() - 2, + 0, + sHighlightBgColor, FALSE); + } + mDragAndDropTarget = FALSE; + } + + LLView::draw(); + + mExpanderHighlighted = FALSE; +} + +// virtual +S32 LLConversationViewSession::arrange(S32* width, S32* height) +{ + LLRect rect(getIndentation() + ARROW_SIZE, + getLocalRect().mTop, + getLocalRect().mRight, + getLocalRect().mTop - getItemHeight()); + mItemPanel->setRect(rect); + mItemPanel->reshape(rect.getWidth(), rect.getHeight()); + + return LLFolderViewFolder::arrange(width, height); +} + void LLConversationViewSession::selectItem() { LLFolderViewItem::selectItem(); @@ -103,6 +266,11 @@ void LLConversationViewSession::refresh() LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); vmi->resetRefresh(); + if (mSessionTitle) + { + mSessionTitle->setText(vmi->getDisplayName()); + } + // Note: for the moment, all that needs to be done is done by LLFolderViewItem::refresh() // Do the regular upstream refresh diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index a3755d9722..ec99b2eb9b 100644 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -29,6 +29,7 @@ #include "llfolderviewitem.h" +class LLTextBox; class LLIMFloaterContainer; class LLConversationViewSession; class LLConversationViewParticipant; @@ -53,11 +54,21 @@ protected: public: virtual ~LLConversationViewSession( void ) { } - virtual void selectItem(); + virtual void selectItem(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); + + /*virtual*/ S32 arrange(S32* width, S32* height); + void setVisibleIfDetached(BOOL visible); LLConversationViewParticipant* findParticipant(const LLUUID& participant_id); virtual void refresh(); + +private: + LLPanel* mItemPanel; + LLTextBox* mSessionTitle; }; // Implementation of conversations list participant (avatar) widgets diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 480f964939..9157d16aea 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -38,6 +38,7 @@ #include "llavataractions.h" #include "llavatariconctrl.h" #include "llavatarnamecache.h" +#include "llcallbacklist.h" #include "llgroupiconctrl.h" #include "llfloateravatarpicker.h" #include "llfloaterpreference.h" @@ -76,6 +77,8 @@ LLIMFloaterContainer::~LLIMFloaterContainer() { LLIMMgr::getInstance()->removeSessionObserver(this); } + + gIdleCallbacks.deleteFunction(idle, (void*)this); } void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) @@ -117,16 +120,31 @@ BOOL LLIMFloaterContainer::postBuild() // CHUI-98 : View Model for conversations LLConversationItem* base_item = new LLConversationItem(getRootViewModel()); - LLFolderView::Params p; - p.view_model = &mConversationViewModel; - p.parent_panel = mConversationsListPanel; - p.rect = mConversationsListPanel->getLocalRect(); - p.follows.flags = FOLLOWS_ALL; - p.listener = base_item; - p.root = NULL; + LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); + p.name = getName(); + p.title = getLabel(); + p.rect = LLRect(0, 0, getRect().getWidth(), 0); + p.parent_panel = mConversationsListPanel; + p.tool_tip = p.name; + p.listener = base_item; + p.view_model = &mConversationViewModel; + p.root = NULL; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); - mConversationsListPanel->addChild(mConversationsRoot); + + // Scroller + LLRect scroller_view_rect = mConversationsListPanel->getRect(); + scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); + LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>()); + scroller_params.rect(scroller_view_rect); + + LLScrollContainer* scroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); + scroller->setFollowsAll(); + mConversationsListPanel->addChild(scroller); + scroller->addChild(mConversationsRoot); + mConversationsRoot->setScrollContainer(scroller); + mConversationsRoot->setFollowsAll(); + mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); addConversationListItem(LLUUID()); // manually add nearby chat @@ -149,6 +167,9 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsPane->handleReshape(list_size, TRUE); } + + gIdleCallbacks.addFunction(idle, (void*)this); + mInitialized = true; return TRUE; } @@ -301,6 +322,13 @@ void LLIMFloaterContainer::setMinimized(BOOL b) } } +// static +void LLIMFloaterContainer::idle(void* user_data) +{ + LLIMFloaterContainer* self = static_cast<LLIMFloaterContainer*>(user_data); + self->mConversationsRoot->update(); +} + void LLIMFloaterContainer::draw() { // CHUI Notes @@ -338,7 +366,6 @@ void LLIMFloaterContainer::draw() { participant_view = createConversationViewParticipant(participant_model); participant_view->addToFolder(session_view); - mConversationsListPanel->addChild(participant_view); participant_view->setVisible(TRUE); } else @@ -363,8 +390,6 @@ void LLIMFloaterContainer::draw() collapseMessagesPane(true); } LLFloater::draw(); - - repositioningWidgets(); } void LLIMFloaterContainer::tabClose() @@ -616,7 +641,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) widget->addToFolder(mConversationsRoot); // Add it to the UI - mConversationsListPanel->addChild(widget); +// mConversationsListPanel->addChild(widget); widget->setVisible(TRUE); // Create the participants widgets now @@ -629,12 +654,16 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); participant_view->addToFolder(widget); - mConversationsListPanel->addChild(participant_view); - participant_view->setVisible(TRUE); +// mConversationsListPanel->addChild(participant_view); +// participant_view->setVisible(TRUE); current_participant_model++; } - repositioningWidgets(); + S32 width = 0; + S32 height = 0; + mConversationsRoot->arrange(&width, &height); + +// repositioningWidgets(); return; } @@ -678,6 +707,7 @@ LLConversationViewSession* LLIMFloaterContainer::createConversationItemWidget(LL //params.icon = bridge->getIcon(); //params.icon_open = bridge->getOpenIcon(); //params.creation_date = bridge->getCreationDate(); + params.item_height = 24; params.root = mConversationsRoot; params.listener = item; params.rect = LLRect (0, 0, 0, 0); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 53e3849600..427baa03e3 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -71,6 +71,8 @@ public: static LLIMFloaterContainer* getInstance(); + static void idle(void* user_data); + virtual void setMinimized(BOOL b); void collapseMessagesPane(bool collapse); diff --git a/indra/newview/llinventoryicon.h b/indra/newview/llinventoryicon.h index c7e2998a20..5c8acf9e85 100644 --- a/indra/newview/llinventoryicon.h +++ b/indra/newview/llinventoryicon.h @@ -1,5 +1,5 @@ /** - * @file llinventoryfunctions.h + * @file llinventoryicon.h * @brief Miscellaneous inventory-related functions and classes * class definition * diff --git a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml new file mode 100644 index 0000000000..d1f25b45fe --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="left|top|right" + height="24" + layout="topleft" + mouse_opaque="flase" + name="conversation_list_item" + width="120"> + <avatar_icon + follows="top|left" + height="20" + default_icon_name="Generic_Person" + layout="topleft" + left="5" + mouse_opaque="true" + top="2" + width="20" /> + <layout_stack + animate="false" + follows="all" + height="24" + layout="topleft" + left_pad="5" + name="caonversation_item_stack" + orientation="horizontal" + top="0" + width="90"> + <layout_panel + auto_resize="false" + user_resize="false" + height="24" + name="call_icon_panel" + visible="false" + width="20"> + <icon + height="20" + follows="top|right|left" + image_name="Conv_toolbar_hang_up" + layout="topleft" + left="0" + name="selected_icon" + top="2" + width="20" /> + </layout_panel> + <layout_panel + auto_resize="true" + user_resize="false" + left_pad="0" + height="24" + name="conversation_title_panel" + min_dim="50" + width="70" + expanded_min_dim="50"> + <text + follows="left|top|right" + font="SansSerifSmall" + height="15" + layout="topleft" + left="5" + name="conversation_title" + parse_urls="false" + top="6" + use_ellipses="true" + value="(loading)" + width="35" /> + <output_monitor + auto_update="true" + follows="top|right" + draw_border="false" + height="16" + layout="topleft" + left_pad="5" + mouse_opaque="true" + name="speaking_indicator" + width="20" /> + </layout_panel> + </layout_stack> +</panel> -- cgit v1.2.3 From 20b95f6ac0a63ce36cb1a7f51505bbf9ef8015c2 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 10 Sep 2012 11:02:13 -0700 Subject: Attempt to fix Linux build --- indra/newview/llfloaterconversationpreview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index c9d9d7aa3b..9ea35fcbad 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -138,7 +138,7 @@ void LLFloaterConversationPreview::showHistory() void LLFloaterConversationPreview::onMoreHistoryBtnClick() { - mCurrentPage = mPageSpinner->getValueF32(); + mCurrentPage = (int)(mPageSpinner->getValueF32()); if (--mCurrentPage < 0) { return; -- cgit v1.2.3 From ef39011f433d93ea72cf636d4c415b468f776a01 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 10 Sep 2012 11:09:05 -0700 Subject: CHUI-283: Now displaying the speaker icon instead of the profile icon --- indra/newview/llconversationview.cpp | 24 +++++++------------- indra/newview/llconversationview.h | 9 ++++---- .../en/widgets/conversation_view_participant.xml | 26 +++++++++++----------- 3 files changed, 25 insertions(+), 34 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index d1a8478697..9c1c9aa225 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -93,8 +93,8 @@ static LLDefaultChildRegistry::Register<LLConversationViewParticipant> r("conver LLConversationViewParticipant::Params::Params() : container(), -view_profile_button("view_profile_button"), -info_button("info_button") +info_button("info_button"), +output_monitor("output_monitor") {} LLConversationViewParticipant::LLConversationViewParticipant( const LLConversationViewParticipant::Params& p ): @@ -104,23 +104,20 @@ LLConversationViewParticipant::LLConversationViewParticipant( const LLConversati } void LLConversationViewParticipant::initFromParams(const LLConversationViewParticipant::Params& params) -{ - LLButton::Params view_profile_button_params(params.view_profile_button()); - LLButton * button = LLUICtrlFactory::create<LLButton>(view_profile_button_params); - addChild(button); - +{ LLButton::Params info_button_params(params.info_button()); - button = LLUICtrlFactory::create<LLButton>(info_button_params); + LLButton * button = LLUICtrlFactory::create<LLButton>(info_button_params); addChild(button); + + LLOutputMonitorCtrl::Params output_monitor_params(params.output_monitor()); + LLOutputMonitorCtrl * outputMonitor = LLUICtrlFactory::create<LLOutputMonitorCtrl>(output_monitor_params); + addChild(outputMonitor); } BOOL LLConversationViewParticipant::postBuild() { mInfoBtn = getChild<LLButton>("info_btn"); - mProfileBtn = getChild<LLButton>("profile_btn"); - mInfoBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onInfoBtnClick, this)); - mProfileBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onProfileBtnClick, this)); LLFolderViewItem::postBuild(); @@ -131,11 +128,6 @@ void LLConversationViewParticipant::onInfoBtnClick() { -} - -void LLConversationViewParticipant::onProfileBtnClick() -{ - } LLButton* LLConversationViewParticipant::createProfileButton() diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 0a008475a3..98eb32d44e 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -36,6 +36,7 @@ #include "llcallbackmap.h" #include "lltextbox.h" #include "llbutton.h" +#include "lloutputmonitorctrl.h" class LLIMFloaterContainer; @@ -75,9 +76,9 @@ public: struct Params : public LLInitParam::Block<Params, LLFolderViewItem::Params> { Optional<LLIMFloaterContainer*> container; - Optional<LLButton::Params> view_profile_button, - info_button; - + Optional<LLButton::Params> info_button; + Optional<LLOutputMonitorCtrl::Params> output_monitor; + Params(); }; @@ -91,12 +92,10 @@ protected: BOOL postBuild(); void onInfoBtnClick(); - void onProfileBtnClick(); private: LLButton* createProfileButton(); LLButton * mInfoBtn; - LLButton * mProfileBtn; }; diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml index 0cff25e083..0b5c1b9511 100755 --- a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml +++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml @@ -8,26 +8,26 @@ mouse_opaque="true" follows="left|top|right" > -<view_profile_button - height="20" - image_overlay="Web_Profile_Off" - layout="topleft" - left_pad="5" - right="200" - name="profile_btn" - tab_stop="false" - tool_tip="View profile" - top_delta="-2" - width="20" /> - <info_button +<info_button height="16" image_pressed="Info_Press" image_unselected="Info_Over" layout="topleft" left_pad="3" - right="225" + right="200" name="info_btn" tab_stop="false" top_delta="0" width="16" /> +<output_monitor + auto_update="true" + draw_border="false" + height="16" + layout="topleft" + left_pad="5" + right="225" + mouse_opaque="true" + name="speaking_indicator" + visible="true" + width="20" /> </conversation_view_participant> -- cgit v1.2.3 From 1e2dcbfb3fbc8717ea594365ff165115b29df83a Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Tue, 11 Sep 2012 17:45:49 +0300 Subject: CHUI-326 FIXED (One entry per conversation with a user in conversation log timestamped with most recent utterance/activity.) - Modified LLConversationLog to show only one entry per conversation with user. I.e. there can't be two conversations with the same session_id in LLConversationLog. - Got rid of processing voice sessions - Refactored creation of conversation in LLConversationLog - Refactored a little bit LLConversation and LLConversationLog: function names and made some functions private --- indra/newview/llconversationlog.cpp | 141 ++++++++++++++++------------ indra/newview/llconversationlog.h | 44 +++++---- indra/newview/llconversationloglist.cpp | 57 ++++++++--- indra/newview/llconversationloglist.h | 9 ++ indra/newview/llconversationloglistitem.cpp | 10 ++ indra/newview/llconversationloglistitem.h | 8 +- indra/newview/llfloaterconversationlog.cpp | 12 +-- indra/newview/llfloaterconversationlog.h | 5 - 8 files changed, 187 insertions(+), 99 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index cc02e18698..239a89015f 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -37,7 +37,7 @@ struct Conversation_params Conversation_params(time_t time) : mTime(time), mTimestamp(LLConversation::createTimestamp(time)), - mIsConversationPast(true) + mIsVoice(false) {} time_t mTime; @@ -48,7 +48,6 @@ struct Conversation_params LLUUID mSessionID; LLUUID mParticipantID; bool mIsVoice; - bool mIsConversationPast; bool mHasOfflineIMs; }; @@ -65,7 +64,6 @@ LLConversation::LLConversation(const Conversation_params& params) mSessionID(params.mSessionID), mParticipantID(params.mParticipantID), mIsVoice(params.mIsVoice), - mIsConversationPast(params.mIsConversationPast), mHasOfflineIMs(params.mHasOfflineIMs) { setListenIMFloaterOpened(); @@ -80,7 +78,6 @@ LLConversation::LLConversation(const LLIMModel::LLIMSession& session) mSessionID(session.mSessionID), mParticipantID(session.mOtherParticipantID), mIsVoice(session.mStartedAsIMCall), - mIsConversationPast(false), mHasOfflineIMs(session.mHasOfflineMessage) { setListenIMFloaterOpened(); @@ -96,7 +93,6 @@ LLConversation::LLConversation(const LLConversation& conversation) mSessionID = conversation.getSessionID(); mParticipantID = conversation.getParticipantID(); mIsVoice = conversation.isVoice(); - mIsConversationPast = conversation.isConversationPast(); mHasOfflineIMs = conversation.hasOfflineMessages(); setListenIMFloaterOpened(); @@ -107,12 +103,10 @@ LLConversation::~LLConversation() mIMFloaterShowedConnection.disconnect(); } -void LLConversation::setIsVoice(bool is_voice) +void LLConversation::updateTimestamp() { - if (mIsConversationPast) - return; - - mIsVoice = is_voice; + mTime = time_corrected(); + mTimestamp = createTimestamp(mTime); } void LLConversation::onIMFloaterShown(const LLUUID& session_id) @@ -154,14 +148,18 @@ void LLConversation::setListenIMFloaterOpened() LLIMFloater* floater = LLIMFloater::findInstance(mSessionID); bool has_offline_ims = !mIsVoice && mHasOfflineIMs; - bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); + bool offline_ims_visible = LLIMFloater::isVisible(floater) && floater->hasFocus(); // we don't need to listen for im floater with this conversation is opened // if floater is already opened or this conversation doesn't have unread offline messages - if (has_offline_ims && !ims_are_read) + if (has_offline_ims && !offline_ims_visible) { mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1)); } + else + { + mHasOfflineIMs = false; + } } /************************************************************************/ @@ -205,6 +203,7 @@ LLConversationLog::LLConversationLog() if (ctrl->getValue().asBoolean()) { LLIMMgr::instance().addSessionObserver(this); + newMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); } } @@ -218,17 +217,80 @@ void LLConversationLog::observeIMSession() if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) { LLIMMgr::instance().addSessionObserver(this); + LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); } else { LLIMMgr::instance().removeSessionObserver(this); + newMessageSignalConnection.disconnect(); } } -void LLConversationLog::logConversation(const LLConversation& conversation) +void LLConversationLog::logConversation(const LLUUID& session_id) { - mConversations.push_back(conversation); - notifyObservers(); + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); + LLConversation* conversation = findConversation(session_id); + + if (session && conversation) + { + updateConversationTimestamp(conversation); + } + else if (session && !conversation) + { + createConversation(session_id); + } +} + +void LLConversationLog::createConversation(const LLUUID& session_id) +{ + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); + + if (session) + { + LLConversation conversation(*session); + mConversations.push_back(conversation); + + if (LLIMModel::LLIMSession::P2P_SESSION == session->mSessionType) + { + LLAvatarNameCache::get(session->mOtherParticipantID, boost::bind(&LLConversationLog::onAvatarNameCache, this, _1, _2, session)); + } + + notifyObservers(); + } +} + +void LLConversationLog::updateConversationName(const LLUUID& session_id, const std::string& name) +{ + LLConversation* conversation = findConversation(session_id); + + if (conversation) + { + conversation->setConverstionName(name); + notifyPrticularConversationObservers(session_id, LLConversationLogObserver::CHANGED_NAME); + } +} + +void LLConversationLog::updateConversationTimestamp(LLConversation* conversation) +{ + if (conversation) + { + conversation->updateTimestamp(); + notifyPrticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_TIME); + } +} + +LLConversation* LLConversationLog::findConversation(const LLUUID& session_id) +{ + conversations_vec_t::iterator conv_it = mConversations.begin(); + for(; conv_it != mConversations.end(); ++conv_it) + { + if (conv_it->getSessionID() == session_id) + { + return &*conv_it; + } + } + + return NULL; } void LLConversationLog::removeConversation(const LLConversation& conversation) @@ -271,34 +333,7 @@ void LLConversationLog::removeObserver(LLConversationLogObserver* observer) void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); - if (session) - { - if (LLIMModel::LLIMSession::P2P_SESSION == session->mSessionType) - { - LLAvatarNameCache::get(session->mOtherParticipantID, boost::bind(&LLConversationLog::onAvatarNameCache, this, _1, _2, session)); - } - else - { - LLConversation conversation(*session); - LLConversationLog::instance().logConversation(conversation); - session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2)); - } - } -} - -void LLConversationLog::sessionRemoved(const LLUUID& session_id) -{ - conversations_vec_t::reverse_iterator rev_iter = mConversations.rbegin(); - - for (; rev_iter != mConversations.rend(); ++rev_iter) - { - if (rev_iter->getSessionID() == session_id && !rev_iter->isConversationPast()) - { - rev_iter->setIsPast(true); - return; // return here because only one session with session_id may be active - } - } + logConversation(session_id); } void LLConversationLog::cache() @@ -442,25 +477,13 @@ void LLConversationLog::notifyPrticularConversationObservers(const LLUUID& sessi } } -void LLConversationLog::onVoiceChannelConnected(const LLUUID& session_id, const LLVoiceChannel::EState& state) +void LLConversationLog::onNewMessageReceived(const LLSD& data) { - conversations_vec_t::reverse_iterator rev_iter = mConversations.rbegin(); - - for (; rev_iter != mConversations.rend(); ++rev_iter) - { - if (rev_iter->getSessionID() == session_id && !rev_iter->isConversationPast() && LLVoiceChannel::STATE_CALL_STARTED == state) - { - rev_iter->setIsVoice(true); - notifyPrticularConversationObservers(session_id, LLConversationLogObserver::VOICE_STATE); - return; // return here because only one session with session_id may be active - } - } + const LLUUID session_id = data["session_id"].asUUID(); + logConversation(session_id); } void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session) { - LLConversation conversation(*session); - conversation.setConverstionName(av_name.getCompleteName()); - LLConversationLog::instance().logConversation(conversation); - session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2)); + updateConversationName(session->mSessionID, av_name.getCompleteName()); } diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 16be37d67a..ffd27f7e20 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -57,15 +57,18 @@ public: const std::string& getTimestamp() const { return mTimestamp; } const time_t& getTime() const { return mTime; } bool isVoice() const { return mIsVoice; } - bool isConversationPast() const { return mIsConversationPast; } bool hasOfflineMessages() const { return mHasOfflineIMs; } void setIsVoice(bool is_voice); - void setIsPast (bool is_past) { mIsConversationPast = is_past; } void setConverstionName(std::string conv_name) { mConversationName = conv_name; } bool isOlderThan(U32 days) const; + /* + * updates last interaction time + */ + void updateTimestamp(); + /* * Resets flag of unread offline message to false when im floater with this conversation is opened. */ @@ -86,7 +89,7 @@ private: boost::signals2::connection mIMFloaterShowedConnection; - time_t mTime; // start time of conversation + time_t mTime; // last interaction time SessionType mConversationType; std::string mConversationName; std::string mHistoryFileName; @@ -94,8 +97,7 @@ private: LLUUID mParticipantID; bool mIsVoice; bool mHasOfflineIMs; - bool mIsConversationPast; // once session is finished conversation became past forever - std::string mTimestamp; // conversation start time in form of: mm/dd/yyyy hh:mm + std::string mTimestamp; // last interaction time in form of: mm/dd/yyyy hh:mm }; /** @@ -112,32 +114,26 @@ class LLConversationLog : public LLSingleton<LLConversationLog>, LLIMSessionObse friend class LLSingleton<LLConversationLog>; public: - /** - * adds conversation to the conversation list and notifies observers - */ - void logConversation(const LLConversation& conversation); void removeConversation(const LLConversation& conversation); /** * Returns first conversation with matched session_id */ - const LLConversation* getConversation(const LLUUID& session_id); + const LLConversation* getConversation(const LLUUID& session_id); + const std::vector<LLConversation>& getConversations() { return mConversations; } void addObserver(LLConversationLogObserver* observer); void removeObserver(LLConversationLogObserver* observer); - const std::vector<LLConversation>& getConversations() { return mConversations; } - // LLIMSessionObserver triggers virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); - virtual void sessionRemoved(const LLUUID& session_id); + virtual void sessionRemoved(const LLUUID& session_id){} // Stub virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){}; // Stub virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){}; // Stub void notifyObservers(); - void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask); - void onVoiceChannelConnected(const LLUUID& session_id, const LLVoiceChannel::EState& state); + void onNewMessageReceived(const LLSD& data); /** * public method which is called on viewer exit to save conversation log @@ -148,6 +144,13 @@ private: LLConversationLog(); + /** + * adds conversation to the conversation list and notifies observers + */ + void logConversation(const LLUUID& session_id); + + void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask); + void observeIMSession(); /** @@ -161,11 +164,19 @@ private: void onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session); + void createConversation(const LLUUID& session_id); + void updateConversationTimestamp(LLConversation* conversation); + void updateConversationName(const LLUUID& session_id, const std::string& name); + + LLConversation* findConversation(const LLUUID& session_id); + typedef std::vector<LLConversation> conversations_vec_t; std::vector<LLConversation> mConversations; std::set<LLConversationLogObserver*> mObservers; LLFriendObserver* mFriendObserver; // Observer of the LLAvatarTracker instance + + boost::signals2::connection newMessageSignalConnection; }; class LLConversationLogObserver @@ -174,7 +185,8 @@ public: enum EConversationChange { - VOICE_STATE = 1 + CHANGED_TIME = 1, // last interaction time changed + CHANGED_NAME = 2 // conversation name changed }; virtual ~LLConversationLogObserver(){} diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index d39e090c22..429e99f7ad 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -143,22 +143,32 @@ void LLConversationLogList::changed() void LLConversationLogList::changed(const LLUUID& session_id, U32 mask) { - if (mask & LLConversationLogObserver::VOICE_STATE) + LLConversationLogListItem* item = getConversationLogListItem(session_id); + + if (!item) { - std::vector<LLPanel*> panels; - LLFlatListViewEx::getItems(panels); + return; + } - std::vector<LLPanel*>::iterator iter = panels.begin(); + if (mask & LLConversationLogObserver::CHANGED_TIME) + { + item->updateTimestamp(); - for (; iter != panels.end(); ++iter) + // if list is sorted by date and a date of some item has changed, + // than the whole list should be rebuilt + if (E_SORT_BY_DATE == getSortOrder()) { - LLConversationLogListItem* item = dynamic_cast<LLConversationLogListItem*>(*iter); - - if (item && session_id == item->getConversation()->getSessionID() && !item->getConversation()->isConversationPast()) - { - item->initIcons(); - return; - } + mIsDirty = true; + } + } + else if (mask & LLConversationLogObserver::CHANGED_NAME) + { + item->updateName(); + // if list is sorted by name and a name of some item has changed, + // than the whole list should be rebuilt + if (E_SORT_BY_DATE == getSortOrder()) + { + mIsDirty = true; } } } @@ -401,6 +411,29 @@ const LLConversation* LLConversationLogList::getSelectedConversation() return NULL; } +LLConversationLogListItem* LLConversationLogList::getConversationLogListItem(const LLUUID& session_id) +{ + std::vector<LLPanel*> panels; + LLFlatListViewEx::getItems(panels); + std::vector<LLPanel*>::iterator iter = panels.begin(); + + for (; iter != panels.end(); ++iter) + { + LLConversationLogListItem* item = dynamic_cast<LLConversationLogListItem*>(*iter); + if (item && session_id == item->getConversation()->getSessionID()) + { + return item; + } + } + + return NULL; +} + +LLConversationLogList::ESortOrder LLConversationLogList::getSortOrder() +{ + return static_cast<ESortOrder>(gSavedSettings.getU32("CallLogSortOrder")); +} + bool LLConversationLogListItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const { const LLConversationLogListItem* conversation_item1 = dynamic_cast<const LLConversationLogListItem*>(item1); diff --git a/indra/newview/llconversationloglist.h b/indra/newview/llconversationloglist.h index 5e7fc0a9fb..62ec57e09e 100644 --- a/indra/newview/llconversationloglist.h +++ b/indra/newview/llconversationloglist.h @@ -43,6 +43,12 @@ class LLConversationLogList: public LLFlatListViewEx, public LLConversationLogOb { LOG_CLASS(LLConversationLogList); public: + + typedef enum e_sort_oder{ + E_SORT_BY_NAME = 0, + E_SORT_BY_DATE = 1, + } ESortOrder; + struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params> { Params(){}; @@ -90,6 +96,9 @@ private: LLIMModel::LLIMSession::SType getSelectedSessionType(); const LLConversationLogListItem* getSelectedConversationPanel(); const LLConversation* getSelectedConversation(); + LLConversationLogListItem* getConversationLogListItem(const LLUUID& session_id); + + ESortOrder getSortOrder(); LLHandle<LLToggleableMenu> mContextMenu; bool mIsDirty; diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp index dddf216592..fac6130371 100644 --- a/indra/newview/llconversationloglistitem.cpp +++ b/indra/newview/llconversationloglistitem.cpp @@ -117,6 +117,16 @@ void LLConversationLogListItem::initIcons() } } +void LLConversationLogListItem::updateTimestamp() +{ + mConversationDate->setValue(mConversation->getTimestamp()); +} + +void LLConversationLogListItem::updateName() +{ + mConversationName->setValue(mConversation->getConversationName()); +} + void LLConversationLogListItem::onMouseEnter(S32 x, S32 y, MASK mask) { getChildView("hovered_icon")->setVisible(true); diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h index 2aaafa0fba..1bf7a0ed93 100644 --- a/indra/newview/llconversationloglistitem.h +++ b/indra/newview/llconversationloglistitem.h @@ -64,10 +64,16 @@ public: void onDoubleClick(); - void initIcons(); + /** + * updates string value of last interaction time from conversation + */ + void updateTimestamp(); + void updateName(); private: + void initIcons(); + const LLConversation* mConversation; LLTextBox* mConversationName; diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index 4375ce5726..7b4c999e52 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -45,11 +45,11 @@ BOOL LLFloaterConversationLog::postBuild() switch (gSavedSettings.getU32("CallLogSortOrder")) { - case E_SORT_BY_NAME: + case LLConversationLogList::E_SORT_BY_NAME: mConversationLogList->sortByName(); break; - case E_SORT_BY_DATE: + case LLConversationLogList::E_SORT_BY_DATE: mConversationLogList->sortByDate(); break; } @@ -87,12 +87,12 @@ void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) if ("sort_by_name" == command_name) { mConversationLogList->sortByName(); - gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_NAME); + gSavedSettings.setU32("CallLogSortOrder", LLConversationLogList::E_SORT_BY_NAME); } else if ("sort_by_date" == command_name) { mConversationLogList->sortByDate(); - gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_DATE); + gSavedSettings.setU32("CallLogSortOrder", LLConversationLogList::E_SORT_BY_DATE); } else if ("sort_friends_on_top" == command_name) { @@ -117,11 +117,11 @@ bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) if ("sort_by_name" == command_name) { - return sort_order == E_SORT_BY_NAME; + return sort_order == LLConversationLogList::E_SORT_BY_NAME; } else if ("sort_by_date" == command_name) { - return sort_order == E_SORT_BY_DATE; + return sort_order == LLConversationLogList::E_SORT_BY_DATE; } else if ("sort_friends_on_top" == command_name) { diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h index 7d788c0290..e971330f3d 100644 --- a/indra/newview/llfloaterconversationlog.h +++ b/indra/newview/llfloaterconversationlog.h @@ -34,11 +34,6 @@ class LLFloaterConversationLog : public LLFloater { public: - typedef enum e_sort_oder{ - E_SORT_BY_NAME = 0, - E_SORT_BY_DATE = 1, - } ESortOrder; - LLFloaterConversationLog(const LLSD& key); virtual ~LLFloaterConversationLog(){}; -- cgit v1.2.3 From cb8ce1141837cc450756764e03a4564f8ab0c9eb Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Tue, 11 Sep 2012 18:37:05 +0300 Subject: CHUI-336 FIXED (Remove Description label and field from Chat history viewer) - Removed lineeditor and text box from code and xml --- indra/newview/llfloaterconversationpreview.cpp | 2 -- .../xui/en/floater_conversation_preview.xml | 28 ++-------------------- 2 files changed, 2 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index 9ea35fcbad..dbcf154ef2 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -65,8 +65,6 @@ BOOL LLFloaterConversationPreview::postBuild() std::string title = getString("Title", args); setTitle(title); - getChild<LLLineEditor>("description")->setValue(name); - LLLogChat::loadChatHistory(file, mMessages, true); mCurrentPage = mMessages.size() / mPageSize; diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml index d74c2c252d..825a88e4e1 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -14,41 +14,17 @@ name="Title"> CONVERSATION: [NAME] </floater.string> - <text - type="string" - length="1" - follows="left|top" - font="SansSerif" - height="19" - layout="topleft" - left="10" - name="desc txt" - top="22" - width="90"> - Description: - </text> - <line_editor - border_style="line" - border_thickness="1" - enabled="false" - follows="left|top|right" - font="SansSerif" - height="22" - layout="topleft" - left_pad="0" - max_length_bytes="127" - name="description" - width="296" /> <chat_history font="SansSerifSmall" follows="all" visible="true" - height="310" + height="330" name="chat_history" notify_unread_msg="false" parse_highlights="true" parse_urls="true" left="5" + top_pad="25" width="390"> </chat_history> <text -- cgit v1.2.3 From 51725b3898df96aa5819d86d1e8e7c71b47304f2 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Wed, 12 Sep 2012 14:09:13 +0300 Subject: CHUI-335 FIXED (Alpha text allowed in page spinner in chat history viewer) - Added XML parameter "allow_digits_only" to spinner control widget, which disables/enables ability to input alpha text. - Disabled ability to enter alpha text in page spinner in chat history viewer --- indra/llui/llspinctrl.cpp | 5 +++++ indra/llui/llspinctrl.h | 1 + indra/newview/skins/default/xui/en/floater_conversation_preview.xml | 1 + 3 files changed, 7 insertions(+) (limited to 'indra') diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index 934879cdfd..8a728df2e7 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -52,6 +52,7 @@ LLSpinCtrl::Params::Params() : label_width("label_width"), decimal_digits("decimal_digits"), allow_text_entry("allow_text_entry", true), + allow_digits_only("allow_digits_only", false), label_wrap("label_wrap", false), text_enabled_color("text_enabled_color"), text_disabled_color("text_disabled_color"), @@ -129,6 +130,10 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p) params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); mEditor = LLUICtrlFactory::create<LLLineEditor> (params); mEditor->setFocusReceivedCallback( boost::bind(&LLSpinCtrl::onEditorGainFocus, _1, this )); + if (p.allow_digits_only) + { + mEditor->setPrevalidateInput(LLTextValidate::validateNonNegativeS32NoSpace); + } //RN: this seems to be a BAD IDEA, as it makes the editor behavior different when it has focus // than when it doesn't. Instead, if you always have to double click to select all the text, // it's easier to understand diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h index 87814f838e..e34add879d 100644 --- a/indra/llui/llspinctrl.h +++ b/indra/llui/llspinctrl.h @@ -44,6 +44,7 @@ public: Optional<S32> label_width; Optional<U32> decimal_digits; Optional<bool> allow_text_entry; + Optional<bool> allow_digits_only; Optional<bool> label_wrap; Optional<LLUIColor> text_enabled_color; diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml index 825a88e4e1..0e5af67f68 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -39,6 +39,7 @@ width="35"> </text> <spinner + allow_digits_only="true" decimal_digits="0" follows="bottom|right" height="23" -- cgit v1.2.3 From ab43940f11b9690c1d3f6874241c66f200f84258 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 12 Sep 2012 15:43:05 -0700 Subject: CHUI-283: Now the speaker icon and information icon are functional. --- indra/newview/llconversationview.cpp | 72 +++++++----------------------------- indra/newview/llconversationview.h | 6 +-- 2 files changed, 17 insertions(+), 61 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 1d1c774874..9fb4b4f0dc 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -31,7 +31,7 @@ #include "llconversationmodel.h" #include "llimconversation.h" #include "llimfloatercontainer.h" - +#include "llfloaterreg.h" #include "lluictrlfactory.h" #include "llavatariconctrl.h" @@ -151,6 +151,7 @@ BOOL LLConversationViewParticipant::postBuild() mInfoBtn = getChild<LLButton>("info_btn"); mInfoBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onInfoBtnClick, this)); + mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator"); LLFolderViewItem::postBuild(); return TRUE; @@ -168,68 +169,23 @@ void LLConversationViewParticipant::refresh() LLFolderViewItem::refresh(); } -void LLConversationViewParticipant::onInfoBtnClick() +void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder) { - - + //Add the item to the folder (conversation) + LLFolderViewItem::addToFolder(folder); + + //Now retrieve the folder (conversation) UUID, which is the speaker session + LLConversationItem* vmi = this->getParentFolder() ? dynamic_cast<LLConversationItem*>(this->getParentFolder()->getViewModelItem()) : NULL; + if(vmi) + { + mSpeakingIndicator->setSpeakerId(mUUID, + vmi->getUUID()); //set the session id } - -LLButton* LLConversationViewParticipant::createProfileButton() -{ - - LLButton::Params params; - - - //<button - params.follows.flags(FOLLOWS_RIGHT); - //params.height="20"; - LLUIImage * someImage = LLUI::getUIImage("Web_Profile_Off"); - params.image_overlay = someImage; - params.layout="topleft"; - params.left_pad=5; - //params.right="-28"; - params.name="profile_btn"; - params.tab_stop="false"; - params.tool_tip="View profile"; - params.top_delta=-2; - //params.width="20"; - ///> - - - /* - LLConversationViewParticipant::Params params; - - params.name = item->getDisplayName(); - //params.icon = bridge->getIcon(); - //params.icon_open = bridge->getOpenIcon(); - //params.creation_date = bridge->getCreationDate(); - params.root = mConversationsRoot; - params.listener = item; - params.rect = LLRect (0, 0, 0, 0); - params.tool_tip = params.name; - params.container = this; - */ - - LLButton * button = LLUICtrlFactory::create<LLButton>(params); - LLRect someRect; - someRect.setOriginAndSize(30, 0, 20, 20); - button->setShape(someRect); - - //button->follows= "right"; - //button->height = 20; - //button->image_overlay="Web_Profile_Off"; - //button->right = -28; - //button->width = 20; - - - - return button; } - -void LLConversationViewParticipant::draw() +void LLConversationViewParticipant::onInfoBtnClick() { - LLFolderViewItem::draw(); + LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", mUUID)); } // EOF diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index a7946f4d06..2ac6c999d6 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -89,9 +89,9 @@ public: }; virtual ~LLConversationViewParticipant( void ) { } - virtual void draw(); bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } virtual void refresh(); + void addToFolder(LLFolderViewFolder* folder); protected: friend class LLUICtrlFactory; @@ -102,9 +102,9 @@ protected: void onInfoBtnClick(); private: - LLButton* createProfileButton(); LLButton * mInfoBtn; - LLUUID mUUID; // UUID of the participant + LLOutputMonitorCtrl* mSpeakingIndicator; + LLUUID mUUID; // UUID of the participant }; #endif // LL_LLCONVERSATIONVIEW_H -- cgit v1.2.3 From 5cad4b5768cccc8301da5e15dd09a0a4e68d4112 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 12 Sep 2012 23:18:52 -0700 Subject: CHUI-308 : Temp fix while waiting for a scroll container to be implemented --- indra/newview/llimfloatercontainer.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index faca92e662..b70305a4e9 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -118,7 +118,7 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsListPanel = getChild<LLPanel>("conversations_list_panel"); - // CHUI-98 : View Model for conversations + // Create the root model and view for all conversation sessions LLConversationItem* base_item = new LLConversationItem(getRootViewModel()); LLFolderView::Params p; p.view_model = &mConversationViewModel; @@ -129,6 +129,8 @@ BOOL LLIMFloaterContainer::postBuild() p.root = NULL; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); + mConversationsRoot->setVisible(TRUE); + mConversationsListPanel->addChild(mConversationsRoot); addConversationListItem(LLUUID()); // manually add nearby chat @@ -370,8 +372,13 @@ void LLIMFloaterContainer::draw() } } - repositioningWidgets(); - + // CHUI-308 : Hack! We shouldn't have to do that but we have too as long as + // we don't have a scroll container. + // *TODO: Take those 3 lines out once we implement the scroll container. + repositioningWidgets(); + mConversationsRoot->setRect(mConversationsListPanel->getLocalRect()); + mConversationsRoot->setFollowsAll(); + if (mTabContainer->getTabCount() == 0) { // Do not close the container when every conversation is torn off because the user @@ -630,7 +637,6 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) widget->addToFolder(mConversationsRoot); // Add it to the UI - mConversationsListPanel->addChild(widget); widget->setVisible(TRUE); // Create the participants widgets now -- cgit v1.2.3 From 8c0fcf0e391ff5db78f95f031562eedec998f164 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Thu, 13 Sep 2012 16:12:53 +0300 Subject: CHUI-321 FIXED (Indicate within the Call Log why there's nothing in it) I. On "LogInstantMessages" variable set to false: 1. save call log to file 2. clear call log 3. show message: "Conversations are not being logged. To log conversations in the future, select "Save IM logs in my computer" under Preferences > Privacy." On "LogInstantMessages" set to true: 1. clear message 2. reload all saved call log entries II. Refactored the way LLConversationLog reacts on "LogInstantMessages" value change --- indra/newview/llappviewer.cpp | 5 +-- indra/newview/llconversationlog.cpp | 36 +++++++++++++--------- indra/newview/llconversationlog.h | 4 +-- indra/newview/llfloaterconversationlog.cpp | 13 ++++++++ indra/newview/llfloaterconversationlog.h | 2 ++ .../default/xui/en/floater_conversation_log.xml | 5 +++ 6 files changed, 44 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 4dacde4792..08a1a237f5 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1834,10 +1834,7 @@ bool LLAppViewer::cleanup() LLMuteList::getInstance()->cache(gAgent.getID()); //save call log list - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) - { - LLConversationLog::instance().cache(); - } + LLConversationLog::instance().cache(); if (mPurgeOnExit) { diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 239a89015f..27be2bc5ae 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -193,37 +193,40 @@ void LLConversationLogFriendObserver::changed(U32 mask) LLConversationLog::LLConversationLog() { - loadFromFile(getFileName()); - LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); if (ctrl) { - ctrl->getSignal()->connect(boost::bind(&LLConversationLog::observeIMSession, this)); - + ctrl->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); if (ctrl->getValue().asBoolean()) { - LLIMMgr::instance().addSessionObserver(this); - newMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); + enableLogging(true); } } - - mFriendObserver = new LLConversationLogFriendObserver; - LLAvatarTracker::instance().addObserver(mFriendObserver); - } -void LLConversationLog::observeIMSession() +void LLConversationLog::enableLogging(bool enable) { - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + if (enable) { + loadFromFile(getFileName()); + LLIMMgr::instance().addSessionObserver(this); - LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); + newMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); + + mFriendObserver = new LLConversationLogFriendObserver; + LLAvatarTracker::instance().addObserver(mFriendObserver); } else { + saveToFile(getFileName()); + LLIMMgr::instance().removeSessionObserver(this); newMessageSignalConnection.disconnect(); + LLAvatarTracker::instance().removeObserver(mFriendObserver); + mConversations.clear(); } + + notifyObservers(); } void LLConversationLog::logConversation(const LLUUID& session_id) @@ -338,7 +341,10 @@ void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string void LLConversationLog::cache() { - saveToFile(getFileName()); + if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + { + saveToFile(getFileName()); + } } std::string LLConversationLog::getFileName() @@ -349,7 +355,7 @@ std::string LLConversationLog::getFileName() bool LLConversationLog::saveToFile(const std::string& filename) { - if(!filename.size()) + if (!filename.size()) { llwarns << "Call log list filename is empty!" << llendl; return false; diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index ffd27f7e20..a458e975bb 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -144,6 +144,8 @@ private: LLConversationLog(); + void enableLogging(bool enable); + /** * adds conversation to the conversation list and notifies observers */ @@ -151,8 +153,6 @@ private: void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask); - void observeIMSession(); - /** * constructs file name in which conversations log will be saved * file name is conversation.log diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index 7b4c999e52..089aec1905 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -63,6 +63,13 @@ BOOL LLFloaterConversationLog::postBuild() getChild<LLFilterEditor>("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); + LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); + if (ctrl) + { + ctrl->getSignal()->connect(boost::bind(&LLFloaterConversationLog::onCallLoggingEnabledDisabled, this, _2)); + onCallLoggingEnabledDisabled(ctrl->getValue().asBoolean()); + } + return LLFloater::postBuild(); } @@ -130,3 +137,9 @@ bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) return false; } + +void LLFloaterConversationLog::onCallLoggingEnabledDisabled(bool enabled) +{ + std::string no_items_msg = enabled ? "" : getString("logging_calls_disabled"); + mConversationLogList->setNoItemsCommentText(no_items_msg); +} diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h index e971330f3d..9e79cbd7d8 100644 --- a/indra/newview/llfloaterconversationlog.h +++ b/indra/newview/llfloaterconversationlog.h @@ -49,6 +49,8 @@ private: bool isActionEnabled(const LLSD& userdata); bool isActionChecked(const LLSD& userdata); + void onCallLoggingEnabledDisabled(bool enabled); + LLConversationLogList* mConversationLogList; }; diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml index 9cdeb0d788..df78bbccec 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -13,6 +13,11 @@ reuse_instance="true" title="CONVERSATION LOG" width="450"> + + <string name="logging_calls_disabled"> + Conversations are not being logged. To log conversations in the future, select "Save IM logs in my computer" under Preferences > Privacy. + </string> + <panel follows="left|top|right" height="27" -- cgit v1.2.3 From 7da24ddaa3813f7b409b51ed5d330c7609b4f8a9 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 13 Sep 2012 17:00:26 +0300 Subject: CHUI-332 [Overlap of icons in chrome when collapsing and expanding conversation list]: force header resizing after show/hide minimize button --- indra/newview/llimfloatercontainer.cpp | 7 +++++++ indra/newview/skins/default/xui/en/floater_im_container.xml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index b70305a4e9..a1bd623ac5 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -492,6 +492,13 @@ void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) setCanResize(is_left_pane_expanded || is_right_pane_expanded); setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); + // force set correct size for the title after show/hide minimize button + LLRect cur_rect = getRect(); + LLRect force_rect = cur_rect; + force_rect.mRight = cur_rect.mRight + 1; + setRect(force_rect); + setRect(cur_rect); + // restore floater's resize limits (prevent collapse when left panel is expanded) if (is_left_pane_expanded && !is_right_pane_expanded) { diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 1583add857..413e66738d 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -36,7 +36,7 @@ name="conversations_layout_panel" min_dim="38" width="268" - expanded_min_dim="165"> + expanded_min_dim="120"> <layout_stack animate="false" follows="left|top|right" -- cgit v1.2.3 From a6370cf4a72371e090d45f2a147929d016f42780 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Thu, 13 Sep 2012 18:49:57 +0300 Subject: CHUI-334 FIXED (Date not shown in the chat log for current date entries) Before the "%Y/%m/%d" was always cutted from timestamp string for today's date. Now I added flag whether we should cut off timestamp or not. --- indra/newview/llfloaterconversationpreview.cpp | 6 +++++- indra/newview/lllogchat.cpp | 17 +++++++++++++---- indra/newview/lllogchat.h | 4 ++-- 3 files changed, 20 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index dbcf154ef2..88efc39764 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -65,7 +65,11 @@ BOOL LLFloaterConversationPreview::postBuild() std::string title = getString("Title", args); setTitle(title); - LLLogChat::loadChatHistory(file, mMessages, true); + LLSD load_params; + load_params["load_all_history"] = true; + load_params["cut_off_todays_date"] = false; + + LLLogChat::loadChatHistory(file, mMessages, load_params); mCurrentPage = mMessages.size() / mPageSize; mPageSpinner = getChild<LLSpinCtrl>("history_page_spin"); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 073f5f00c5..3692658e9e 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -387,13 +387,16 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line) } // static -void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, bool load_all_history/*= false*/) +void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params) { if (file_name.empty()) { llwarns << "Session name is Empty!" << llendl; return ; } + + bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false; + //LL_INFOS("") << "Loading:" << file_name << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ //LL_INFOS("") << "Current:" << makeLogFileName(file_name) << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r");/*Flawfinder: ignore*/ @@ -449,7 +452,7 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m else { LLSD item; - if (!LLChatLogParser::parse(line, item)) + if (!LLChatLogParser::parse(line, item, load_params)) { item[IM_TEXT] = line; } @@ -500,10 +503,11 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const } } -bool LLChatLogParser::parse(std::string& raw, LLSD& im) +bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params) { if (!raw.length()) return false; + bool cut_off_todays_date = parse_params.has("cut_off_todays_date") ? parse_params["cut_off_todays_date"].asBoolean() : true; im = LLSD::emptyMap(); //matching a timestamp @@ -518,7 +522,12 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im) boost::trim(timestamp); timestamp.erase(0, 1); timestamp.erase(timestamp.length()-1, 1); - LLLogChatTimeScanner::instance().checkAndCutOffDate(timestamp); + + if (cut_off_todays_date) + { + LLLogChatTimeScanner::instance().checkAndCutOffDate(timestamp); + } + im[IM_TIME] = timestamp; } else diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index 95f83e64e5..d3e9adcc37 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -55,7 +55,7 @@ public: void (*callback)(ELogLineType, const LLSD&, void*), void* userdata); - static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, bool load_all_history = false); + static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD()); private: static std::string cleanFileName(std::string filename); }; @@ -105,7 +105,7 @@ public: * * @return false if failed to parse mandatory data - message text */ - static bool parse(std::string& raw, LLSD& im); + static bool parse(std::string& raw, LLSD& im, const LLSD& parse_params = LLSD()); protected: LLChatLogParser(); -- cgit v1.2.3 From 4b52515b543546844835064dfb89e5af2bbbd948 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Thu, 13 Sep 2012 20:10:45 +0300 Subject: CHUI-282 WIP Fixed conversation list items selection. Fixed displaying session participants only when session item is open. --- indra/newview/llconversationmodel.cpp | 5 ++++ indra/newview/llconversationmodel.h | 2 ++ indra/newview/llconversationview.cpp | 32 ++++++++++++++++++---- indra/newview/llimfloatercontainer.cpp | 22 ++------------- .../xui/en/panel_conversation_list_item.xml | 22 +++++++-------- .../xui/en/widgets/conversation_view_session.xml | 9 ++++++ 6 files changed, 56 insertions(+), 36 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/widgets/conversation_view_session.xml (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index fa49987d15..51a37fe856 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -101,6 +101,11 @@ LLConversationItemSession::LLConversationItemSession(const LLUUID& uuid, LLFolde { } +bool LLConversationItemSession::hasChildren() const +{ + return getChildrenCount() > 0; +} + void LLConversationItemSession::addParticipant(LLConversationItemParticipant* participant) { addChild(participant); diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 26c7a29d76..e5c727feae 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -120,6 +120,8 @@ public: LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItemSession() {} + /*virtual*/ bool hasChildren() const; + void setSessionID(const LLUUID& session_id) { mUUID = session_id; mNeedsRefresh = true; } void addParticipant(LLConversationItemParticipant* participant); void removeParticipant(LLConversationItemParticipant* participant); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 514bf38b00..53971a3159 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -35,12 +35,13 @@ // // Implementation of conversations list session widgets // +static LLDefaultChildRegistry::Register<LLConversationViewSession> r_conversation_view_session("conversation_view_session"); LLConversationViewSession::Params::Params() : container() {} -LLConversationViewSession::LLConversationViewSession( const LLConversationViewSession::Params& p ): +LLConversationViewSession::LLConversationViewSession(const LLConversationViewSession::Params& p): LLFolderViewFolder(p), mContainer(p.container), mItemPanel(NULL), @@ -65,6 +66,8 @@ BOOL LLConversationViewSession::postBuild() void LLConversationViewSession::draw() { +// *TODO Seth PE: remove the code duplicated from LLFolderViewFolder::draw() +// ***** LLFolderViewFolder::draw() code begin ***** if (mAutoOpenCountdown != 0.f) { mControlLabelRotation = mAutoOpenCountdown * -90.f; @@ -77,7 +80,10 @@ void LLConversationViewSession::draw() { mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); } +// ***** LLFolderViewFolder::draw() code end ***** +// *TODO Seth PE: remove the code duplicated from LLFolderViewItem::draw() +// ***** LLFolderViewItem::draw() code begin ***** const LLColor4U DEFAULT_WHITE(255, 255, 255); static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); @@ -190,10 +196,27 @@ void LLConversationViewSession::draw() } mDragAndDropTarget = FALSE; } +// ***** LLFolderViewItem::draw() code end ***** - LLView::draw(); + // draw children if root folder, or any other folder that is open or animating to closed state + bool draw_children = getRoot() == static_cast<LLFolderViewFolder*>(this) + || isOpen() + || mCurHeight != mTargetHeight; - mExpanderHighlighted = FALSE; + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setVisible(draw_children); + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + (*iit)->setVisible(draw_children); + } + + LLView::draw(); } // virtual @@ -203,8 +226,7 @@ S32 LLConversationViewSession::arrange(S32* width, S32* height) getLocalRect().mTop, getLocalRect().mRight, getLocalRect().mTop - getItemHeight()); - mItemPanel->setRect(rect); - mItemPanel->reshape(rect.getWidth(), rect.getHeight()); + mItemPanel->setShape(rect); return LLFolderViewFolder::arrange(width, height); } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 9157d16aea..79009942bf 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -132,7 +132,7 @@ BOOL LLIMFloaterContainer::postBuild() p.root = NULL; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); - // Scroller + // a scroller for folder view LLRect scroller_view_rect = mConversationsListPanel->getRect(); scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>()); @@ -639,10 +639,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) // Add a new conversation widget to the root folder of the folder view widget->addToFolder(mConversationsRoot); - - // Add it to the UI -// mConversationsListPanel->addChild(widget); - widget->setVisible(TRUE); + widget->requestArrange(); // Create the participants widgets now // Note: usually, we do not get an updated avatar list at that point @@ -654,16 +651,8 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); participant_view->addToFolder(widget); -// mConversationsListPanel->addChild(participant_view); -// participant_view->setVisible(TRUE); current_participant_model++; } - - S32 width = 0; - S32 height = 0; - mConversationsRoot->arrange(&width, &height); - -// repositioningWidgets(); return; } @@ -683,8 +672,6 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c // Suppress the conversation items and widgets from their respective maps mConversationsItems.erase(uuid); mConversationsWidgets.erase(uuid); - - repositioningWidgets(); // Don't let the focus fall IW, select and refocus on the first conversation in the list if (change_focus) @@ -704,13 +691,8 @@ LLConversationViewSession* LLIMFloaterContainer::createConversationItemWidget(LL LLConversationViewSession::Params params; params.name = item->getDisplayName(); - //params.icon = bridge->getIcon(); - //params.icon_open = bridge->getOpenIcon(); - //params.creation_date = bridge->getCreationDate(); - params.item_height = 24; params.root = mConversationsRoot; params.listener = item; - params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; params.container = this; diff --git a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml index d1f25b45fe..375ea79ebe 100644 --- a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml @@ -3,8 +3,8 @@ follows="left|top|right" height="24" layout="topleft" - mouse_opaque="flase" name="conversation_list_item" + mouse_opaque="false" width="120"> <avatar_icon follows="top|left" @@ -12,7 +12,6 @@ default_icon_name="Generic_Person" layout="topleft" left="5" - mouse_opaque="true" top="2" width="20" /> <layout_stack @@ -21,7 +20,8 @@ height="24" layout="topleft" left_pad="5" - name="caonversation_item_stack" + mouse_opaque="false" + name="conversation_item_stack" orientation="horizontal" top="0" width="90"> @@ -29,6 +29,7 @@ auto_resize="false" user_resize="false" height="24" + mouse_opaque="false" name="call_icon_panel" visible="false" width="20"> @@ -44,13 +45,11 @@ </layout_panel> <layout_panel auto_resize="true" - user_resize="false" - left_pad="0" + user_resize="false" height="24" + mouse_opaque="false" name="conversation_title_panel" - min_dim="50" - width="70" - expanded_min_dim="50"> + width="70"> <text follows="left|top|right" font="SansSerifSmall" @@ -70,9 +69,10 @@ height="16" layout="topleft" left_pad="5" - mouse_opaque="true" - name="speaking_indicator" - width="20" /> + mouse_opaque="true" + name="speaking_indicator" + visible="false" + width="20" /> </layout_panel> </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_session.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_session.xml new file mode 100644 index 0000000000..f44731ea3d --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_session.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<conversation_view_session + folder_arrow_image="Folder_Arrow" + folder_indentation="8" + item_height="24" + item_top_pad="4" + selection_image="Rounded_Square" + mouse_opaque="true" + follows="left|top|right"/> -- cgit v1.2.3 From 2084d33c1ec827b4e8d975a3bf1232e971f704e2 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 13 Sep 2012 11:22:41 -0700 Subject: CHUI-283: Now the information icon only appears upon mousehover. Also the information/speaker icon are right justified. --- indra/llui/llfolderviewitem.cpp | 2 +- indra/newview/llconversationview.cpp | 23 ++++++++++++++++++---- indra/newview/llconversationview.h | 5 ++++- indra/newview/llimfloatercontainer.cpp | 3 ++- .../en/widgets/conversation_view_participant.xml | 11 +++++------ 5 files changed, 31 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index c46af27a04..155a605c3b 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -771,7 +771,7 @@ void LLFolderViewItem::draw() // font->renderUTF8(mLabel, 0, text_left, y, color, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); + S32_MAX, getRect().getWidth() - (S32) text_left - TEXT_PAD_RIGHT, &right_x, TRUE); //--------------------------------------------------------------------------------// // Draw label suffix diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 9fb4b4f0dc..7b1c9ef912 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -138,10 +138,12 @@ LLConversationViewParticipant::LLConversationViewParticipant( const LLConversati void LLConversationViewParticipant::initFromParams(const LLConversationViewParticipant::Params& params) { LLButton::Params info_button_params(params.info_button()); + applyXUILayout(info_button_params, this); LLButton * button = LLUICtrlFactory::create<LLButton>(info_button_params); addChild(button); LLOutputMonitorCtrl::Params output_monitor_params(params.output_monitor()); + applyXUILayout(output_monitor_params, this); LLOutputMonitorCtrl * outputMonitor = LLUICtrlFactory::create<LLOutputMonitorCtrl>(output_monitor_params); addChild(outputMonitor); } @@ -150,9 +152,10 @@ BOOL LLConversationViewParticipant::postBuild() { mInfoBtn = getChild<LLButton>("info_btn"); mInfoBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onInfoBtnClick, this)); - + mInfoBtn->setVisible(false); + mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator"); - + LLFolderViewItem::postBuild(); return TRUE; } @@ -179,8 +182,8 @@ void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder) if(vmi) { mSpeakingIndicator->setSpeakerId(mUUID, - vmi->getUUID()); //set the session id -} + vmi->getUUID()); //set the session id + } } void LLConversationViewParticipant::onInfoBtnClick() @@ -188,5 +191,17 @@ void LLConversationViewParticipant::onInfoBtnClick() LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", mUUID)); } +void LLConversationViewParticipant::onMouseEnter(S32 x, S32 y, MASK mask) +{ + mInfoBtn->setVisible(true); + LLFolderViewItem::onMouseEnter(x, y, mask); +} + +void LLConversationViewParticipant::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mInfoBtn->setVisible(false); + LLFolderViewItem::onMouseEnter(x, y, mask); +} + // EOF diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 2ac6c999d6..0dcf6542a3 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -92,7 +92,10 @@ public: bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } virtual void refresh(); void addToFolder(LLFolderViewFolder* folder); - + + void onMouseEnter(S32 x, S32 y, MASK mask); + void onMouseLeave(S32 x, S32 y, MASK mask); + protected: friend class LLUICtrlFactory; LLConversationViewParticipant( const Params& p ); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index faca92e662..3243fd48de 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -703,6 +703,7 @@ LLConversationViewSession* LLIMFloaterContainer::createConversationItemWidget(LL LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParticipant(LLConversationItem* item) { LLConversationViewParticipant::Params params; + LLRect panel_rect = mConversationsListPanel->getRect(); params.name = item->getDisplayName(); //params.icon = bridge->getIcon(); @@ -710,7 +711,7 @@ LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParti //params.creation_date = bridge->getCreationDate(); params.root = mConversationsRoot; params.listener = item; - params.rect = LLRect (0, 0, 0, 0); + params.rect = LLRect (0, 16, panel_rect.getWidth(), 0); params.tool_tip = params.name; params.participant_id = item->getUUID(); diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml index 0b5c1b9511..60015576b5 100755 --- a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml +++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml @@ -9,23 +9,22 @@ follows="left|top|right" > <info_button + follows="right" + auto_update="true" height="16" image_pressed="Info_Press" image_unselected="Info_Over" layout="topleft" - left_pad="3" - right="200" + right="-28" name="info_btn" - tab_stop="false" - top_delta="0" width="16" /> <output_monitor + follows="right" auto_update="true" draw_border="false" height="16" layout="topleft" - left_pad="5" - right="225" + right="-3" mouse_opaque="true" name="speaking_indicator" visible="true" -- cgit v1.2.3 From 386c50d414e6357975cb18814b6bfb048b46b3da Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Fri, 14 Sep 2012 00:29:50 +0300 Subject: CHUI-282 WIP Removed the hack added for CHUI-308 to resize the folder view in conversation list. Fixed some glitches after automated merge. --- indra/newview/llimfloatercontainer.cpp | 11 ----------- indra/newview/llimfloatercontainer.h | 2 -- 2 files changed, 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 6aa7a2e054..58b788d231 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -80,8 +80,6 @@ LLIMFloaterContainer::~LLIMFloaterContainer() { LLIMMgr::getInstance()->removeSessionObserver(this); } - - gIdleCallbacks.deleteFunction(idle, (void*)this); } void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) @@ -171,8 +169,6 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsPane->handleReshape(list_size, TRUE); } - gIdleCallbacks.addFunction(idle, (void*)this); - mInitialized = true; // Add callback: we'll take care of view updates on idle @@ -390,13 +386,6 @@ void LLIMFloaterContainer::draw() } } - // CHUI-308 : Hack! We shouldn't have to do that but we have too as long as - // we don't have a scroll container. - // *TODO: Take those 3 lines out once we implement the scroll container. - repositioningWidgets(); - mConversationsRoot->setRect(mConversationsListPanel->getLocalRect()); - mConversationsRoot->setFollowsAll(); - if (mTabContainer->getTabCount() == 0) { // Do not close the container when every conversation is torn off because the user diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index bda1ce0cb1..324adfcc11 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -71,8 +71,6 @@ public: static LLIMFloaterContainer* getInstance(); - static void idle(void* user_data); - virtual void setMinimized(BOOL b); void collapseMessagesPane(bool collapse); -- cgit v1.2.3 From c6863d18d7c981756c57bbcd52baa06af00d1551 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 13 Sep 2012 19:10:28 -0700 Subject: CHUI-283: Now upon the information icon and speaker icon do not overlap the username text. Instead the username text will be truncated with an ellipse to prevent the overlap. Also did a code cleanup. --- indra/llcommon/llfoldertype.h | 2 +- indra/llui/llfolderviewitem.cpp | 31 +++++++------- indra/llui/llfolderviewitem.h | 4 +- indra/newview/llconversationmodel.h | 2 +- indra/newview/llconversationview.cpp | 78 ++++++++++++++++++++++++++++++++-- indra/newview/llconversationview.h | 20 +++++---- indra/newview/llimfloatercontainer.cpp | 2 + indra/newview/llviewerfoldertype.cpp | 2 +- 8 files changed, 110 insertions(+), 31 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h index 6b5ae572a9..609b550900 100755 --- a/indra/llcommon/llfoldertype.h +++ b/indra/llcommon/llfoldertype.h @@ -91,7 +91,7 @@ public: FT_NONE = -1, - FT_PROFILE = 58 + FT_PROFILEXXXGGG = 58 }; static EType lookup(const std::string& type_name); diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 155a605c3b..7ca02b726a 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -98,6 +98,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) : LLView(p), mLabelWidth(0), mLabelWidthDirty(false), + mLabelPaddingRight(DEFAULT_TEXT_PADDING_RIGHT), mParentFolder( NULL ), mIsSelected( FALSE ), mIsCurSelection( FALSE ), @@ -291,7 +292,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height ) : 0; if (mLabelWidthDirty) { - mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + TEXT_PAD_RIGHT; + mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + mLabelPaddingRight; mLabelWidthDirty = false; } @@ -610,13 +611,13 @@ void LLFolderViewItem::draw() static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); - getViewModelItem()->update(); - const Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); const S32 TOP_PAD = default_params.item_top_pad; const S32 FOCUS_LEFT = 1; const LLFontGL* font = getLabelFontForStyle(mLabelStyle); + getViewModelItem()->update(); + //--------------------------------------------------------------------------------// // Draw open folder arrow // @@ -771,7 +772,7 @@ void LLFolderViewItem::draw() // font->renderUTF8(mLabel, 0, text_left, y, color, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, getRect().getWidth() - (S32) text_left - TEXT_PAD_RIGHT, &right_x, TRUE); + S32_MAX, getRect().getWidth() - (S32) text_left - mLabelPaddingRight, &right_x, TRUE); //--------------------------------------------------------------------------------// // Draw label suffix @@ -786,18 +787,18 @@ void LLFolderViewItem::draw() //--------------------------------------------------------------------------------// // Highlight string match // - if (filter_string_length > 0) - { - F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mViewModelItem->getFilterStringOffset()); - F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; - font->renderUTF8( combined_string, mViewModelItem->getFilterStringOffset(), match_string_left, yy, - sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - filter_string_length, S32_MAX, &right_x, FALSE ); - } + if (filter_string_length > 0) + { + F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mViewModelItem->getFilterStringOffset()); + F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + font->renderUTF8( combined_string, mViewModelItem->getFilterStringOffset(), match_string_left, yy, + sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + filter_string_length, S32_MAX, &right_x, FALSE ); + } - - LLView::draw(); - } + + LLView::draw(); +} const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const { diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 766d9b3fe3..fab24e52d1 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -68,7 +68,7 @@ public: ICON_PAD = 2, ICON_WIDTH = 16, TEXT_PAD = 1, - TEXT_PAD_RIGHT = 4, + DEFAULT_TEXT_PADDING_RIGHT = 4, ARROW_SIZE = 12, MAX_FOLDER_ITEM_OVERLAP = 2; @@ -85,6 +85,7 @@ protected: std::string mLabel; S32 mLabelWidth; bool mLabelWidthDirty; + S32 mLabelPaddingRight; LLFolderViewFolder* mParentFolder; LLFolderViewModelItem* mViewModelItem; LLFontGL::StyleFlags mLabelStyle; @@ -243,6 +244,7 @@ public: private: static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts + }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 4f13d3d3a1..e1713f9db7 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -57,7 +57,7 @@ public: virtual const std::string& getSearchableName() const { return mName; } virtual const LLUUID& getUUID() const { return mUUID; } virtual time_t getCreationDate() const { return 0; } - virtual LLPointer<LLUIImage> getIcon() const { return LLUI::getUIImage(LLViewerFolderType::lookupIconName(LLFolderType::FT_PROFILE, FALSE)); } + virtual LLPointer<LLUIImage> getIcon() const { return LLUI::getUIImage(LLViewerFolderType::lookupIconName(LLFolderType::FT_PROFILEXXXGGG, FALSE)); } virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } virtual std::string getLabelSuffix() const { return LLStringUtil::null; } diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 7b1c9ef912..bc85cd68bc 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -28,13 +28,13 @@ #include "llviewerprecompiledheaders.h" #include "llconversationview.h" + +#include <boost/bind.hpp> #include "llconversationmodel.h" #include "llimconversation.h" #include "llimfloatercontainer.h" #include "llfloaterreg.h" - #include "lluictrlfactory.h" -#include "llavatariconctrl.h" // // Implementation of conversations list session widgets @@ -120,6 +120,8 @@ void LLConversationViewSession::refresh() // static LLDefaultChildRegistry::Register<LLConversationViewParticipant> r("conversation_view_participant"); +bool LLConversationViewParticipant::sStaticInitialized = false; +S32 LLConversationViewParticipant::sChildrenWidths[LLConversationViewParticipant::ALIC_COUNT]; LLConversationViewParticipant::Params::Params() : container(), @@ -130,6 +132,8 @@ output_monitor("output_monitor") LLConversationViewParticipant::LLConversationViewParticipant( const LLConversationViewParticipant::Params& p ): LLFolderViewItem(p), + mInfoBtn(NULL), + mSpeakingIndicator(NULL), mUUID(p.participant_id) { @@ -156,8 +160,16 @@ BOOL LLConversationViewParticipant::postBuild() mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator"); - LLFolderViewItem::postBuild(); - return TRUE; + if (!sStaticInitialized) + { + // Remember children widths including their padding from the next sibling, + // so that we can hide and show them again later. + initChildrenWidths(this); + sStaticInitialized = true; + } + + computeLabelRightPadding(); + return LLFolderViewItem::postBuild(); } void LLConversationViewParticipant::refresh() @@ -194,14 +206,72 @@ void LLConversationViewParticipant::onInfoBtnClick() void LLConversationViewParticipant::onMouseEnter(S32 x, S32 y, MASK mask) { mInfoBtn->setVisible(true); + computeLabelRightPadding(); LLFolderViewItem::onMouseEnter(x, y, mask); } void LLConversationViewParticipant::onMouseLeave(S32 x, S32 y, MASK mask) { mInfoBtn->setVisible(false); + computeLabelRightPadding(); LLFolderViewItem::onMouseEnter(x, y, mask); } +// static +void LLConversationViewParticipant::initChildrenWidths(LLConversationViewParticipant* self) +{ + //speaking indicator width + padding + S32 speaking_indicator_width = self->getRect().getWidth() - self->mSpeakingIndicator->getRect().mLeft; + + //info btn width + padding + S32 info_btn_width = self->mSpeakingIndicator->getRect().mLeft - self->mInfoBtn->getRect().mLeft; + + S32 index = ALIC_COUNT; + sChildrenWidths[--index] = info_btn_width; + sChildrenWidths[--index] = speaking_indicator_width; + llassert(index == 0); +} + +void LLConversationViewParticipant::computeLabelRightPadding() +{ + mLabelPaddingRight = DEFAULT_TEXT_PADDING_RIGHT; + LLView* control; + S32 ctrl_width; + + for (S32 i = 0; i < ALIC_COUNT; ++i) + { + control = getItemChildView((EAvatarListItemChildIndex)i); + + // skip invisible views + if (!control->getVisible()) continue; + + ctrl_width = sChildrenWidths[i]; // including space between current & left controls + // accumulate the amount of space taken by the controls + mLabelPaddingRight += ctrl_width; + } +} + +LLView* LLConversationViewParticipant::getItemChildView(EAvatarListItemChildIndex child_view_index) +{ + LLView* child_view = NULL; + + switch (child_view_index) + { + case ALIC_SPEAKER_INDICATOR: + child_view = mSpeakingIndicator; + break; + case ALIC_INFO_BUTTON: + child_view = mInfoBtn; + break; + default: + LL_WARNS("AvatarItemReshape") << "Unexpected child view index is passed: " << child_view_index << LL_ENDL; + llassert(0); + break; + // leave child_view untouched + } + + return child_view; +} + // EOF diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 0dcf6542a3..686a79ad39 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -29,12 +29,6 @@ #include "llfolderviewitem.h" - - - -#include "llstyle.h" -#include "llcallbackmap.h" -#include "lltextbox.h" #include "llbutton.h" #include "lloutputmonitorctrl.h" @@ -71,8 +65,6 @@ public: // Implementation of conversations list participant (avatar) widgets -class LLAvatarIconCtrl; - class LLConversationViewParticipant : public LLFolderViewItem { @@ -108,6 +100,18 @@ private: LLButton * mInfoBtn; LLOutputMonitorCtrl* mSpeakingIndicator; LLUUID mUUID; // UUID of the participant + + typedef enum e_avatar_item_child { + ALIC_SPEAKER_INDICATOR, + ALIC_INFO_BUTTON, + ALIC_COUNT, + } EAvatarListItemChildIndex; + + static bool sStaticInitialized; // this variable is introduced to improve code readability + static S32 sChildrenWidths[ALIC_COUNT]; + static void initChildrenWidths(LLConversationViewParticipant* self); + void computeLabelRightPadding(); + LLView* getItemChildView(EAvatarListItemChildIndex child_view_index); }; #endif // LL_LLCONVERSATIONVIEW_H diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 9320117eb5..299d38298e 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -724,6 +724,8 @@ LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParti //params.creation_date = bridge->getCreationDate(); params.root = mConversationsRoot; params.listener = item; + + //16 and panel_rect.getWidth() are used since that is currently the values used in repositioningWidgets() params.rect = LLRect (0, 16, panel_rect.getWidth(), 0); params.tool_tip = params.name; params.participant_id = item->getUUID(); diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index d470abb8c5..0a402d8c42 100755 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -148,7 +148,7 @@ LLViewerFolderDictionary::LLViewerFolderDictionary() } #endif - addEntry(LLFolderType::FT_PROFILE, new ViewerFolderEntry("Profile", "Generic_Person", "Generic_Person", FALSE, false, "default")); + addEntry(LLFolderType::FT_PROFILEXXXGGG, new ViewerFolderEntry("Profile", "Generic_Person", "Generic_Person", FALSE, false, "default")); } bool LLViewerFolderDictionary::initEnsemblesFromFile() -- cgit v1.2.3 From 72f6bebe59f5f900af02a4d234a4091a3e034529 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 14 Sep 2012 16:11:42 +0300 Subject: CHUI-261 Additional fix (Nearby chat controls and log are not visible on next login after tearing off and docking nearby chat in previous session): prevent start LLNearbyChat before start its container --- indra/newview/llimconversation.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index bab588126f..a2efe63546 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -381,6 +381,9 @@ void LLIMConversation::hideAllStandardButtons() void LLIMConversation::updateHeaderAndToolbar() { + // prevent start conversation before its container + LLIMFloaterContainer::getInstance(); + bool is_torn_off = !getHost(); if (!is_torn_off) { -- cgit v1.2.3 From 399ba09c08d8ccaf9b34daa8b743f837639b2f35 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 14 Sep 2012 18:47:39 -0700 Subject: CHUI-283: Now the info/speaker icon are better positioned within the participant item. Also the participant item now matches the height of the session (conversation) item. --- indra/newview/llimfloatercontainer.cpp | 2 +- .../skins/default/xui/en/widgets/conversation_view_participant.xml | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 54a40627fb..e039702683 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -721,7 +721,7 @@ LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParti params.listener = item; //16 and panel_rect.getWidth() are used since that is currently the values used in repositioningWidgets() - params.rect = LLRect (0, 16, panel_rect.getWidth(), 0); + params.rect = LLRect (0, 24, panel_rect.getWidth(), 0); params.tool_tip = params.name; params.participant_id = item->getUUID(); diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml index 60015576b5..b00e8aaeee 100755 --- a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml +++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml @@ -2,7 +2,7 @@ <conversation_view_participant folder_arrow_image="ForSale_Badge" folder_indentation="8" - item_height="20" + item_height="24" item_top_pad="4" selection_image="Rounded_Square" mouse_opaque="true" @@ -10,11 +10,9 @@ > <info_button follows="right" - auto_update="true" height="16" image_pressed="Info_Press" image_unselected="Info_Over" - layout="topleft" right="-28" name="info_btn" width="16" /> @@ -23,7 +21,6 @@ auto_update="true" draw_border="false" height="16" - layout="topleft" right="-3" mouse_opaque="true" name="speaking_indicator" -- cgit v1.2.3 From 9b0d627a06a817fc11edc4c6c718f1114aa7cfcf Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 14 Sep 2012 19:47:52 -0700 Subject: CHUI-192 : Implement menus and settings for sorting. The sort itself is not performed though. Wait for CHUI-340 for this. --- indra/newview/app_settings/settings.xml | 11 +++ indra/newview/llconversationmodel.h | 23 ++++-- indra/newview/llimfloatercontainer.cpp | 89 ++++++++++++++++++++++ indra/newview/llimfloatercontainer.h | 4 + .../skins/default/xui/en/menu_participant_view.xml | 70 +++++++++++++++++ 5 files changed, 190 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 593381cb29..9ada5e5918 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1683,6 +1683,17 @@ <key>Value</key> <integer>100</integer> </map> + <key>ConversationSortOrder</key> + <map> + <key>Comment</key> + <string>Specifies sort key for conversations</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>131073</integer> + </map> <key>NearbyChatIsNotTornOff</key> <map> <key>Comment</key> diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index c340194dd3..ef1903ab19 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -170,10 +170,14 @@ public: enum ESortOrderType { - SO_NAME = 0, // Sort inventory by name - SO_DATE = 0x1, // Sort inventory by date + SO_NAME = 0, // Sort by name + SO_DATE = 0x1, // Sort by date (most recent) + SO_SESSION_TYPE = 0x2, // Sort by type (valid only for sessions) + SO_DISTANCE = 0x3, // Sort by distance (valid only for participants in nearby chat) }; - + // Default sort order is by type for sessions and by date for participants + static const U32 SO_DEFAULT = (SO_SESSION_TYPE << 16) | (SO_DATE); + LLConversationFilter() { mEmpty = ""; } ~LLConversationFilter() {} @@ -211,13 +215,18 @@ private: class LLConversationSort { public: - LLConversationSort(U32 order = 0) : mSortOrder(order) { } - - bool isByDate() const { return (mSortOrder & LLConversationFilter::SO_DATE); } - U32 getSortOrder() const { return mSortOrder; } + LLConversationSort(U32 order = LLConversationFilter::SO_DEFAULT) : mSortOrder(order) { } + // 16 LSB bits used for participants, 16 MSB bits for sessions + U32 getSortOrderSessions() const { return ((mSortOrder >> 16) & 0xFFFF); } + U32 getSortOrderParticipants() const { return (mSortOrder & 0xFFFF); } + void setSortOrderSessions(LLConversationFilter::ESortOrderType session) { mSortOrder = ((session & 0xFFFF) << 16) | (mSortOrder & 0xFFFF); } + void setSortOrderParticipants(LLConversationFilter::ESortOrderType participant) { mSortOrder = (mSortOrder & 0xFFFF0000) | (participant & 0xFFFF); } + bool operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const; + operator U32() const { return mSortOrder; } private: + // Note: we're treating this value as a sort order bitmask as done in other places in the code (e.g. inventory) U32 mSortOrder; }; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 81dddfaa70..ab4b64471b 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -58,6 +58,7 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) mInitialized(false) { mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLIMFloaterContainer::onCustomAction, this, _2)); + mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLIMFloaterContainer::isActionChecked, this, _2)); // Firstly add our self to IMSession observers, so we catch session events LLIMMgr::getInstance()->addSessionObserver(this); @@ -169,6 +170,9 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsPane->handleReshape(list_size, TRUE); } + // Init the sort order now that the root had been created + setSortOrder(LLConversationSort(gSavedSettings.getU32("ConversationSortOrder"))); + mInitialized = true; // Add callback: we'll take care of view updates on idle @@ -546,6 +550,30 @@ void LLIMFloaterContainer::onCustomAction(const LLSD& userdata) { std::string command = userdata.asString(); + if ("sort_sessions_by_type" == command) + { + setSortOrderSessions(LLConversationFilter::SO_SESSION_TYPE); + } + if ("sort_sessions_by_name" == command) + { + setSortOrderSessions(LLConversationFilter::SO_NAME); + } + if ("sort_sessions_by_recent" == command) + { + setSortOrderSessions(LLConversationFilter::SO_DATE); + } + if ("sort_participants_by_name" == command) + { + setSortOrderParticipants(LLConversationFilter::SO_NAME); + } + if ("sort_participants_by_recent" == command) + { + setSortOrderParticipants(LLConversationFilter::SO_DATE); + } + if ("sort_participants_by_distance" == command) + { + setSortOrderParticipants(LLConversationFilter::SO_DISTANCE); + } if ("chat_preferences" == command) { LLFloaterPreference* floater_prefs = LLFloaterReg::showTypedInstance<LLFloaterPreference>("preferences"); @@ -561,6 +589,67 @@ void LLIMFloaterContainer::onCustomAction(const LLSD& userdata) } } +BOOL LLIMFloaterContainer::isActionChecked(const LLSD& userdata) +{ + LLConversationSort order = mConversationViewModel.getSorter(); + std::string command = userdata.asString(); + if ("sort_sessions_by_type" == command) + { + return (order.getSortOrderSessions() == LLConversationFilter::SO_SESSION_TYPE); + } + if ("sort_sessions_by_name" == command) + { + return (order.getSortOrderSessions() == LLConversationFilter::SO_NAME); + } + if ("sort_sessions_by_recent" == command) + { + return (order.getSortOrderSessions() == LLConversationFilter::SO_DATE); + } + if ("sort_participants_by_name" == command) + { + return (order.getSortOrderParticipants() == LLConversationFilter::SO_NAME); + } + if ("sort_participants_by_recent" == command) + { + return (order.getSortOrderParticipants() == LLConversationFilter::SO_DATE); + } + if ("sort_participants_by_distance" == command) + { + return (order.getSortOrderParticipants() == LLConversationFilter::SO_DISTANCE); + } + + return FALSE; +} + +void LLIMFloaterContainer::setSortOrderSessions(const LLConversationFilter::ESortOrderType order) +{ + LLConversationSort old_order = mConversationViewModel.getSorter(); + if (order != old_order.getSortOrderSessions()) + { + old_order.setSortOrderSessions(order); + setSortOrder(old_order); + } +} + +void LLIMFloaterContainer::setSortOrderParticipants(const LLConversationFilter::ESortOrderType order) +{ + LLConversationSort old_order = mConversationViewModel.getSorter(); + if (order != old_order.getSortOrderParticipants()) + { + old_order.setSortOrderParticipants(order); + setSortOrder(old_order); + } +} + +void LLIMFloaterContainer::setSortOrder(const LLConversationSort& order) +{ + mConversationViewModel.setSorter(order); + mConversationsRoot->arrangeAll(); + // try to keep selection onscreen, even if it wasn't to start with + mConversationsRoot->scrollToShowSelection(); + gSavedSettings.setU32("ConversationSortOrder", (U32)order); +} + void LLIMFloaterContainer::repositioningWidgets() { if (!mInitialized) diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index f6048bed37..1f526091bb 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -105,7 +105,11 @@ private: void onAddButtonClicked(); void onAvatarPicked(const uuid_vec_t& ids); + BOOL isActionChecked(const LLSD& userdata); void onCustomAction (const LLSD& userdata); + void setSortOrderSessions(const LLConversationFilter::ESortOrderType order); + void setSortOrderParticipants(const LLConversationFilter::ESortOrderType order); + void setSortOrder(const LLConversationSort& order); LLButton* mExpandCollapseBtn; LLLayoutPanel* mMessagesPane; diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml index df2700c94c..0043c14479 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_view.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -2,6 +2,76 @@ <toggleable_menu layout="topleft" name="participant_manu_view"> + <menu_item_check + label="Sort conversations by type" + layout="topleft" + name="sort_sessions_by_type"> + <on_click + function="IMFloaterContainer.Action" + parameter="sort_sessions_by_type" /> + <on_check + function="IMFloaterContainer.Check" + parameter="sort_sessions_by_type" /> + </menu_item_check> + <menu_item_check + label="Sort conversations by name" + layout="topleft" + name="sort_sessions_by_name"> + <on_click + function="IMFloaterContainer.Action" + parameter="sort_sessions_by_name" /> + <on_check + function="IMFloaterContainer.Check" + parameter="sort_sessions_by_name" /> + </menu_item_check> + <menu_item_check + label="Sort conversations by recent activity" + layout="topleft" + name="sort_sessions_by_recent"> + <on_click + function="IMFloaterContainer.Action" + parameter="sort_sessions_by_recent" /> + <on_check + function="IMFloaterContainer.Check" + parameter="sort_sessions_by_recent" /> + </menu_item_check> + <menu_item_separator + layout="topleft" /> + <menu_item_check + label="Sort participants by name" + layout="topleft" + name="sort_participants_by_name"> + <on_click + function="IMFloaterContainer.Action" + parameter="sort_participants_by_name" /> + <on_check + function="IMFloaterContainer.Check" + parameter="sort_participants_by_name" /> + </menu_item_check> + <menu_item_check + label="Sort participants by recent activity" + layout="topleft" + name="sort_participants_by_recent"> + <on_click + function="IMFloaterContainer.Action" + parameter="sort_participants_by_recent" /> + <on_check + function="IMFloaterContainer.Check" + parameter="sort_participants_by_recent" /> + </menu_item_check> + <menu_item_check + label="Sort participants by distance from you" + layout="topleft" + name="sort_participants_by_distance"> + <on_click + function="IMFloaterContainer.Action" + parameter="sort_participants_by_distance" /> + <on_check + function="IMFloaterContainer.Check" + parameter="sort_participants_by_distance" /> + </menu_item_check> + <menu_item_separator + layout="topleft" /> <menu_item_call label="Chat preferences..." name="chat_preferences"> -- cgit v1.2.3 From d22c8510b19f12e81dc68562de45c2c364036440 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 17 Sep 2012 17:53:17 -0700 Subject: CHUI-340 : WIP : Sorting implemented. Type and name work. Date and distance still need the relevant values to be computed. --- indra/newview/llconversationmodel.cpp | 70 ++++++++++++++++++++++++++++++---- indra/newview/llconversationmodel.h | 17 +++++++++ indra/newview/llimfloatercontainer.cpp | 1 - indra/newview/llparticipantlist.cpp | 21 ++++++++++ 4 files changed, 101 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index c36c3cbc65..612744c3e9 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -37,7 +37,8 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& u LLFolderViewModelItemCommon(root_view_model), mName(display_name), mUUID(uuid), - mNeedsRefresh(true) + mNeedsRefresh(true), + mConvType(CONV_UNKNOWN) { } @@ -45,7 +46,8 @@ LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInte LLFolderViewModelItemCommon(root_view_model), mName(""), mUUID(uuid), - mNeedsRefresh(true) + mNeedsRefresh(true), + mConvType(CONV_UNKNOWN) { } @@ -53,7 +55,8 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod LLFolderViewModelItemCommon(root_view_model), mName(""), mUUID(), - mNeedsRefresh(true) + mNeedsRefresh(true), + mConvType(CONV_UNKNOWN) { } @@ -86,11 +89,13 @@ LLConversationItemSession::LLConversationItemSession(std::string display_name, c LLConversationItem(display_name,uuid,root_view_model), mIsLoaded(false) { + mConvType = CONV_SESSION_UNKNOWN; } LLConversationItemSession::LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLConversationItem(uuid,root_view_model) { + mConvType = CONV_SESSION_UNKNOWN; } bool LLConversationItemSession::hasChildren() const @@ -183,11 +188,13 @@ LLConversationItemParticipant::LLConversationItemParticipant(std::string display mIsMuted(false), mIsModerator(false) { + mConvType = CONV_PARTICIPANT; } LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLConversationItem(uuid,root_view_model) { + mConvType = CONV_PARTICIPANT; } void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) @@ -212,11 +219,60 @@ void LLConversationItemParticipant::dumpDebugData() bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const { - // For the moment, we sort only by name - // *TODO : Implement the sorting by date as well (most recent first) - // *TODO : Check the type of item (session/participants) as order should be different for both (eventually) + LLConversationItem::EConversationType type_a = a->getType(); + LLConversationItem::EConversationType type_b = b->getType(); + + if ((type_a == LLConversationItem::CONV_PARTICIPANT) && (type_b == LLConversationItem::CONV_PARTICIPANT)) + { + // If both are participants + U32 sort_order = getSortOrderParticipants(); + if (sort_order == LLConversationFilter::SO_DATE) + { + F32 time_a = 0.0; + F32 time_b = 0.0; + if (a->getTime(time_a) && b->getTime(time_b)) + { + return (time_a > time_b); + } + } + else if (sort_order == LLConversationFilter::SO_DISTANCE) + { + F32 dist_a = 0.0; + F32 dist_b = 0.0; + if (a->getDistanceToAgent(dist_a) && b->getDistanceToAgent(dist_b)) + { + return (dist_a > dist_b); + } + } + } + else if ((type_a > LLConversationItem::CONV_PARTICIPANT) && (type_b > LLConversationItem::CONV_PARTICIPANT)) + { + // If both are sessions + U32 sort_order = getSortOrderSessions(); + if (sort_order == LLConversationFilter::SO_DATE) + { + F32 time_a = 0.0; + F32 time_b = 0.0; + if (a->getTime(time_a) && b->getTime(time_b)) + { + return (time_a > time_b); + } + } + else if (sort_order == LLConversationFilter::SO_SESSION_TYPE) + { + return (type_a < type_b); + } + } + else + { + // If one is a participant and the other a session, the session is always "less" than the participant + // so we simply compare the type + // Notes: as a consequence, CONV_UNKNOWN (which should never get created...) always come first + return (type_a < type_b); + } + // By default, in all other possible cases (including sort order of type LLConversationFilter::SO_NAME of course), sort by name S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); - return (compare < 0); + return (compare < 0); } // diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index ef1903ab19..954543f91a 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -46,6 +46,17 @@ typedef std::map<LLUUID, LLFolderViewItem*> conversations_widgets_map; class LLConversationItem : public LLFolderViewModelItemCommon { public: + enum EConversationType + { + CONV_UNKNOWN = 0, + CONV_PARTICIPANT = 1, + CONV_SESSION_NEARBY = 2, // The order counts here as it is used to sort sessions by type + CONV_SESSION_1_ON_1 = 3, + CONV_SESSION_AD_HOC = 4, + CONV_SESSION_GROUP = 5, + CONV_SESSION_UNKNOWN = 6 + }; + LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItem(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItem(LLFolderViewModelInterface& root_view_model); @@ -93,6 +104,11 @@ public: virtual void selectItem(void) { } virtual void showProperties(void); + // Methods used in sorting (see LLConversationSort::operator() + EConversationType const getType() const { return mConvType; } + virtual const bool getTime(F32& time) const { return false; } + virtual const bool getDistanceToAgent(F32& distance) const { return false; } + // This method will be called to determine if a drop can be // performed, and will set drop to TRUE if a drop is // requested. @@ -111,6 +127,7 @@ public: protected: std::string mName; // Name of the session or the participant LLUUID mUUID; // UUID of the session or the participant + EConversationType mConvType; // Type of conversation item bool mNeedsRefresh; // Flag signaling to the view that something changed for this item }; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index ab4b64471b..76bd6b14b9 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -740,7 +740,6 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) llwarns << "Couldn't create conversation session item : " << display_name << llendl; return; } - // *TODO: Should we flag LLConversationItemSession with a mIsNearbyChat? item->renameItem(display_name); mConversationsItems[uuid] = item; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 0d1a37c835..339cee3f95 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -280,6 +280,27 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, } // we need to exclude agent id for non group chat sort(); + + // Identify and store what kind of session we are + LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(data_source->getSessionID()); + if (im_session) + { + // By default, sessions that can't be identified as group or ad-hoc will be considered P2P (i.e. 1 on 1) + mConvType = CONV_SESSION_1_ON_1; + if (im_session->isAdHocSessionType()) + { + mConvType = CONV_SESSION_AD_HOC; + } + else if (im_session->isGroupSessionType()) + { + mConvType = CONV_SESSION_GROUP; + } + } + else + { + // That's the only session that doesn't get listed in the LLIMModel as a session... + mConvType = CONV_SESSION_NEARBY; + } } LLParticipantList::~LLParticipantList() -- cgit v1.2.3 From a3607a8d8c86b2c25bfa0abda1b0fc9b00f2c099 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Tue, 18 Sep 2012 16:41:37 +0300 Subject: CHUI-339 FIXED (2 entries shown in conversation log for ad hoc conference for user that starts the conference) --- indra/newview/llconversationlog.cpp | 35 ++++++++++++++++++++++------------- indra/newview/llconversationlog.h | 8 ++++---- indra/newview/llimview.cpp | 21 +++++++++++++++++---- indra/newview/llimview.h | 6 ++++-- 4 files changed, 47 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 27be2bc5ae..44bee70427 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -75,7 +75,7 @@ LLConversation::LLConversation(const LLIMModel::LLIMSession& session) mConversationType(session.mSessionType), mConversationName(session.mName), mHistoryFileName(session.mHistoryFileName), - mSessionID(session.mSessionID), + mSessionID(session.isOutgoingAdHoc() ? session.generateOutgouigAdHocHash() : session.mSessionID), mParticipantID(session.mOtherParticipantID), mIsVoice(session.mStartedAsIMCall), mHasOfflineIMs(session.mHasOfflineMessage) @@ -231,8 +231,8 @@ void LLConversationLog::enableLogging(bool enable) void LLConversationLog::logConversation(const LLUUID& session_id) { - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); - LLConversation* conversation = findConversation(session_id); + const LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); + LLConversation* conversation = findConversation(session); if (session && conversation) { @@ -240,14 +240,12 @@ void LLConversationLog::logConversation(const LLUUID& session_id) } else if (session && !conversation) { - createConversation(session_id); + createConversation(session); } } -void LLConversationLog::createConversation(const LLUUID& session_id) +void LLConversationLog::createConversation(const LLIMModel::LLIMSession* session) { - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); - if (session) { LLConversation conversation(*session); @@ -262,14 +260,18 @@ void LLConversationLog::createConversation(const LLUUID& session_id) } } -void LLConversationLog::updateConversationName(const LLUUID& session_id, const std::string& name) +void LLConversationLog::updateConversationName(const LLIMModel::LLIMSession* session, const std::string& name) { - LLConversation* conversation = findConversation(session_id); + if (!session) + { + return; + } + LLConversation* conversation = findConversation(session); if (conversation) { conversation->setConverstionName(name); - notifyPrticularConversationObservers(session_id, LLConversationLogObserver::CHANGED_NAME); + notifyPrticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_NAME); } } @@ -282,8 +284,15 @@ void LLConversationLog::updateConversationTimestamp(LLConversation* conversation } } -LLConversation* LLConversationLog::findConversation(const LLUUID& session_id) +LLConversation* LLConversationLog::findConversation(const LLIMModel::LLIMSession* session) { + if (!session) + { + return NULL; + } + + const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID; + conversations_vec_t::iterator conv_it = mConversations.begin(); for(; conv_it != mConversations.end(); ++conv_it) { @@ -489,7 +498,7 @@ void LLConversationLog::onNewMessageReceived(const LLSD& data) logConversation(session_id); } -void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session) +void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, const LLIMModel::LLIMSession* session) { - updateConversationName(session->mSessionID, av_name.getCompleteName()); + updateConversationName(session, av_name.getCompleteName()); } diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index a458e975bb..6fff7d6772 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -162,13 +162,13 @@ private: bool saveToFile(const std::string& filename); bool loadFromFile(const std::string& filename); - void onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session); + void onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, const LLIMModel::LLIMSession* session); - void createConversation(const LLUUID& session_id); + void createConversation(const LLIMModel::LLIMSession* session); void updateConversationTimestamp(LLConversation* conversation); - void updateConversationName(const LLUUID& session_id, const std::string& name); + void updateConversationName(const LLIMModel::LLIMSession* session, const std::string& name); - LLConversation* findConversation(const LLUUID& session_id); + LLConversation* findConversation(const LLIMModel::LLIMSession* session); typedef std::vector<LLConversation> conversations_vec_t; std::vector<LLConversation> mConversations; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index f5392b442a..b45903835a 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -536,7 +536,7 @@ LLIMModel::LLIMSession* LLIMModel::findAdHocIMSession(const uuid_vec_t& ids) return NULL; } -bool LLIMModel::LLIMSession::isOutgoingAdHoc() +bool LLIMModel::LLIMSession::isOutgoingAdHoc() const { return IM_SESSION_CONFERENCE_START == mType; } @@ -556,6 +556,19 @@ bool LLIMModel::LLIMSession::isOtherParticipantAvaline() return !mOtherParticipantIsAvatar; } +LLUUID LLIMModel::LLIMSession::generateOutgouigAdHocHash() const +{ + LLUUID hash = LLUUID::null; + + if (mInitialTargetIDs.size()) + { + std::set<LLUUID> sorted_uuids(mInitialTargetIDs.begin(), mInitialTargetIDs.end()); + hash = generateHash(sorted_uuids); + } + + return hash; +} + void LLIMModel::LLIMSession::buildHistoryFileName() { mHistoryFileName = mName; @@ -572,7 +585,7 @@ void LLIMModel::LLIMSession::buildHistoryFileName() if (mInitialTargetIDs.size()) { std::set<LLUUID> sorted_uuids(mInitialTargetIDs.begin(), mInitialTargetIDs.end()); - mHistoryFileName = mName + " hash" + generateHash(sorted_uuids); + mHistoryFileName = mName + " hash" + generateHash(sorted_uuids).asString(); } else { @@ -606,7 +619,7 @@ void LLIMModel::LLIMSession::buildHistoryFileName() } //static -std::string LLIMModel::LLIMSession::generateHash(const std::set<LLUUID>& sorted_uuids) +LLUUID LLIMModel::LLIMSession::generateHash(const std::set<LLUUID>& sorted_uuids) { LLMD5 md5_uuid; @@ -620,7 +633,7 @@ std::string LLIMModel::LLIMSession::generateHash(const std::set<LLUUID>& sorted_ LLUUID participants_md5_hash; md5_uuid.raw_digest((unsigned char*) participants_md5_hash.mData); - return participants_md5_hash.asString(); + return participants_md5_hash; } void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id) diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index fa9d20ca53..82cfa394a6 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -85,7 +85,7 @@ public: /** @deprecated */ static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata); - bool isOutgoingAdHoc(); + bool isOutgoingAdHoc() const; bool isAdHoc(); bool isP2P(); bool isOtherParticipantAvaline(); @@ -95,6 +95,8 @@ public: bool isGroupSessionType() const { return mSessionType == GROUP_SESSION;} bool isAvalineSessionType() const { return mSessionType == AVALINE_SESSION;} + LLUUID generateOutgouigAdHocHash() const; + //*TODO make private /** ad-hoc sessions involve sophisticated chat history file naming schemes */ void buildHistoryFileName(); @@ -139,7 +141,7 @@ public: private: void onAdHocNameCache(const LLAvatarName& av_name); - static std::string generateHash(const std::set<LLUUID>& sorted_uuids); + static LLUUID generateHash(const std::set<LLUUID>& sorted_uuids); }; -- cgit v1.2.3 From 3fb222e939de7ef71630c5754d964fb81e08fce1 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Tue, 18 Sep 2012 18:07:16 +0300 Subject: CHUI-348 FIXED (Voice call icon still shows in conversation log) - Removed code responsible for showing voice icon --- indra/newview/llconversationlog.cpp | 18 ++++++------------ indra/newview/llconversationlog.h | 5 +---- indra/newview/llconversationloglistitem.cpp | 12 ++---------- 3 files changed, 9 insertions(+), 26 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 44bee70427..7a5a476efb 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -36,8 +36,7 @@ struct Conversation_params { Conversation_params(time_t time) : mTime(time), - mTimestamp(LLConversation::createTimestamp(time)), - mIsVoice(false) + mTimestamp(LLConversation::createTimestamp(time)) {} time_t mTime; @@ -47,7 +46,6 @@ struct Conversation_params std::string mHistoryFileName; LLUUID mSessionID; LLUUID mParticipantID; - bool mIsVoice; bool mHasOfflineIMs; }; @@ -63,7 +61,6 @@ LLConversation::LLConversation(const Conversation_params& params) mHistoryFileName(params.mHistoryFileName), mSessionID(params.mSessionID), mParticipantID(params.mParticipantID), - mIsVoice(params.mIsVoice), mHasOfflineIMs(params.mHasOfflineIMs) { setListenIMFloaterOpened(); @@ -77,7 +74,6 @@ LLConversation::LLConversation(const LLIMModel::LLIMSession& session) mHistoryFileName(session.mHistoryFileName), mSessionID(session.isOutgoingAdHoc() ? session.generateOutgouigAdHocHash() : session.mSessionID), mParticipantID(session.mOtherParticipantID), - mIsVoice(session.mStartedAsIMCall), mHasOfflineIMs(session.mHasOfflineMessage) { setListenIMFloaterOpened(); @@ -92,7 +88,6 @@ LLConversation::LLConversation(const LLConversation& conversation) mHistoryFileName = conversation.getHistoryFileName(); mSessionID = conversation.getSessionID(); mParticipantID = conversation.getParticipantID(); - mIsVoice = conversation.isVoice(); mHasOfflineIMs = conversation.hasOfflineMessages(); setListenIMFloaterOpened(); @@ -147,12 +142,11 @@ void LLConversation::setListenIMFloaterOpened() { LLIMFloater* floater = LLIMFloater::findInstance(mSessionID); - bool has_offline_ims = !mIsVoice && mHasOfflineIMs; bool offline_ims_visible = LLIMFloater::isVisible(floater) && floater->hasFocus(); // we don't need to listen for im floater with this conversation is opened // if floater is already opened or this conversation doesn't have unread offline messages - if (has_offline_ims && !offline_ims_visible) + if (mHasOfflineIMs && !offline_ims_visible) { mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1)); } @@ -393,7 +387,7 @@ bool LLConversationLog::saveToFile(const std::string& filename) fprintf(fp, "[%d] %d %d %d %s| %s %s %s|\n", (S32)conv_it->getTime(), (S32)conv_it->getConversationType(), - (S32)conv_it->isVoice(), + (S32)0, (S32)conv_it->hasOfflineMessages(), conv_it->getConversationName().c_str(), participant_id.c_str(), @@ -423,10 +417,11 @@ bool LLConversationLog::loadFromFile(const std::string& filename) char part_id_buffer[MAX_STRING]; char conv_id_buffer[MAX_STRING]; char history_file_name[MAX_STRING]; - int is_voice; int has_offline_ims; int stype; S32 time; + // before CHUI-348 it was a flag of conversation voice state + int prereserved_unused; while (!feof(fp) && fgets(buffer, MAX_STRING, fp)) { @@ -437,7 +432,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename) sscanf(buffer, "[%d] %d %d %d %[^|]| %s %s %[^|]|", &time, &stype, - &is_voice, + &prereserved_unused, &has_offline_ims, conv_name_buffer, part_id_buffer, @@ -446,7 +441,6 @@ bool LLConversationLog::loadFromFile(const std::string& filename) Conversation_params params(time); params.mConversationType = (SessionType)stype; - params.mIsVoice = is_voice; params.mHasOfflineIMs = has_offline_ims; params.mConversationName = std::string(conv_name_buffer); params.mParticipantID = LLUUID(part_id_buffer); diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 6fff7d6772..373406aa6f 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -56,11 +56,9 @@ public: const LLUUID& getParticipantID() const { return mParticipantID; } const std::string& getTimestamp() const { return mTimestamp; } const time_t& getTime() const { return mTime; } - bool isVoice() const { return mIsVoice; } bool hasOfflineMessages() const { return mHasOfflineIMs; } - void setIsVoice(bool is_voice); - void setConverstionName(std::string conv_name) { mConversationName = conv_name; } + void setConverstionName(std::string conv_name) { mConversationName = conv_name; } bool isOlderThan(U32 days) const; @@ -95,7 +93,6 @@ private: std::string mHistoryFileName; LLUUID mSessionID; LLUUID mParticipantID; - bool mIsVoice; bool mHasOfflineIMs; std::string mTimestamp; // last interaction time in form of: mm/dd/yyyy hh:mm }; diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp index fac6130371..b4ae5f19da 100644 --- a/indra/newview/llconversationloglistitem.cpp +++ b/indra/newview/llconversationloglistitem.cpp @@ -49,10 +49,9 @@ LLConversationLogListItem::LLConversationLogListItem(const LLConversation* conve LLIMFloater* floater = LLIMFloater::findInstance(mConversation->getSessionID()); - bool has_offline_ims = !mConversation->isVoice() && mConversation->hasOfflineMessages(); bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); - if (has_offline_ims && !ims_are_read) + if (mConversation->hasOfflineMessages() && !ims_are_read) { mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversationLogListItem::onIMFloaterShown, this, _1)); } @@ -104,16 +103,9 @@ void LLConversationLogListItem::initIcons() break; } - if (mConversation->isVoice()) + if (mConversation->hasOfflineMessages()) { - getChild<LLIconCtrl>("voice_session_icon")->setVisible(TRUE); - } - else - { - if (mConversation->hasOfflineMessages()) - { getChild<LLIconCtrl>("unread_ims_icon")->setVisible(TRUE); - } } } -- cgit v1.2.3 From 3c8407f32cf947ee1631ed66bba7a676e8b3b670 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 18 Sep 2012 12:15:51 -0700 Subject: CHUI-283: Now the avatar icon loads in the user's avatar image.Also the avatar image is of proper size. The participant of the conversation is offset correctly as well. --- indra/llcommon/llfoldertype.h | 4 +- indra/llui/llfolderviewitem.cpp | 230 +++++++++++---------- indra/llui/llfolderviewitem.h | 3 + indra/newview/llconversationmodel.h | 2 +- indra/newview/llconversationview.cpp | 50 ++++- indra/newview/llconversationview.h | 6 +- indra/newview/llviewerfoldertype.cpp | 2 - .../default/xui/en/floater_pathfinding_console.xml | 2 +- .../en/widgets/conversation_view_participant.xml | 8 +- 9 files changed, 185 insertions(+), 122 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h index 609b550900..a0c847914f 100755 --- a/indra/llcommon/llfoldertype.h +++ b/indra/llcommon/llfoldertype.h @@ -89,9 +89,7 @@ public: FT_COUNT, - FT_NONE = -1, - - FT_PROFILEXXXGGG = 58 + FT_NONE = -1 }; static EType lookup(const std::string& type_name); diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 7ca02b726a..5fcb1f51d1 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -105,6 +105,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mSelectPending(FALSE), mLabelStyle( LLFontGL::NORMAL ), mHasVisibleChildren(FALSE), + mLocalIndentation(p.folder_indentation), mIndentation(0), mItemHeight(p.item_height), mControlLabelRotation(0.f), @@ -284,11 +285,9 @@ void LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) // makes sure that this view and its children are the right size. S32 LLFolderViewItem::arrange( S32* width, S32* height ) { - const Params& p = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); - S32 indentation = p.folder_indentation(); // Only indent deeper items in hierarchy mIndentation = (getParentFolder()) - ? getParentFolder()->getIndentation() + indentation + ? getParentFolder()->getIndentation() + mLocalIndentation : 0; if (mLabelWidthDirty) { @@ -596,24 +595,134 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, return handled; } +void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor, + const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor) +{ + + //--------------------------------------------------------------------------------// + // Draw highlight for selected items + // + + const S32 focus_top = getRect().getHeight(); + const S32 focus_bottom = getRect().getHeight() - mItemHeight; + const bool folder_open = (getRect().getHeight() > mItemHeight + 4); + const S32 FOCUS_LEFT = 1; + + if (mIsSelected) // always render "current" item. Only render other selected items if mShowSingleSelection is FALSE + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLColor4 bg_color = bgColor; + if (!mIsCurSelection) + { + // do time-based fade of extra objects + F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); + if (getRoot() && getRoot()->getShowSingleSelection()) + { + // fading out + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); + } + else + { + // fading in + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); + } + } + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + bg_color, hasKeyboardFocus); + if (mIsCurSelection) + { + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + focusOutlineColor, FALSE); + } + if (folder_open) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect + getRect().getWidth() - 2, + 0, + focusOutlineColor, FALSE); + if (showContent) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, + getRect().getWidth() - 2, + 0, + bgColor, TRUE); + } + } + } + else if (mIsMouseOverTitle) + { + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + mouseOverColor, FALSE); + } + + //--------------------------------------------------------------------------------// + // Draw DragNDrop highlight + // + if (mDragAndDropTarget) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + bgColor, FALSE); + if (folder_open) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect + getRect().getWidth() - 2, + 0, + bgColor, FALSE); + } + mDragAndDropTarget = FALSE; + } +} + +void LLFolderViewItem::drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 right_x) +{ + //TODO RN: implement this in terms of getColor() + //if (highlight_link) color = sLinkColor; + //if (gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; + + //--------------------------------------------------------------------------------// + // Draw the actual label text + // + font->renderUTF8(mLabel, 0, x, y, color, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, getRect().getWidth() - (S32) x - mLabelPaddingRight, &right_x, TRUE); +} + void LLFolderViewItem::draw() { static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); - static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); - static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); - static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); + static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); static LLUIColor sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); static LLUIColor sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); - static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); - + + const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); + const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled const Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); const S32 TOP_PAD = default_params.item_top_pad; - const S32 FOCUS_LEFT = 1; + const LLFontGL* font = getLabelFontForStyle(mLabelStyle); getViewModelItem()->update(); @@ -630,93 +739,7 @@ void LLFolderViewItem::draw() } - //--------------------------------------------------------------------------------// - // Draw highlight for selected items - // - const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); - const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled - const S32 focus_top = getRect().getHeight(); - const S32 focus_bottom = getRect().getHeight() - mItemHeight; - const bool folder_open = (getRect().getHeight() > mItemHeight + 4); - if (mIsSelected) // always render "current" item. Only render other selected items if mShowSingleSelection is FALSE - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLColor4 bg_color = sHighlightBgColor; - if (!mIsCurSelection) - { - // do time-based fade of extra objects - F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); - if (getRoot() && getRoot()->getShowSingleSelection()) - { - // fading out - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); - } - else - { - // fading in - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); - } - } - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - bg_color, filled); - if (mIsCurSelection) - { - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sFocusOutlineColor, FALSE); - } - if (folder_open) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, // overlap with bottom edge of above rect - getRect().getWidth() - 2, - 0, - sFocusOutlineColor, FALSE); - if (show_context) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, - getRect().getWidth() - 2, - 0, - sHighlightBgColor, TRUE); - } - } - } - else if (mIsMouseOverTitle) - { - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sMouseOverColor, FALSE); - } - - //--------------------------------------------------------------------------------// - // Draw DragNDrop highlight - // - if (mDragAndDropTarget) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sHighlightBgColor, FALSE); - if (folder_open) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, // overlap with bottom edge of above rect - getRect().getWidth() - 2, - 0, - sHighlightBgColor, FALSE); - } - mDragAndDropTarget = FALSE; - } + drawHighlight(show_context, filled, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); //--------------------------------------------------------------------------------// // Draw open icon @@ -760,19 +783,10 @@ void LLFolderViewItem::draw() LLUIImage* box_image = default_params.selection_image; LLRect box_rect(left, top, right, bottom); box_image->draw(box_rect, sFilterBGColor); - } + } - LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; - //TODO RN: implement this in terms of getColor() - //if (highlight_link) color = sLinkColor; - //if (gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; - - //--------------------------------------------------------------------------------// - // Draw the actual label text - // - font->renderUTF8(mLabel, 0, text_left, y, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, getRect().getWidth() - (S32) text_left - mLabelPaddingRight, &right_x, TRUE); + LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; + drawLabel(font, text_left, y, color, right_x); //--------------------------------------------------------------------------------// // Draw label suffix diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 7025b94a9a..a9e10c92c9 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -93,6 +93,7 @@ protected: LLUIImagePtr mIcon, mIconOpen, mIconOverlay; + S32 mLocalIndentation; S32 mIndentation; S32 mItemHeight; S32 mDragStartX, @@ -235,6 +236,8 @@ public: // virtual void handleDropped(); virtual void draw(); + void drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor); + void drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 right_x); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index ef1903ab19..49af927acf 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -57,7 +57,7 @@ public: virtual const std::string& getSearchableName() const { return mName; } virtual const LLUUID& getUUID() const { return mUUID; } virtual time_t getCreationDate() const { return 0; } - virtual LLPointer<LLUIImage> getIcon() const { return LLUI::getUIImage(LLViewerFolderType::lookupIconName(LLFolderType::FT_PROFILEXXXGGG, FALSE)); } + virtual LLPointer<LLUIImage> getIcon() const { return NULL; } virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } virtual std::string getLabelSuffix() const { return LLStringUtil::null; } diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index d5d4fc13da..721abd5892 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -41,7 +41,7 @@ // static LLDefaultChildRegistry::Register<LLConversationViewSession> r_conversation_view_session("conversation_view_session"); - +const LLColor4U DEFAULT_WHITE(255, 255, 255); LLConversationViewSession::Params::Params() : container() @@ -90,7 +90,6 @@ void LLConversationViewSession::draw() // *TODO Seth PE: remove the code duplicated from LLFolderViewItem::draw() // ***** LLFolderViewItem::draw() code begin ***** - const LLColor4U DEFAULT_WHITE(255, 255, 255); static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); @@ -317,21 +316,27 @@ S32 LLConversationViewParticipant::sChildrenWidths[LLConversationViewParticipant LLConversationViewParticipant::Params::Params() : container(), participant_id(), +avatar_icon("avatar_icon"), info_button("info_button"), output_monitor("output_monitor") {} LLConversationViewParticipant::LLConversationViewParticipant( const LLConversationViewParticipant::Params& p ): LLFolderViewItem(p), + mAvatarIcon(NULL), mInfoBtn(NULL), mSpeakingIndicator(NULL), mUUID(p.participant_id) { - } void LLConversationViewParticipant::initFromParams(const LLConversationViewParticipant::Params& params) { + LLAvatarIconCtrl::Params avatar_icon_params(params.avatar_icon()); + applyXUILayout(avatar_icon_params, this); + LLAvatarIconCtrl * avatarIcon = LLUICtrlFactory::create<LLAvatarIconCtrl>(avatar_icon_params); + addChild(avatarIcon); + LLButton::Params info_button_params(params.info_button()); applyXUILayout(info_button_params, this); LLButton * button = LLUICtrlFactory::create<LLButton>(info_button_params); @@ -345,6 +350,8 @@ void LLConversationViewParticipant::initFromParams(const LLConversationViewParti BOOL LLConversationViewParticipant::postBuild() { + mAvatarIcon = getChild<LLAvatarIconCtrl>("avatar_icon"); + mInfoBtn = getChild<LLButton>("info_btn"); mInfoBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onInfoBtnClick, this)); mInfoBtn->setVisible(false); @@ -363,6 +370,36 @@ BOOL LLConversationViewParticipant::postBuild() return LLFolderViewItem::postBuild(); } +void LLConversationViewParticipant::draw() +{ + static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); + static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + + const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); + const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled + + const LLFolderViewItem::Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); + const S32 TOP_PAD = default_params.item_top_pad; + + const LLFontGL* font = getLabelFontForStyle(mLabelStyle); + F32 right_x = 0; + + //TEXT_PAD, TOP_PAD, ICON_PAD and mIndentation are temporary values and will non-const eventually since they don't + //apply to every single layout + F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + F32 text_left = (F32)(mAvatarIcon->getRect().mRight + ICON_PAD + mIndentation); + LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; + + drawHighlight(show_context, filled, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); + drawLabel(font, text_left, y, color, right_x); + + LLView::draw(); +} + + void LLConversationViewParticipant::refresh() { // Refresh the participant view from its model data @@ -384,8 +421,11 @@ void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder) LLConversationItem* vmi = this->getParentFolder() ? dynamic_cast<LLConversationItem*>(this->getParentFolder()->getViewModelItem()) : NULL; if(vmi) { - mSpeakingIndicator->setSpeakerId(mUUID, - vmi->getUUID()); //set the session id + //Allows speaking icon image to be loaded based on mUUID + mAvatarIcon->setValue(mUUID); + + //Allows the speaker indicator to be activated based on the user and conversation + mSpeakingIndicator->setSpeakerId(mUUID, vmi->getUUID()); } } diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 3dbc36e811..075ad09d5b 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -29,6 +29,7 @@ #include "llfolderviewitem.h" +#include "llavatariconctrl.h" #include "llbutton.h" #include "lloutputmonitorctrl.h" @@ -84,7 +85,8 @@ public: struct Params : public LLInitParam::Block<Params, LLFolderViewItem::Params> { Optional<LLIMFloaterContainer*> container; - Optional<LLUUID> participant_id; + Optional<LLUUID> participant_id; + Optional<LLAvatarIconCtrl::Params> avatar_icon; Optional<LLButton::Params> info_button; Optional<LLOutputMonitorCtrl::Params> output_monitor; @@ -104,10 +106,12 @@ protected: LLConversationViewParticipant( const Params& p ); void initFromParams(const Params& params); BOOL postBuild(); + /*virtual*/ void draw(); void onInfoBtnClick(); private: + LLAvatarIconCtrl* mAvatarIcon; LLButton * mInfoBtn; LLOutputMonitorCtrl* mSpeakingIndicator; LLUUID mUUID; // UUID of the participant diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index 0a402d8c42..a179b61cff 100755 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -147,8 +147,6 @@ LLViewerFolderDictionary::LLViewerFolderDictionary() addEntry((LLFolderType::EType)type, new ViewerFolderEntry("New Folder", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, false)); } #endif - - addEntry(LLFolderType::FT_PROFILEXXXGGG, new ViewerFolderEntry("Profile", "Generic_Person", "Generic_Person", FALSE, false, "default")); } bool LLViewerFolderDictionary::initEnsemblesFromFile() diff --git a/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml b/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml index 2629313069..79f2027c31 100644 --- a/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml +++ b/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml @@ -152,7 +152,7 @@ </text> <check_box height="19" - label="World" + label="Test" layout="topleft" name="show_world" top_pad="4" diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml index b00e8aaeee..7ddcfe3b03 100755 --- a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml +++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml @@ -1,13 +1,19 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <conversation_view_participant folder_arrow_image="ForSale_Badge" - folder_indentation="8" + folder_indentation="0" item_height="24" item_top_pad="4" selection_image="Rounded_Square" mouse_opaque="true" follows="left|top|right" > +<avatar_icon + follows="left" + height="20" + default_icon_name="Generic_Person" + left="50" + width="20" /> <info_button follows="right" height="16" -- cgit v1.2.3 From 86ac47474f42598d3edb65970117b442457f7284 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 18 Sep 2012 15:04:23 -0700 Subject: Regress Fix: After a CHUI 283 commit the inventory items suffix was overlapping text. Problem was that a variable storing the width of the text was not passed in as a reference, which always resulted in the suffix overlapping the prior text. --- indra/llui/llfolderviewitem.cpp | 4 ++-- indra/llui/llfolderviewitem.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 5fcb1f51d1..a20ce23b18 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -689,7 +689,7 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo } } -void LLFolderViewItem::drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 right_x) +void LLFolderViewItem::drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x) { //TODO RN: implement this in terms of getColor() //if (highlight_link) color = sLinkColor; @@ -797,7 +797,7 @@ void LLFolderViewItem::draw() LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE ); } - + //--------------------------------------------------------------------------------// // Highlight string match // diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index a9e10c92c9..5c97407bc1 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -237,7 +237,7 @@ public: // virtual void handleDropped(); virtual void draw(); void drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor); - void drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 right_x); + void drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, -- cgit v1.2.3 From fcb010e835d9b894ba6d1012ac8e3a85c5ab3400 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Wed, 19 Sep 2012 19:20:21 +0300 Subject: CHUI-338 FIXED (LLAvatarNameResponder warning shown in debug console when using spinner to page through chat history viewer) - Trying to restore avatarID by its name before appending message to chat history. - Also prevented requesting avatar name by null LLUUID in LLAvatarIconCtrl::setValue --- indra/newview/llavatariconctrl.cpp | 7 ++-- indra/newview/llfloaterconversationpreview.cpp | 27 ++++++++++++--- indra/newview/llnearbychat.cpp | 40 +++++++++++----------- indra/newview/llnearbychat.h | 2 ++ .../xui/en/floater_conversation_preview.xml | 2 +- 5 files changed, 50 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index b539ac38ed..62c6c6763b 100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -245,9 +245,10 @@ void LLAvatarIconCtrl::setValue(const LLSD& value) LLIconCtrl::setValue(value); } - LLAvatarNameCache::get(mAvatarId, - boost::bind(&LLAvatarIconCtrl::onAvatarNameCache, - this, _1, _2)); + if (mAvatarId != LLUUID::null) + { + LLAvatarNameCache::get(mAvatarId, boost::bind(&LLAvatarIconCtrl::onAvatarNameCache, this, _1, _2)); + } } bool LLAvatarIconCtrl::updateFromCache() diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index 88efc39764..a3825eafc8 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -29,6 +29,7 @@ #include "llfloaterconversationpreview.h" #include "llimview.h" #include "lllineeditor.h" +#include "llnearbychat.h" #include "llspinctrl.h" #include "lltrans.h" @@ -43,7 +44,6 @@ LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_i BOOL LLFloaterConversationPreview::postBuild() { mChatHistory = getChild<LLChatHistory>("chat_history"); - getChild<LLUICtrl>("more_history")->setCommitCallback(boost::bind(&LLFloaterConversationPreview::onMoreHistoryBtnClick, this)); const LLConversation* conv = LLConversationLog::instance().getConversation(mSessionID); std::string name; @@ -119,20 +119,39 @@ void LLFloaterConversationPreview::showHistory() { LLSD msg = *iter; + LLUUID from_id = LLUUID::null; std::string time = msg["time"].asString(); - LLUUID from_id = msg["from_id"].asUUID(); std::string from = msg["from"].asString(); std::string message = msg["message"].asString(); - bool is_history = msg["is_history"].asBoolean(); + + if (msg["from_id"].isDefined()) + { + from_id = msg["from_id"].asUUID(); + } + else + { + std::string legacy_name = gCacheName->buildLegacyName(from); + gCacheName->getUUID(legacy_name, from_id); + } LLChat chat; chat.mFromID = from_id; chat.mSessionID = mSessionID; chat.mFromName = from; chat.mTimeStr = time; - chat.mChatStyle = is_history ? CHAT_STYLE_HISTORY : chat.mChatStyle; + chat.mChatStyle = CHAT_STYLE_HISTORY; chat.mText = message; + if (from_id.isNull() && SYSTEM_FROM == from) + { + chat.mSourceType = CHAT_SOURCE_SYSTEM; + + } + else if (from_id.isNull()) + { + chat.mSourceType = LLNearbyChat::isWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT; + } + mChatHistory->appendMessage(chat); } diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a803b35aa8..76626bd5a6 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -69,26 +69,6 @@ S32 LLNearbyChat::sLastSpecialChatChannel = 0; -// --- function in the global namespace :( --- -bool isWordsName(const std::string& name) -{ - // checking to see if it's display name plus username in parentheses - S32 open_paren = name.find(" (", 0); - S32 close_paren = name.find(')', 0); - - if (open_paren != std::string::npos && - close_paren == name.length()-1) - { - return true; - } - else - { - //checking for a single space - S32 pos = name.find(' ', 0); - return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos; - } -} - const S32 EXPANDED_HEIGHT = 266; const S32 COLLAPSED_HEIGHT = 60; const S32 EXPANDED_MIN_HEIGHT = 150; @@ -717,6 +697,26 @@ void LLNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BO send_chat_from_viewer(utf8_out_text, type, channel); } +// static +bool LLNearbyChat::isWordsName(const std::string& name) +{ + // checking to see if it's display name plus username in parentheses + S32 open_paren = name.find(" (", 0); + S32 close_paren = name.find(')', 0); + + if (open_paren != std::string::npos && + close_paren == name.length()-1) + { + return true; + } + else + { + //checking for a single space + S32 pos = name.find(' ', 0); + return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos; + } +} + // static void LLNearbyChat::startChat(const char* line) { diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 2cbafbfa62..648098113a 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -79,6 +79,8 @@ public: static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate); static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); + static bool isWordsName(const std::string& name); + void showHistory(); protected: diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml index 0e5af67f68..6f1ddaaf4f 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -52,7 +52,7 @@ width="50"/> <text follows="bottom|right" - font="SandSerif" + font="SansSerif" height="22" layout="topleft" name="page_num_label" -- cgit v1.2.3 From f5fc2a9c3af23cc1aaf74e432eb3690d8d376d89 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 19 Sep 2012 17:59:37 -0700 Subject: CHUI-340 : WIP : Update time stamp for IM and voice utterance --- indra/newview/llimfloater.cpp | 3 +++ indra/newview/llnearbychat.cpp | 3 +++ indra/newview/llparticipantlist.cpp | 21 +++++++++++++++++++++ indra/newview/llparticipantlist.h | 9 +++++++++ indra/newview/llspeakers.cpp | 17 +++++++++++++++++ indra/newview/llspeakers.h | 9 +++++++++ 6 files changed, 62 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 2474fe0891..fbc1b8e7fe 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -907,6 +907,9 @@ void LLIMFloater::updateMessages() chat.mText = message; } + // Merov debug + llinfos << "Merov debug : LLIMFloater::updateMessages, session = " << mSessionID << ", from = " << msg["from"].asString() << ", uuid = " << msg["from_id"].asString() << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; + appendMessage(chat); mLastMessageIndex = msg["index"].asInteger(); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 76626bd5a6..bf47aa06a8 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -233,6 +233,9 @@ void LLNearbyChat::loadHistory() gCacheName->getUUID(legacy_name, from_id); } + // Merov debug + llinfos << "Merov debug : LLNearbyChat::loadHistory, session = " << mSessionID << ", from = " << msg[IM_FROM].asString() << ", uuid = " << msg[IM_FROM_ID].asString() << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; + LLChat chat; chat.mFromName = from; chat.mFromID = from_id; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 339cee3f95..8bc6bb60cf 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -224,12 +224,14 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, mSpeakerRemoveListener = new SpeakerRemoveListener(*this); mSpeakerClearListener = new SpeakerClearListener(*this); mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this); + mSpeakerUpdateListener = new SpeakerUpdateListener(*this); mSpeakerMuteListener = new SpeakerMuteListener(*this); mSpeakerMgr->addListener(mSpeakerAddListener, "add"); mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove"); mSpeakerMgr->addListener(mSpeakerClearListener, "clear"); mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator"); + mSpeakerMgr->addListener(mSpeakerUpdateListener, "update_speaker"); setSessionID(mSpeakerMgr->getSessionID()); @@ -584,6 +586,17 @@ bool LLParticipantList::onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, return true; } +bool LLParticipantList::onSpeakerUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ + const LLSD& evt_data = event->getValue(); + if ( evt_data.has("id") ) + { + LLUUID id = evt_data["id"]; + llinfos << "Merov debug : onSpeakerUpdateEvent, session = " << mUUID << ", uuid = " << id << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; + } + return true; +} + bool LLParticipantList::onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) { const LLSD& evt_data = event->getValue(); @@ -745,6 +758,14 @@ bool LLParticipantList::SpeakerClearListener::handleEvent(LLPointer<LLOldEvents: return mParent.onClearListEvent(event, userdata); } +// +// LLParticipantList::SpeakerUpdateListener +// +bool LLParticipantList::SpeakerUpdateListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ + return mParent.onSpeakerUpdateEvent(event, userdata); +} + // // LLParticipantList::SpeakerModeratorListener // diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index f8165aa292..acee68873c 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -95,6 +95,7 @@ protected: bool onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + bool onSpeakerUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); /** @@ -136,6 +137,13 @@ protected: /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); }; + class SpeakerUpdateListener : public BaseSpeakerListener + { + public: + SpeakerUpdateListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} + /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + }; + class SpeakerModeratorUpdateListener : public BaseSpeakerListener { public: @@ -264,6 +272,7 @@ private: LLPointer<SpeakerAddListener> mSpeakerAddListener; LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener; LLPointer<SpeakerClearListener> mSpeakerClearListener; + LLPointer<SpeakerUpdateListener> mSpeakerUpdateListener; LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener; LLPointer<SpeakerMuteListener> mSpeakerMuteListener; diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 07d2f1ad6f..f50ae28421 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -84,6 +84,19 @@ bool LLSpeaker::isInVoiceChannel() return mStatus <= LLSpeaker::STATUS_VOICE_ACTIVE || mStatus == LLSpeaker::STATUS_MUTED; } +LLSpeakerUpdateSpeakerEvent::LLSpeakerUpdateSpeakerEvent(LLSpeaker* source) +: LLEvent(source, "Speaker update speaker event"), +mSpeakerID (source->mID) +{ +} + +LLSD LLSpeakerUpdateSpeakerEvent::getValue() +{ + LLSD ret; + ret["id"] = mSpeakerID; + return ret; +} + LLSpeakerUpdateModeratorEvent::LLSpeakerUpdateModeratorEvent(LLSpeaker* source) : LLEvent(source, "Speaker add moderator event"), mSpeakerID (source->mID), @@ -374,6 +387,8 @@ void LLSpeakerMgr::update(BOOL resort_ok) { speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32(); speakerp->mHasSpoken = TRUE; + llinfos << "Merov debug : LLSpeakerMgr::update, session = " << getSessionID() << ", uuid = " << speaker_id << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; + speakerp->fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker"); } speakerp->mStatus = LLSpeaker::STATUS_SPEAKING; // interpolate between active color and full speaking color based on power of speech output @@ -548,6 +563,8 @@ void LLSpeakerMgr::speakerChatted(const LLUUID& speaker_id) { speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32(); speakerp->mHasSpoken = TRUE; + llinfos << "Merov debug : LLSpeakerMgr::speakerChatted, session = " << getSessionID() << ", uuid = " << speaker_id << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; + speakerp->fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker"); } } diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 1c6f51e131..8ab08661d3 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -79,6 +79,15 @@ public: BOOL mModeratorMutedText; }; +class LLSpeakerUpdateSpeakerEvent : public LLOldEvents::LLEvent +{ +public: + LLSpeakerUpdateSpeakerEvent(LLSpeaker* source); + /*virtual*/ LLSD getValue(); +private: + const LLUUID& mSpeakerID; +}; + class LLSpeakerUpdateModeratorEvent : public LLOldEvents::LLEvent { public: -- cgit v1.2.3 From 5cb0a6221613f1a2f1181cea0fb8bd526ab872bf Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 20 Sep 2012 11:28:10 -0700 Subject: CHUI-353: Regress Bug caused by a CHUI 283 commit. Problem: The font was rendering differently due to the folderviewitem::draw() method calling llview::draw(). I added llview::draw() initially but it is not longer needed. Resolution: Removing the call to llview::draw(). --- indra/llui/llfolderviewitem.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index a20ce23b18..171af92e73 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -809,9 +809,6 @@ void LLFolderViewItem::draw() sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, filter_string_length, S32_MAX, &right_x, FALSE ); } - - - LLView::draw(); } const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const -- cgit v1.2.3 From bb8820c70b6dc50524fa8e35a4a14b3cb66bf26c Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 20 Sep 2012 13:22:21 -0700 Subject: CHUI-340 : WIP : Fix the event firing from LLSpeakerMgr to LLParticipantList --- indra/newview/llspeakers.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index f50ae28421..2d2b5202e0 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -86,7 +86,7 @@ bool LLSpeaker::isInVoiceChannel() LLSpeakerUpdateSpeakerEvent::LLSpeakerUpdateSpeakerEvent(LLSpeaker* source) : LLEvent(source, "Speaker update speaker event"), -mSpeakerID (source->mID) + mSpeakerID (source->mID) { } @@ -387,8 +387,7 @@ void LLSpeakerMgr::update(BOOL resort_ok) { speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32(); speakerp->mHasSpoken = TRUE; - llinfos << "Merov debug : LLSpeakerMgr::update, session = " << getSessionID() << ", uuid = " << speaker_id << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; - speakerp->fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker"); + fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker"); } speakerp->mStatus = LLSpeaker::STATUS_SPEAKING; // interpolate between active color and full speaking color based on power of speech output @@ -563,8 +562,7 @@ void LLSpeakerMgr::speakerChatted(const LLUUID& speaker_id) { speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32(); speakerp->mHasSpoken = TRUE; - llinfos << "Merov debug : LLSpeakerMgr::speakerChatted, session = " << getSessionID() << ", uuid = " << speaker_id << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; - speakerp->fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker"); + fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker"); } } -- cgit v1.2.3 From 381c13d0e51c3c054fdf2afeff8a8bcb6fc7aa11 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 20 Sep 2012 16:12:28 -0700 Subject: CHUI-283: Refactor of how the layout is determined for LLFolderViewItem. Changed constant members that defined the layout to non-const member varaibles, which are populated using a .xml file. --- indra/llui/llfolderview.cpp | 20 ++++--- indra/llui/llfolderviewitem.cpp | 63 ++++++++++++++++------ indra/llui/llfolderviewitem.h | 29 ++++++---- indra/newview/llconversationview.cpp | 24 ++++----- indra/newview/llconversationview.h | 2 + .../default/xui/en/panel_outbox_inventory.xml | 9 +++- .../en/widgets/conversation_view_participant.xml | 11 +++- .../xui/en/widgets/conversation_view_session.xml | 9 +++- .../default/xui/en/widgets/folder_view_item.xml | 8 ++- .../xui/en/widgets/inbox_folder_view_folder.xml | 8 ++- 10 files changed, 130 insertions(+), 53 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 11004fe390..ab4efea4dd 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -56,11 +56,7 @@ const S32 RENAME_WIDTH_PAD = 4; const S32 RENAME_HEIGHT_PAD = 1; const S32 AUTO_OPEN_STACK_DEPTH = 16; -const S32 MIN_ITEM_WIDTH_VISIBLE = LLFolderViewItem::ICON_WIDTH - + LLFolderViewItem::ICON_PAD - + LLFolderViewItem::ARROW_SIZE - + LLFolderViewItem::TEXT_PAD - + /*first few characters*/ 40; + const S32 MINIMUM_RENAMER_WIDTH = 80; // *TODO: move in params in xml if necessary. Requires modification of LLFolderView & LLInventoryPanel Params. @@ -211,10 +207,11 @@ LLFolderView::LLFolderView(const Params& p) // Textbox LLTextBox::Params text_p; LLFontGL* font = getLabelFontForStyle(mLabelStyle); - LLRect new_r = LLRect(rect.mLeft + ICON_PAD, - rect.mTop - TEXT_PAD, + //mIconPad, mTextPad are set in folder_view_item.xml + LLRect new_r = LLRect(rect.mLeft + mIconPad, + rect.mTop - mTextPad, rect.mRight, - rect.mTop - TEXT_PAD - font->getLineHeight()); + rect.mTop - mTextPad - font->getLineHeight()); text_p.rect(new_r); text_p.name(std::string(p.name)); text_p.font(font); @@ -1652,12 +1649,13 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight(); // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder - S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); + S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + item->getIconPad()) : local_rect.getHeight(); // get portion of item that we want to see... LLRect item_local_rect = LLRect(item->getIndentation(), local_rect.getHeight(), - llmin(MIN_ITEM_WIDTH_VISIBLE, local_rect.getWidth()), + //+32 is supposed to include few first characters + llmin(item->getLabelXPos() + 32, local_rect.getWidth()), llmax(0, local_rect.getHeight() - max_height_to_show)); LLRect item_doc_rect; @@ -1874,7 +1872,7 @@ void LLFolderView::updateRenamerPosition() if(mRenameItem) { // See also LLFolderViewItem::draw() - S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mRenameItem->getIndentation(); + S32 x = mRenameItem->getLabelXPos(); S32 y = mRenameItem->getRect().getHeight() - mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; mRenameItem->localPointToScreen( x, y, &x, &y ); screenPointToLocal( x, y, &x, &y ); diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 171af92e73..9632612752 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -90,7 +90,14 @@ LLFolderViewItem::Params::Params() item_height("item_height"), item_top_pad("item_top_pad"), creation_date(), - allow_open("allow_open", true) + allow_open("allow_open", true), + left_pad("left_pad", 0), + icon_pad("icon_pad", 0), + icon_width("icon_width", 0), + text_pad("text_pad", 0), + text_pad_right("text_pad_right", 0), + arrow_size("arrow_size", 0), + max_folder_item_overlap("max_folder_item_overlap", 0) {} // Default constructor @@ -98,7 +105,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) : LLView(p), mLabelWidth(0), mLabelWidthDirty(false), - mLabelPaddingRight(DEFAULT_TEXT_PADDING_RIGHT), + mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT), mParentFolder( NULL ), mIsSelected( FALSE ), mIsCurSelection( FALSE ), @@ -114,7 +121,14 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mRoot(p.root), mViewModelItem(p.listener), mIsMouseOverTitle(false), - mAllowOpen(p.allow_open) + mAllowOpen(p.allow_open), + mLeftPad(p.left_pad), + mIconPad(p.icon_pad), + mIconWidth(p.icon_width), + mTextPad(p.text_pad), + mTextPadRight(p.text_pad_right), + mArrowSize(p.arrow_size), + mMaxFolderItemOverlap(p.max_folder_item_overlap) { if (mViewModelItem) { @@ -291,11 +305,11 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height ) : 0; if (mLabelWidthDirty) { - mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + mLabelPaddingRight; + mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + mLabelPaddingRight; mLabelWidthDirty = false; } - *width = llmax(*width, mLabelWidth + mIndentation); + *width = llmax(*width, mLabelWidth); // determine if we need to use ellipses to avoid horizontal scroll. EXT-719 bool use_ellipses = getRoot()->getUseEllipses(); @@ -313,6 +327,21 @@ S32 LLFolderViewItem::getItemHeight() return mItemHeight; } +S32 LLFolderViewItem::getLabelXPos() +{ + return getIndentation() + mArrowSize + mTextPad + mIconWidth + mIconPad; +} + +S32 LLFolderViewItem::getIconPad() +{ + return mIconPad; +} + +S32 LLFolderViewItem::getTextPad() +{ + return mTextPad; +} + // *TODO: This can be optimized a lot by simply recording that it is // selected in the appropriate places, and assuming that set selection // means 'deselect' for a leaf item. Do this optimization after @@ -734,8 +763,8 @@ void LLFolderViewItem::draw() { LLUIImage* arrow_image = default_params.folder_arrow_image; gl_draw_scaled_rotated_image( - mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD - TOP_PAD, - ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, arrow_image->getImage(), sFgColor); + mIndentation, getRect().getHeight() - mArrowSize - mTextPad - TOP_PAD, + mArrowSize, mArrowSize, mControlLabelRotation, arrow_image->getImage(), sFgColor); } @@ -744,7 +773,7 @@ void LLFolderViewItem::draw() //--------------------------------------------------------------------------------// // Draw open icon // - const S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; + const S32 icon_x = mIndentation + mArrowSize + mTextPad; if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders { mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); @@ -769,8 +798,8 @@ void LLFolderViewItem::draw() std::string::size_type filter_string_length = mViewModelItem->hasFilterStringMatch() ? mViewModelItem->getFilterStringSize() : 0; F32 right_x = 0; - F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; - F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); + F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; + F32 text_left = (F32)getLabelXPos(); std::string combined_string = mLabel + mLabelSuffix; if (filter_string_length > 0) @@ -804,11 +833,15 @@ void LLFolderViewItem::draw() if (filter_string_length > 0) { F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mViewModelItem->getFilterStringOffset()); - F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; font->renderUTF8( combined_string, mViewModelItem->getFilterStringOffset(), match_string_left, yy, sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, filter_string_length, S32_MAX, &right_x, FALSE ); } + + //Gilbert Linden 9-20-2012: Although this should be legal, removing it because it causes the mLabelSuffix rendering to + //be distorted...oddly. I initially added this in but didn't need it after all. So removing to prevent unnecessary bug. + //LLView::draw(); } const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const @@ -984,7 +1017,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height ) folders_t::iterator fit = iter++; // number of pixels that bottom of folder label is from top of parent folder if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight() - > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) + > llround(mCurHeight) + mMaxFolderItemOverlap) { // hide if beyond current folder height (*fit)->setVisible(FALSE); @@ -997,7 +1030,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height ) items_t::iterator iit = iter++; // number of pixels that bottom of item label is from top of parent folder if (getRect().getHeight() - (*iit)->getRect().mBottom - > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) + > llround(mCurHeight) + mMaxFolderItemOverlap) { (*iit)->setVisible(FALSE); } @@ -1757,7 +1790,7 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) } if( !handled ) { - if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD) + if(mIndentation < x && x < mIndentation + mArrowSize + mTextPad) { toggleOpen(); handled = TRUE; @@ -1781,7 +1814,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) } if( !handled ) { - if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD) + if(mIndentation < x && x < mIndentation + mArrowSize + mTextPad) { // don't select when user double-clicks plus sign // so as not to contradict single-click behavior diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 5c97407bc1..b7e0091aca 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -60,18 +60,18 @@ public: Optional<time_t> creation_date; Optional<bool> allow_open; + Optional<S32> left_pad, + icon_pad, + icon_width, + text_pad, + text_pad_right, + arrow_size, + max_folder_item_overlap; Params(); }; - // layout constants - static const S32 LEFT_PAD = 5, - ICON_PAD = 2, - ICON_WIDTH = 16, - TEXT_PAD = 1, - DEFAULT_TEXT_PADDING_RIGHT = 4, - ARROW_SIZE = 12, - MAX_FOLDER_ITEM_OVERLAP = 2; - + + static const S32 DEFAULT_LABEL_PADDING_RIGHT = 4; // animation parameters static const F32 FOLDER_CLOSE_TIME_CONSTANT, FOLDER_OPEN_TIME_CONSTANT; @@ -99,6 +99,14 @@ protected: S32 mDragStartX, mDragStartY; + S32 mLeftPad, + mIconPad, + mIconWidth, + mTextPad, + mTextPadRight, + mArrowSize, + mMaxFolderItemOverlap; + F32 mControlLabelRotation; LLFolderView* mRoot; bool mHasVisibleChildren, @@ -136,6 +144,9 @@ public: // makes sure that this view and it's children are the right size. virtual S32 arrange( S32* width, S32* height ); virtual S32 getItemHeight(); + virtual S32 getLabelXPos(); + S32 getIconPad(); + S32 getTextPad(); // If 'selection' is 'this' then note that otherwise ignore. // Returns TRUE if this item ends up being selected. diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 721abd5892..6860415377 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -109,8 +109,8 @@ void LLConversationViewSession::draw() { LLUIImage* arrow_image = default_params.folder_arrow_image; gl_draw_scaled_rotated_image( - mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD - TOP_PAD, - ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, arrow_image->getImage(), sFgColor); + mIndentation, getRect().getHeight() - mArrowSize - mTextPad - TOP_PAD, + mArrowSize, mArrowSize, mControlLabelRotation, arrow_image->getImage(), sFgColor); } @@ -227,7 +227,7 @@ void LLConversationViewSession::draw() // virtual S32 LLConversationViewSession::arrange(S32* width, S32* height) { - LLRect rect(getIndentation() + ARROW_SIZE, + LLRect rect(getIndentation() + mArrowSize, getLocalRect().mTop, getLocalRect().mRight, getLocalRect().mTop - getItemHeight()); @@ -336,7 +336,7 @@ void LLConversationViewParticipant::initFromParams(const LLConversationViewParti applyXUILayout(avatar_icon_params, this); LLAvatarIconCtrl * avatarIcon = LLUICtrlFactory::create<LLAvatarIconCtrl>(avatar_icon_params); addChild(avatarIcon); - + LLButton::Params info_button_params(params.info_button()); applyXUILayout(info_button_params, this); LLButton * button = LLUICtrlFactory::create<LLButton>(info_button_params); @@ -381,16 +381,11 @@ void LLConversationViewParticipant::draw() const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled - const LLFolderViewItem::Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); - const S32 TOP_PAD = default_params.item_top_pad; - const LLFontGL* font = getLabelFontForStyle(mLabelStyle); F32 right_x = 0; - //TEXT_PAD, TOP_PAD, ICON_PAD and mIndentation are temporary values and will non-const eventually since they don't - //apply to every single layout - F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; - F32 text_left = (F32)(mAvatarIcon->getRect().mRight + ICON_PAD + mIndentation); + F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad; + F32 text_left = (F32)getLabelXPos(); LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; drawHighlight(show_context, filled, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); @@ -448,6 +443,11 @@ void LLConversationViewParticipant::onMouseLeave(S32 x, S32 y, MASK mask) LLFolderViewItem::onMouseEnter(x, y, mask); } +S32 LLConversationViewParticipant::getLabelXPos() +{ + return mAvatarIcon->getRect().mRight + mIconPad; +} + // static void LLConversationViewParticipant::initChildrenWidths(LLConversationViewParticipant* self) { @@ -465,7 +465,7 @@ void LLConversationViewParticipant::initChildrenWidths(LLConversationViewPartici void LLConversationViewParticipant::computeLabelRightPadding() { - mLabelPaddingRight = DEFAULT_TEXT_PADDING_RIGHT; + mLabelPaddingRight = DEFAULT_LABEL_PADDING_RIGHT; LLView* control; S32 ctrl_width; diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 075ad09d5b..5bc4678b7b 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -101,6 +101,8 @@ public: void onMouseEnter(S32 x, S32 y, MASK mask); void onMouseLeave(S32 x, S32 y, MASK mask); + /*virtual*/ S32 getLabelXPos(); + protected: friend class LLUICtrlFactory; LLConversationViewParticipant( const Params& p ); diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml index 203febbf18..c80e5b168a 100644 --- a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml @@ -20,6 +20,13 @@ folder_indentation="8" item_height="20" item_top_pad="4" - selection_image="Rounded_Square"/> + selection_image="Rounded_Square" + left_pad="5" + icon_pad="2" + icon_width="16" + text_pad="1" + text_pad_right="4" + arrow_size="12" + max_folder_item_overlap="2"/> <item allow_open="false"/> </inventory_panel> diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml index 7ddcfe3b03..a28d6e0209 100755 --- a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml +++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml @@ -1,12 +1,19 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <conversation_view_participant - folder_arrow_image="ForSale_Badge" + folder_arrow_image="Folder_Arrow" folder_indentation="0" item_height="24" - item_top_pad="4" + item_top_pad="0" selection_image="Rounded_Square" mouse_opaque="true" follows="left|top|right" + left_pad="0" + icon_pad="10" + icon_width="20" + text_pad="7" + text_pad_right="4" + arrow_size="12" + max_folder_item_overlap="2" > <avatar_icon follows="left" diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_session.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_session.xml index f44731ea3d..b8c39eec1d 100644 --- a/indra/newview/skins/default/xui/en/widgets/conversation_view_session.xml +++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_session.xml @@ -6,4 +6,11 @@ item_top_pad="4" selection_image="Rounded_Square" mouse_opaque="true" - follows="left|top|right"/> + follows="left|top|right" + left_pad="5" + icon_pad="2" + icon_width="16" + text_pad="1" + text_pad_right="4" + arrow_size="12" + max_folder_item_overlap="2"/> diff --git a/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml b/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml index 6fa74f403d..bbd53ccb12 100644 --- a/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml +++ b/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml @@ -7,4 +7,10 @@ selection_image="Rounded_Square" mouse_opaque="true" follows="left|top|right" - /> + left_pad="5" + icon_pad="2" + icon_width="16" + text_pad="1" + text_pad_right="4" + arrow_size="12" + max_folder_item_overlap="2"/> diff --git a/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml b/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml index 77d8024cb2..590a4730a9 100644 --- a/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml +++ b/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml @@ -5,7 +5,13 @@ item_height="20" item_top_pad="4" selection_image="Rounded_Square" - > + left_pad="5" + icon_pad="2" + icon_width="16" + text_pad="1" + text_pad_right="4" + arrow_size="12" + max_folder_item_overlap="2"> <new_badge label="New" label_offset_horiz="-1" -- cgit v1.2.3 From 59a6a23ee0a94a7695679ea8df93bc0c60682262 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 20 Sep 2012 16:33:21 -0700 Subject: CHUI-283: within LLFolderView::scrollToShowItem(), adjusted the calculation that scrolls to the selected item. My prior commit changed this calculation and adjusted it in this commit to preserve prior behavior. --- indra/llui/llfolderview.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index ab4efea4dd..ce1bc5914c 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1654,8 +1654,8 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr // get portion of item that we want to see... LLRect item_local_rect = LLRect(item->getIndentation(), local_rect.getHeight(), - //+32 is supposed to include few first characters - llmin(item->getLabelXPos() + 32, local_rect.getWidth()), + //+40 is supposed to include few first characters + llmin(item->getLabelXPos() - item->getIndentation() + 40, local_rect.getWidth()), llmax(0, local_rect.getHeight() - max_height_to_show)); LLRect item_doc_rect; -- cgit v1.2.3 From 1107803a5c6da07cd5171f06afc0490f3eca7bf7 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 20 Sep 2012 17:50:58 -0700 Subject: CHUI-340 : WIP : Implement time update and comparison for sessions and participants --- indra/newview/llconversationmodel.cpp | 44 +++++++++++++++++++++++++++++------ indra/newview/llconversationmodel.h | 10 ++++++-- indra/newview/llparticipantlist.cpp | 9 +++++-- 3 files changed, 52 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 612744c3e9..b39b997a55 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -167,6 +167,31 @@ void LLConversationItemSession::setParticipantIsModerator(const LLUUID& particip } } +// The time of activity of a session is the time of the most recent participation +const bool LLConversationItemSession::getTime(F64& time) const +{ + bool has_time = false; + F64 most_recent_time = 0.0; + LLConversationItemParticipant* participant = NULL; + child_list_t::const_iterator iter; + for (iter = mChildren.begin(); iter != mChildren.end(); iter++) + { + participant = dynamic_cast<LLConversationItemParticipant*>(*iter); + F64 participant_time; + if (participant->getTime(participant_time)) + { + has_time = true; + most_recent_time = llmax(most_recent_time,participant_time); + } + } + if (has_time) + { + time = most_recent_time; + } + llinfos << "Merov debug : get time session, uuid = " << mUUID << ", has_time = " << has_time << ", time = " << time << llendl; + return has_time; +} + void LLConversationItemSession::dumpDebugData() { llinfos << "Merov debug : session, uuid = " << mUUID << ", name = " << mName << ", is loaded = " << mIsLoaded << llendl; @@ -186,7 +211,8 @@ void LLConversationItemSession::dumpDebugData() LLConversationItemParticipant::LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLConversationItem(display_name,uuid,root_view_model), mIsMuted(false), - mIsModerator(false) + mIsModerator(false), + mLastActiveTime(0.0) { mConvType = CONV_PARTICIPANT; } @@ -228,8 +254,8 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL U32 sort_order = getSortOrderParticipants(); if (sort_order == LLConversationFilter::SO_DATE) { - F32 time_a = 0.0; - F32 time_b = 0.0; + F64 time_a = 0.0; + F64 time_b = 0.0; if (a->getTime(time_a) && b->getTime(time_b)) { return (time_a > time_b); @@ -251,8 +277,8 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL U32 sort_order = getSortOrderSessions(); if (sort_order == LLConversationFilter::SO_DATE) { - F32 time_a = 0.0; - F32 time_b = 0.0; + F64 time_a = 0.0; + F64 time_b = 0.0; if (a->getTime(time_a) && b->getTime(time_b)) { return (time_a > time_b); @@ -260,7 +286,10 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL } else if (sort_order == LLConversationFilter::SO_SESSION_TYPE) { - return (type_a < type_b); + if (type_a != type_b) + { + return (type_a < type_b); + } } } else @@ -270,7 +299,8 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL // Notes: as a consequence, CONV_UNKNOWN (which should never get created...) always come first return (type_a < type_b); } - // By default, in all other possible cases (including sort order of type LLConversationFilter::SO_NAME of course), sort by name + // By default, in all other possible cases (including sort order of type LLConversationFilter::SO_NAME of course), + // we sort by name S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); return (compare < 0); } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index dbc04223af..f3f99b5575 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -104,9 +104,9 @@ public: virtual void selectItem(void) { } virtual void showProperties(void); - // Methods used in sorting (see LLConversationSort::operator() + // Methods used in sorting (see LLConversationSort::operator()) EConversationType const getType() const { return mConvType; } - virtual const bool getTime(F32& time) const { return false; } + virtual const bool getTime(F64& time) const { return false; } virtual const bool getDistanceToAgent(F32& distance) const { return false; } // This method will be called to determine if a drop can be @@ -152,6 +152,8 @@ public: bool isLoaded() { return mIsLoaded; } + virtual const bool getTime(F64& time) const; + void dumpDebugData(); private: @@ -169,14 +171,18 @@ public: bool isModerator() {return mIsModerator; } void setIsMuted(bool is_muted) { mIsMuted = is_muted; mNeedsRefresh = true; } void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; } + void setTimeNow() { mLastActiveTime = LLFrameTimer::getElapsedSeconds(); } void onAvatarNameCache(const LLAvatarName& av_name); + virtual const bool getTime(F64& time) const { time = mLastActiveTime; return (time > 0.1 ? true : false); } + void dumpDebugData(); private: bool mIsMuted; // default is false bool mIsModerator; // default is false + F64 mLastActiveTime; }; // We don't want to ever filter conversations but we need to declare that class to create a conversation view model. diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 8bc6bb60cf..9f470a735e 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -591,8 +591,13 @@ bool LLParticipantList::onSpeakerUpdateEvent(LLPointer<LLOldEvents::LLEvent> eve const LLSD& evt_data = event->getValue(); if ( evt_data.has("id") ) { - LLUUID id = evt_data["id"]; - llinfos << "Merov debug : onSpeakerUpdateEvent, session = " << mUUID << ", uuid = " << id << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; + LLUUID participant_id = evt_data["id"]; + LLConversationItemParticipant* participant = findParticipant(participant_id); + if (participant) + { + participant->setTimeNow(); + } + llinfos << "Merov debug : onSpeakerUpdateEvent, session = " << mUUID << ", uuid = " << participant_id << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; } return true; } -- cgit v1.2.3 From fc6bbee3f4ba1abba2956ee92f7ac7ba01d0f59b Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 20 Sep 2012 20:48:20 -0700 Subject: CHUI-340 : WIP : Implement time update on all IM typing cases --- indra/newview/llconversationmodel.cpp | 9 +++++++++ indra/newview/llconversationmodel.h | 1 + indra/newview/llimfloater.cpp | 4 +++- indra/newview/llnearbychat.cpp | 5 +++-- indra/newview/llparticipantlist.cpp | 7 +------ 5 files changed, 17 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index b39b997a55..31f9ca6a32 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -167,6 +167,15 @@ void LLConversationItemSession::setParticipantIsModerator(const LLUUID& particip } } +void LLConversationItemSession::setParticipantTimeNow(const LLUUID& participant_id) +{ + LLConversationItemParticipant* participant = findParticipant(participant_id); + if (participant) + { + participant->setTimeNow(); + } +} + // The time of activity of a session is the time of the most recent participation const bool LLConversationItemSession::getTime(F64& time) const { diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index f3f99b5575..e2c88785a2 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -149,6 +149,7 @@ public: void setParticipantIsMuted(const LLUUID& participant_id, bool is_muted); void setParticipantIsModerator(const LLUUID& participant_id, bool is_moderator); + void setParticipantTimeNow(const LLUUID& participant_id); bool isLoaded() { return mIsLoaded; } diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index fbc1b8e7fe..8268764816 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -907,9 +907,11 @@ void LLIMFloater::updateMessages() chat.mText = message; } - // Merov debug + // Update the participant activity time + mParticipantList->setParticipantTimeNow(from_id); llinfos << "Merov debug : LLIMFloater::updateMessages, session = " << mSessionID << ", from = " << msg["from"].asString() << ", uuid = " << msg["from_id"].asString() << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; + // Add the message to the chat log appendMessage(chat); mLastMessageIndex = msg["index"].asInteger(); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index bf47aa06a8..0d52a9e14c 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -233,9 +233,10 @@ void LLNearbyChat::loadHistory() gCacheName->getUUID(legacy_name, from_id); } - // Merov debug + // Update the participant activity time + mParticipantList->setParticipantTimeNow(from_id); llinfos << "Merov debug : LLNearbyChat::loadHistory, session = " << mSessionID << ", from = " << msg[IM_FROM].asString() << ", uuid = " << msg[IM_FROM_ID].asString() << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; - + LLChat chat; chat.mFromName = from; chat.mFromID = from_id; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 9f470a735e..6283c8f296 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -592,12 +592,7 @@ bool LLParticipantList::onSpeakerUpdateEvent(LLPointer<LLOldEvents::LLEvent> eve if ( evt_data.has("id") ) { LLUUID participant_id = evt_data["id"]; - LLConversationItemParticipant* participant = findParticipant(participant_id); - if (participant) - { - participant->setTimeNow(); - } - llinfos << "Merov debug : onSpeakerUpdateEvent, session = " << mUUID << ", uuid = " << participant_id << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; + setParticipantTimeNow(participant_id); } return true; } -- cgit v1.2.3 From 073065d6520a3b438fce3c5c27ee51c6d86ee742 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 21 Sep 2012 17:52:03 +0300 Subject: CHUI-289 ADD. FIX (Newly added conversation is not selected in conversation list): Select item which was added from avatar picker --- indra/newview/llimconversation.cpp | 1 + indra/newview/llimfloatercontainer.cpp | 4 +++- indra/newview/llimfloatercontainer.h | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index a2efe63546..d5bce5a43f 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -54,6 +54,7 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id) , mInputEditor(NULL) , mInputEditorTopPad(0) , mRefreshTimer(new LLTimer()) + , mHaveFocus(false) { mSession = LLIMModel::getInstance()->findIMSession(mSessionID); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 4e0fba9502..de1fd58661 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -700,7 +700,7 @@ void LLIMFloaterContainer::repositioningWidgets() } } -void LLIMFloaterContainer::setConvItemSelect(LLUUID& session_id) +void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id) { LLFolderViewItem* widget = mConversationsWidgets[session_id]; if (widget && mSelectedSession != session_id) @@ -763,6 +763,8 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) participant_view->addToFolder(widget); current_participant_model++; } + + setConvItemSelect(uuid); return; } diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 1f526091bb..077ecd192b 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -62,7 +62,7 @@ public: /*virtual*/ void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); - void setConvItemSelect(LLUUID& session_id); + void setConvItemSelect(const LLUUID& session_id); /*virtual*/ void tabClose(); static LLFloater* getCurrentVoiceFloater(); -- cgit v1.2.3 From 8b63f7f50367f5726d03fb784f5a2f0783470b9c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 21 Sep 2012 19:42:11 +0300 Subject: CHUI-289 ADDITIONAL FIX (Newly added conversation is not selected in conversation list): gave more meaningful names to variables --- indra/newview/llimconversation.cpp | 10 +++++----- indra/newview/llimconversation.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index d5bce5a43f..ca8493f787 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -54,7 +54,7 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id) , mInputEditor(NULL) , mInputEditorTopPad(0) , mRefreshTimer(new LLTimer()) - , mHaveFocus(false) + , mHasFocus(false) { mSession = LLIMModel::getInstance()->findIMSession(mSessionID); @@ -217,10 +217,10 @@ void LLIMConversation::onFocusReceived() LLTransientDockableFloater::onFocusReceived(); - mHasFocus = mHaveFocus; - mHaveFocus = true; + mHadFocus = mHasFocus; + mHasFocus = true; - if (! mHasFocus) + if (! mHadFocus) { LLIMFloaterContainer* container = LLIMFloaterContainer::getInstance(); container->setConvItemSelect(mSessionID); @@ -230,7 +230,7 @@ void LLIMConversation::onFocusReceived() void LLIMConversation::onFocusLost() { setBackgroundOpaque(false); - mHaveFocus = false; + mHasFocus = false; LLTransientDockableFloater::onFocusLost(); } diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index e09ba79a6a..bad5eaa99f 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -140,8 +140,8 @@ private: LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. + bool mHadFocus; bool mHasFocus; - bool mHaveFocus; }; -- cgit v1.2.3 From 6dd2bf36c52fa00732ed5a3910539f38c91ff173 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 21 Sep 2012 15:27:46 -0700 Subject: CHUI-283: Now the speaker/info icon positions are set based upon visibility.' --- indra/newview/llconversationview.cpp | 23 ++++++++++++++++++---- indra/newview/llconversationview.h | 2 +- .../en/widgets/conversation_view_participant.xml | 2 ++ 3 files changed, 22 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 6860415377..26d618e1b3 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -366,7 +366,7 @@ BOOL LLConversationViewParticipant::postBuild() sStaticInitialized = true; } - computeLabelRightPadding(); + updateChildren(); return LLFolderViewItem::postBuild(); } @@ -432,14 +432,14 @@ void LLConversationViewParticipant::onInfoBtnClick() void LLConversationViewParticipant::onMouseEnter(S32 x, S32 y, MASK mask) { mInfoBtn->setVisible(true); - computeLabelRightPadding(); + updateChildren(); LLFolderViewItem::onMouseEnter(x, y, mask); } void LLConversationViewParticipant::onMouseLeave(S32 x, S32 y, MASK mask) { mInfoBtn->setVisible(false); - computeLabelRightPadding(); + updateChildren(); LLFolderViewItem::onMouseEnter(x, y, mask); } @@ -463,12 +463,14 @@ void LLConversationViewParticipant::initChildrenWidths(LLConversationViewPartici llassert(index == 0); } -void LLConversationViewParticipant::computeLabelRightPadding() +void LLConversationViewParticipant::updateChildren() { mLabelPaddingRight = DEFAULT_LABEL_PADDING_RIGHT; LLView* control; S32 ctrl_width; + LLRect controlRect; + //Cycles through controls starting from right to left for (S32 i = 0; i < ALIC_COUNT; ++i) { control = getItemChildView((EAvatarListItemChildIndex)i); @@ -476,9 +478,22 @@ void LLConversationViewParticipant::computeLabelRightPadding() // skip invisible views if (!control->getVisible()) continue; + //Get current pos/dimensions + controlRect = control->getRect(); + ctrl_width = sChildrenWidths[i]; // including space between current & left controls // accumulate the amount of space taken by the controls mLabelPaddingRight += ctrl_width; + + //Reposition visible controls in case adjacent controls to the right are hidden. + controlRect.setLeftTopAndSize( + getLocalRect().getWidth() - mLabelPaddingRight, + controlRect.mTop, + controlRect.getWidth(), + controlRect.getHeight()); + + //Sets the new position + control->setShape(controlRect); } } diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 5bc4678b7b..0b98c34c73 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -127,7 +127,7 @@ private: static bool sStaticInitialized; // this variable is introduced to improve code readability static S32 sChildrenWidths[ALIC_COUNT]; static void initChildrenWidths(LLConversationViewParticipant* self); - void computeLabelRightPadding(); + void updateChildren(); LLView* getItemChildView(EAvatarListItemChildIndex child_view_index); }; diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml index a28d6e0209..0024decd4c 100755 --- a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml +++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml @@ -19,7 +19,9 @@ follows="left" height="20" default_icon_name="Generic_Person" + layout="topleft" left="50" + top="2" width="20" /> <info_button follows="right" -- cgit v1.2.3 From 18f294715822bedaea3bafa9dfec1ee42c12353c Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 21 Sep 2012 16:26:44 -0700 Subject: CHUI-283: Now the mouse over highlight only shows up when hovering over a participant. Before there was a bug where the onMouseLeave() function was not being called. This prevented the mouse-over-highlight from turning off. --- indra/newview/llconversationview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 26d618e1b3..394a830e5e 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -440,7 +440,7 @@ void LLConversationViewParticipant::onMouseLeave(S32 x, S32 y, MASK mask) { mInfoBtn->setVisible(false); updateChildren(); - LLFolderViewItem::onMouseEnter(x, y, mask); + LLFolderViewItem::onMouseLeave(x, y, mask); } S32 LLConversationViewParticipant::getLabelXPos() -- cgit v1.2.3 From b5583906d0cce652f456851732db5b1c19659662 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 21 Sep 2012 18:12:06 -0700 Subject: CHUI-340 : WIP : Fix sorting bugs on time for sessions, simplified the update time mechanism and clean up --- indra/llui/llfolderviewmodel.h | 2 +- indra/newview/llconversationmodel.cpp | 53 +++++++++++++++++++++++++--------- indra/newview/llconversationmodel.h | 10 +++---- indra/newview/llimconversation.cpp | 8 +++++ indra/newview/llimfloater.cpp | 4 --- indra/newview/llimfloatercontainer.cpp | 15 ++++++++++ indra/newview/llimfloatercontainer.h | 1 + indra/newview/llnearbychat.cpp | 4 --- indra/newview/llparticipantlist.cpp | 7 ++++- 9 files changed, 75 insertions(+), 29 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 22bfc4dfb4..c99fa07c8b 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -226,7 +226,7 @@ public: mParent(NULL), mRootViewModel(root_view_model) { - std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); + mChildren.clear(); } void requestSort() { mSortVersion = -1; } diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 31f9ca6a32..e090d1647f 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -38,7 +38,8 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& u mName(display_name), mUUID(uuid), mNeedsRefresh(true), - mConvType(CONV_UNKNOWN) + mConvType(CONV_UNKNOWN), + mLastActiveTime(0.0) { } @@ -47,7 +48,8 @@ LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInte mName(""), mUUID(uuid), mNeedsRefresh(true), - mConvType(CONV_UNKNOWN) + mConvType(CONV_UNKNOWN), + mLastActiveTime(0.0) { } @@ -56,7 +58,8 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod mName(""), mUUID(), mNeedsRefresh(true), - mConvType(CONV_UNKNOWN) + mConvType(CONV_UNKNOWN), + mLastActiveTime(0.0) { } @@ -167,8 +170,10 @@ void LLConversationItemSession::setParticipantIsModerator(const LLUUID& particip } } -void LLConversationItemSession::setParticipantTimeNow(const LLUUID& participant_id) +void LLConversationItemSession::setTimeNow(const LLUUID& participant_id) { + mLastActiveTime = LLFrameTimer::getElapsedSeconds(); + mNeedsRefresh = true; LLConversationItemParticipant* participant = findParticipant(participant_id); if (participant) { @@ -176,11 +181,11 @@ void LLConversationItemSession::setParticipantTimeNow(const LLUUID& participant_ } } -// The time of activity of a session is the time of the most recent participation +// The time of activity of a session is the time of the most recent activity, session and participants included const bool LLConversationItemSession::getTime(F64& time) const { - bool has_time = false; - F64 most_recent_time = 0.0; + F64 most_recent_time = mLastActiveTime; + bool has_time = (most_recent_time > 0.1); LLConversationItemParticipant* participant = NULL; child_list_t::const_iterator iter; for (iter = mChildren.begin(); iter != mChildren.end(); iter++) @@ -197,7 +202,6 @@ const bool LLConversationItemSession::getTime(F64& time) const { time = most_recent_time; } - llinfos << "Merov debug : get time session, uuid = " << mUUID << ", has_time = " << has_time << ", time = " << time << llendl; return has_time; } @@ -220,8 +224,7 @@ void LLConversationItemSession::dumpDebugData() LLConversationItemParticipant::LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLConversationItem(display_name,uuid,root_view_model), mIsMuted(false), - mIsModerator(false), - mLastActiveTime(0.0) + mIsModerator(false) { mConvType = CONV_PARTICIPANT; } @@ -265,19 +268,34 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL { F64 time_a = 0.0; F64 time_b = 0.0; - if (a->getTime(time_a) && b->getTime(time_b)) + bool has_time_a = a->getTime(time_a); + bool has_time_b = b->getTime(time_b); + if (has_time_a && has_time_b) { return (time_a > time_b); } + else if (has_time_a || has_time_b) + { + // If we have only one time updated, we consider the element with time as the "highest". + // That boils down to "has_time_a" if you think about it. + return has_time_a; + } + // If not time available, we'll default to sort by name at the end of this method } else if (sort_order == LLConversationFilter::SO_DISTANCE) { F32 dist_a = 0.0; F32 dist_b = 0.0; - if (a->getDistanceToAgent(dist_a) && b->getDistanceToAgent(dist_b)) + bool has_dist_a = a->getDistanceToAgent(dist_a); + bool has_dist_b = b->getDistanceToAgent(dist_b); + if (has_dist_a && has_dist_b) { return (dist_a > dist_b); } + else if (has_dist_a || has_dist_b) + { + return has_dist_a; + } } } else if ((type_a > LLConversationItem::CONV_PARTICIPANT) && (type_b > LLConversationItem::CONV_PARTICIPANT)) @@ -288,10 +306,19 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL { F64 time_a = 0.0; F64 time_b = 0.0; - if (a->getTime(time_a) && b->getTime(time_b)) + bool has_time_a = a->getTime(time_a); + bool has_time_b = b->getTime(time_b); + if (has_time_a && has_time_b) { return (time_a > time_b); } + else if (has_time_a || has_time_b) + { + // If we have only one time updated, we consider the element with time as the "highest". + // That boils down to "has_time_a" if you think about it. + return has_time_a; + } + // If not time available, we'll default to sort by name at the end of this method } else if (sort_order == LLConversationFilter::SO_SESSION_TYPE) { diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index e2c88785a2..e67aeb9aca 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -106,7 +106,7 @@ public: // Methods used in sorting (see LLConversationSort::operator()) EConversationType const getType() const { return mConvType; } - virtual const bool getTime(F64& time) const { return false; } + virtual const bool getTime(F64& time) const { time = mLastActiveTime; return (time > 0.1); } virtual const bool getDistanceToAgent(F32& distance) const { return false; } // This method will be called to determine if a drop can be @@ -129,6 +129,7 @@ protected: LLUUID mUUID; // UUID of the session or the participant EConversationType mConvType; // Type of conversation item bool mNeedsRefresh; // Flag signaling to the view that something changed for this item + F64 mLastActiveTime; }; class LLConversationItemSession : public LLConversationItem @@ -149,7 +150,7 @@ public: void setParticipantIsMuted(const LLUUID& participant_id, bool is_muted); void setParticipantIsModerator(const LLUUID& participant_id, bool is_moderator); - void setParticipantTimeNow(const LLUUID& participant_id); + void setTimeNow(const LLUUID& participant_id); bool isLoaded() { return mIsLoaded; } @@ -172,18 +173,15 @@ public: bool isModerator() {return mIsModerator; } void setIsMuted(bool is_muted) { mIsMuted = is_muted; mNeedsRefresh = true; } void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; } - void setTimeNow() { mLastActiveTime = LLFrameTimer::getElapsedSeconds(); } + void setTimeNow() { mLastActiveTime = LLFrameTimer::getElapsedSeconds(); mNeedsRefresh = true; } void onAvatarNameCache(const LLAvatarName& av_name); - virtual const bool getTime(F64& time) const { time = mLastActiveTime; return (time > 0.1 ? true : false); } - void dumpDebugData(); private: bool mIsMuted; // default is false bool mIsModerator; // default is false - F64 mLastActiveTime; }; // We don't want to ever filter conversations but we need to declare that class to create a conversation view model. diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index a2efe63546..5425baec6d 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -250,6 +250,14 @@ std::string LLIMConversation::appendTime() void LLIMConversation::appendMessage(const LLChat& chat, const LLSD &args) { + // Update the participant activity time + LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); + if (im_box) + { + im_box->setTimeNow(mSessionID,chat.mFromID); + } + + LLChat& tmp_chat = const_cast<LLChat&>(chat); if(tmp_chat.mTimeStr.empty()) diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 8268764816..43adfdfd08 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -907,10 +907,6 @@ void LLIMFloater::updateMessages() chat.mText = message; } - // Update the participant activity time - mParticipantList->setParticipantTimeNow(from_id); - llinfos << "Merov debug : LLIMFloater::updateMessages, session = " << mSessionID << ", from = " << msg["from"].asString() << ", uuid = " << msg["from_id"].asString() << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; - // Add the message to the chat log appendMessage(chat); mLastMessageIndex = msg["index"].asInteger(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 4e0fba9502..f84da25baa 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -710,6 +710,21 @@ void LLIMFloaterContainer::setConvItemSelect(LLUUID& session_id) } } +void LLIMFloaterContainer::setTimeNow(const LLUUID& session_id, const LLUUID& participant_id) +{ + conversations_items_map::iterator item_it = mConversationsItems.find(session_id); + if (item_it != mConversationsItems.end()) + { + LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(item_it->second); + if (item) + { + item->setTimeNow(participant_id); + mConversationViewModel.requestSortAll(); + mConversationsRoot->arrangeAll(); + } + } +} + void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) { bool is_nearby_chat = uuid.isNull(); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 1f526091bb..a7a5b8a391 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -124,6 +124,7 @@ private: public: void removeConversationListItem(const LLUUID& uuid, bool change_focus = true); void addConversationListItem(const LLUUID& uuid); + void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); private: LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 0d52a9e14c..76626bd5a6 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -233,10 +233,6 @@ void LLNearbyChat::loadHistory() gCacheName->getUUID(legacy_name, from_id); } - // Update the participant activity time - mParticipantList->setParticipantTimeNow(from_id); - llinfos << "Merov debug : LLNearbyChat::loadHistory, session = " << mSessionID << ", from = " << msg[IM_FROM].asString() << ", uuid = " << msg[IM_FROM_ID].asString() << ", date = " << LLFrameTimer::getElapsedSeconds() << llendl; - LLChat chat; chat.mFromName = from; chat.mFromID = from_id; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 6283c8f296..09f2716773 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -34,6 +34,7 @@ #include "llagent.h" #include "llimview.h" +#include "llimfloatercontainer.h" #include "llpanelpeoplemenus.h" #include "llnotificationsutil.h" #include "llparticipantlist.h" @@ -592,7 +593,11 @@ bool LLParticipantList::onSpeakerUpdateEvent(LLPointer<LLOldEvents::LLEvent> eve if ( evt_data.has("id") ) { LLUUID participant_id = evt_data["id"]; - setParticipantTimeNow(participant_id); + LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); + if (im_box) + { + im_box->setTimeNow(mUUID,participant_id); + } } return true; } -- cgit v1.2.3 From 552f288a0caea45e30a231478a19f4243d69689c Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 21 Sep 2012 20:13:50 -0700 Subject: CHUI-340 : Implement distance computation and update --- indra/newview/llconversationmodel.cpp | 24 +++++++++++++++----- indra/newview/llconversationmodel.h | 7 +++++- indra/newview/llimfloatercontainer.cpp | 40 ++++++++++++++++++++++++++++++++++ indra/newview/llimfloatercontainer.h | 1 + 4 files changed, 66 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index e090d1647f..b0d691fa13 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -181,6 +181,16 @@ void LLConversationItemSession::setTimeNow(const LLUUID& participant_id) } } +void LLConversationItemSession::setDistance(const LLUUID& participant_id, F64 dist) +{ + LLConversationItemParticipant* participant = findParticipant(participant_id); + if (participant) + { + participant->setDistance(dist); + mNeedsRefresh = true; + } +} + // The time of activity of a session is the time of the most recent activity, session and participants included const bool LLConversationItemSession::getTime(F64& time) const { @@ -224,13 +234,17 @@ void LLConversationItemSession::dumpDebugData() LLConversationItemParticipant::LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLConversationItem(display_name,uuid,root_view_model), mIsMuted(false), - mIsModerator(false) + mIsModerator(false), + mDistToAgent(-1.0) { mConvType = CONV_PARTICIPANT; } LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : - LLConversationItem(uuid,root_view_model) + LLConversationItem(uuid,root_view_model), + mIsMuted(false), + mIsModerator(false), + mDistToAgent(-1.0) { mConvType = CONV_PARTICIPANT; } @@ -284,13 +298,13 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL } else if (sort_order == LLConversationFilter::SO_DISTANCE) { - F32 dist_a = 0.0; - F32 dist_b = 0.0; + F64 dist_a = 0.0; + F64 dist_b = 0.0; bool has_dist_a = a->getDistanceToAgent(dist_a); bool has_dist_b = b->getDistanceToAgent(dist_b); if (has_dist_a && has_dist_b) { - return (dist_a > dist_b); + return (dist_a < dist_b); } else if (has_dist_a || has_dist_b) { diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index e67aeb9aca..18c5dd1ce1 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -107,7 +107,7 @@ public: // Methods used in sorting (see LLConversationSort::operator()) EConversationType const getType() const { return mConvType; } virtual const bool getTime(F64& time) const { time = mLastActiveTime; return (time > 0.1); } - virtual const bool getDistanceToAgent(F32& distance) const { return false; } + virtual const bool getDistanceToAgent(F64& distance) const { return false; } // This method will be called to determine if a drop can be // performed, and will set drop to TRUE if a drop is @@ -151,6 +151,7 @@ public: void setParticipantIsMuted(const LLUUID& participant_id, bool is_muted); void setParticipantIsModerator(const LLUUID& participant_id, bool is_moderator); void setTimeNow(const LLUUID& participant_id); + void setDistance(const LLUUID& participant_id, F64 dist); bool isLoaded() { return mIsLoaded; } @@ -174,14 +175,18 @@ public: void setIsMuted(bool is_muted) { mIsMuted = is_muted; mNeedsRefresh = true; } void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; } void setTimeNow() { mLastActiveTime = LLFrameTimer::getElapsedSeconds(); mNeedsRefresh = true; } + void setDistance(F64 dist) { mDistToAgent = dist; mNeedsRefresh = true; } void onAvatarNameCache(const LLAvatarName& av_name); + virtual const bool getDistanceToAgent(F64& dist) const { dist = mDistToAgent; return (dist >= 0.0); } + void dumpDebugData(); private: bool mIsMuted; // default is false bool mIsModerator; // default is false + F64 mDistToAgent; // Distance to the agent. A negative (meaningless) value means the distance has not been set. }; // We don't want to ever filter conversations but we need to declare that class to create a conversation view model. diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 3c21794d28..cd56ea6081 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -47,6 +47,7 @@ #include "llviewercontrol.h" #include "llconversationview.h" #include "llcallbacklist.h" +#include "llworld.h" // // LLIMFloaterContainer @@ -333,6 +334,14 @@ void LLIMFloaterContainer::setMinimized(BOOL b) void LLIMFloaterContainer::idle(void* user_data) { LLIMFloaterContainer* self = static_cast<LLIMFloaterContainer*>(user_data); + + // Update the distance to agent in the nearby chat session if required + // Note: it makes no sense of course to update the distance in other session + if (self->mConversationViewModel.getSorter().getSortOrderParticipants() == LLConversationFilter::SO_DISTANCE) + { + self->setNearbyDistances(); + } + self->mConversationsRoot->update(); } @@ -725,6 +734,37 @@ void LLIMFloaterContainer::setTimeNow(const LLUUID& session_id, const LLUUID& pa } } +void LLIMFloaterContainer::setNearbyDistances() +{ + // Get the nearby chat session: that's the one with uuid nul in mConversationsItems + conversations_items_map::iterator item_it = mConversationsItems.find(LLUUID()); + if (item_it != mConversationsItems.end()) + { + LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(item_it->second); + if (item) + { + // Get the positions of the nearby avatars and their ids + std::vector<LLVector3d> positions; + uuid_vec_t avatar_ids; + LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); + // Get the position of the agent + const LLVector3d& me_pos = gAgent.getPositionGlobal(); + // For each nearby avatar, compute and update the distance + int avatar_count = positions.size(); + for (int i = 0; i < avatar_count; i++) + { + F64 dist = dist_vec_squared(positions[i], me_pos); + item->setDistance(avatar_ids[i],dist); + } + // Also does it for the agent itself + item->setDistance(gAgent.getID(),0.0f); + // Request resort + mConversationViewModel.requestSortAll(); + mConversationsRoot->arrangeAll(); + } + } +} + void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) { bool is_nearby_chat = uuid.isNull(); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 4546029e93..e8d185297c 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -125,6 +125,7 @@ public: void removeConversationListItem(const LLUUID& uuid, bool change_focus = true); void addConversationListItem(const LLUUID& uuid); void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); + void setNearbyDistances(); private: LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); -- cgit v1.2.3 From 05bae4d6d78de8165eca397493ce9d0156e3ad12 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Mon, 24 Sep 2012 13:27:50 +0300 Subject: CHUI-124 FIXED Tooltips for buttons are added --- .../skins/default/xui/en/panel_block_list_sidetray.xml | 4 ++++ indra/newview/skins/default/xui/en/panel_people.xml | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml index 24f7d44cce..53d0252215 100644 --- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -43,6 +43,7 @@ menu_filename="menu_people_blocked_gear.xml" menu_position="bottomleft" name="blocked_gear_btn" + tool_tip="Actions on selected person or object" top="3" width="31" /> <menu_button @@ -57,6 +58,7 @@ menu_filename="menu_people_blocked_view.xml" menu_position="bottomleft" name="view_btn" + tool_tip="Sort options" top_delta="0" width="31" /> <menu_button @@ -71,6 +73,7 @@ menu_filename="menu_people_blocked_plus.xml" menu_position="bottomleft" name="plus_btn" + tool_tip="Pick a Resident or an object to block" top_delta="0" width="31"/> <button @@ -83,6 +86,7 @@ left_pad="2" layout="topleft" name="unblock_btn" + tool_tip="Remove Resident or object from blocked list" top_delta="0" width="31"/> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 09156b41b5..7433ad828d 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -116,6 +116,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left_pad="7" name="gear_btn" + tool_tip="Actions on selected person" top="3" width="31" /> <menu_button @@ -130,6 +131,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M menu_filename="menu_people_nearby_view.xml" menu_position="bottomleft" name="nearby_view_btn" + tool_tip="View/sort options" top_delta="0" width="31" /> <button @@ -142,6 +144,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left_pad="2" name="add_friend_btn" + tool_tip="Offer friendship to a resident" top_delta="0" width="31"> <commit_callback @@ -158,6 +161,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left_pad="2" layout="topleft" name="nearby_del_btn" + tool_tip="Remove selected person as a friend" top_delta="0" width="31"> <commit_callback @@ -264,6 +268,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left_pad="8" name="gear_btn" + tool_tip="Actions on selected person" top="3" width="31" /> <menu_button @@ -278,6 +283,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M menu_filename="menu_people_friends_view.xml" menu_position="bottomleft" name="friends_view_btn" + tool_tip="View/sort options" top_delta="0" width="31" /> <button @@ -290,6 +296,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left_pad="2" name="friends_add_btn" + tool_tip="Offer friendship to a resident" top_delta="0" width="31"> <commit_callback @@ -305,6 +312,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left_pad="2" layout="topleft" name="friends_del_btn" + tool_tip="Remove selected person as a friend" top_delta="0" width="31"> <commit_callback @@ -419,6 +427,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left_pad="8" name="groups_gear_btn" + tool_tip="Actions on selected group" top="3" width="31" /> <menu_button @@ -433,6 +442,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M menu_filename="menu_people_groups_view.xml" menu_position="bottomleft" name="groups_view_btn" + tool_tip="View/sort options" top_delta="0" width="31" /> <menu_button @@ -447,6 +457,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M menu_filename="menu_group_plus.xml" menu_position="bottomleft" name="plus_btn" + tool_tip="Join group/Create new group" top_delta="0" width="31"> <validate_callback @@ -462,6 +473,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left_pad="2" layout="topleft" name="minus_btn" + tool_tip="Leave selected group" top_delta="0" width="31"> <commit_callback @@ -527,6 +539,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left_pad="8" name="gear_btn" + tool_tip="Actions on selected person" top="3" width="31" /> <menu_button @@ -541,6 +554,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M menu_filename="menu_people_recent_view.xml" menu_position="bottomleft" name="recent_view_btn" + tool_tip="View/sort options" top_delta="0" width="31" /> <button @@ -553,6 +567,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M layout="topleft" left_pad="2" name="add_friend_btn" + tool_tip="Offer friendship to a resident" top_delta="0" width="31"> <commit_callback @@ -569,6 +584,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M left_pad="2" layout="topleft" name="recent_del_btn" + tool_tip="Remove selected person as a friend" top_delta="0" width="31"> <commit_callback -- cgit v1.2.3 From e0b252fc99968eb54031a8a2bb8216baae5078b2 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Mon, 24 Sep 2012 14:52:20 +0300 Subject: CHUI-123 FIXED Tooltips for buttons are added --- indra/newview/llimconversation.cpp | 1 + indra/newview/skins/default/xui/en/floater_im_container.xml | 4 +++- indra/newview/skins/default/xui/en/floater_im_session.xml | 11 +++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 64f171ce8f..3ca93b1b07 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -424,6 +424,7 @@ void LLIMConversation::updateHeaderAndToolbar() mExpandCollapseBtn->setEnabled(!is_torn_off || !mIsP2PChat); mTearOffBtn->setImageOverlay(getString(is_torn_off? "return_icon" : "tear_off_icon")); + mTearOffBtn->setToolTip(getString(!is_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window")); mCloseBtn->setVisible(!is_torn_off && !mIsNearbyChat); diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 413e66738d..d23ff28fd0 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -62,6 +62,7 @@ layout="topleft" left="10" name="sort_btn" + tool_tip="View/sort options" top="5" width="31" /> <button @@ -75,7 +76,7 @@ top="5" left_pad="4" name="add_btn" - tool_tip="Add button on the left panel" + tool_tip="Start a new conversation" width="31"/> </layout_panel> <layout_panel @@ -94,6 +95,7 @@ top="5" left="5" name="expand_collapse_btn" + tool_tip="Collapse/Expand this list" width="31" /> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index d6d48130ab..5c74f7f9bb 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -37,6 +37,12 @@ <floater.string name="multiple_participants_added" value="[NAME] were invited to the conversation."/> + <floater.string + name="tooltip_to_separate_window" + value="Move this conversation to a separate window"/> + <floater.string + name="tooltip_to_main_window" + value="Move this conversation back to main window"/> <view follows="all" layout="topleft" @@ -64,6 +70,7 @@ layout="topleft" left="5" name="view_options_btn" + tool_tip="View/sort options" top="5" width="31" /> <button @@ -78,6 +85,7 @@ top="5" left_pad="4" name="add_btn" + tool_tip="Add someone to this conversation" width="31"/> <button follows="top|left" @@ -90,6 +98,7 @@ top="5" left_pad="4" name="voice_call_btn" + tool_tip="Open voice connection" width="31"/> <button follows="right|top" @@ -102,6 +111,7 @@ top="5" left="283" name="close_btn" + tool_tip="End this conversation" width="31" /> <button follows="right|top" @@ -114,6 +124,7 @@ top="5" left_pad="5" name="expand_collapse_btn" + tool_tip="Collapse/Expand this pane" width="31" /> <button follows="right|top" -- cgit v1.2.3 From a3b36bad821907f9b30891c45e7901b92366be52 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Mon, 24 Sep 2012 15:33:59 +0300 Subject: CHUI-309 FIXED Use onRemoveNotification only for "LoadWebPage", "ScriptDialog" and "ScriptDialogGroup" notifications --- indra/newview/llnotificationscripthandler.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 5dcd84b400..290a81f91c 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -109,7 +109,7 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) void LLScriptHandler::onDelete( LLNotificationPtr notification ) { - if(notification->hasFormElements()) + if(notification->hasFormElements() && !notification->canShowToast()) { LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); } @@ -128,10 +128,11 @@ void LLScriptHandler::onDeleteToast(LLToast* toast) // in this case listener is a SysWellWindow and it will remove a corresponding item from its list LLNotificationPtr notification = LLNotifications::getInstance()->find(toast->getNotificationID()); - if( notification && notification->hasFormElements()) + if( notification && notification->hasFormElements() && !notification->canShowToast()) { LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); } + } -- cgit v1.2.3 From f9e0831ba04f99335bfb494a22435446dc0852de Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 24 Sep 2012 18:57:04 +0300 Subject: CHUI-355 FIXED Nearby chat entries do not appear in torn off nearby chat window when opening from a toast: moved setIsSingleInstance() from constructor to postBuild() for prevent of a resetting it in buildFromXML(); implemented correct set of mReuseInstance; changed type of the key of LLIMConversation from LLUUID() to LLSD() --- indra/llui/llfloater.cpp | 5 +++++ indra/llui/llfloater.h | 7 ++++--- indra/newview/llimconversation.cpp | 4 ++-- indra/newview/llimconversation.h | 2 +- indra/newview/llnearbychat.cpp | 7 +++---- indra/newview/llnearbychat.h | 4 ++-- 6 files changed, 17 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 029c47c726..58b17f74a8 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -240,6 +240,7 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) mTitle(p.title), mShortTitle(p.short_title), mSingleInstance(p.single_instance), + mIsReuseInitialized(p.reuse_instance.isProvided()), mReuseInstance(p.reuse_instance.isProvided() ? p.reuse_instance : p.single_instance), // reuse single-instance floaters by default mKey(key), mCanTearOff(p.can_tear_off), @@ -631,6 +632,10 @@ void LLFloater::setVisible( BOOL visible ) void LLFloater::setIsSingleInstance(BOOL is_single_instance) { mSingleInstance = is_single_instance; + if (!mIsReuseInitialized) + { + mReuseInstance = is_single_instance; // reuse single-instance floaters by default + } } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 4b738f88ea..07b79d5523 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -447,9 +447,10 @@ private: LLUIString mTitle; LLUIString mShortTitle; - BOOL mSingleInstance; // TRUE if there is only ever one instance of the floater - bool mReuseInstance; // true if we want to hide the floater when we close it instead of destroying it - std::string mInstanceName; // Store the instance name so we can remove ourselves from the list + BOOL mSingleInstance; // TRUE if there is only ever one instance of the floater + bool mReuseInstance; // true if we want to hide the floater when we close it instead of destroying it + bool mIsReuseInitialized; // true if mReuseInstance already set from parameters + std::string mInstanceName; // Store the instance name so we can remove ourselves from the list BOOL mCanTearOff; BOOL mCanMinimize; diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 3ca93b1b07..2ad7f9b193 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -42,13 +42,13 @@ const F32 REFRESH_INTERVAL = 0.2f; -LLIMConversation::LLIMConversation(const LLUUID& session_id) +LLIMConversation::LLIMConversation(const LLSD& session_id) : LLTransientDockableFloater(NULL, true, session_id) , mIsP2PChat(false) , mExpandCollapseBtn(NULL) , mTearOffBtn(NULL) , mCloseBtn(NULL) - , mSessionID(session_id) + , mSessionID(session_id.asUUID()) , mParticipantList(NULL) , mChatHistory(NULL) , mInputEditor(NULL) diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index bad5eaa99f..c54081d316 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -47,7 +47,7 @@ class LLIMConversation public: LOG_CLASS(LLIMConversation); - LLIMConversation(const LLUUID& session_id); + LLIMConversation(const LLSD& session_id); ~LLIMConversation(); // reload all message with new settings of visual modes diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 76626bd5a6..71c4938ae9 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -88,7 +88,7 @@ static LLChatTypeTrigger sChatTypeTriggers[] = { LLNearbyChat::LLNearbyChat(const LLSD& llsd) -: LLIMConversation(llsd.asUUID()), +: LLIMConversation(llsd), //mOutputMonitor(NULL), mSpeakerMgr(NULL), mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) @@ -96,16 +96,15 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd) mIsP2PChat = false; mIsNearbyChat = true; setIsChrome(TRUE); - mKey = LLSD(LLUUID()); mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); mSessionID = LLUUID(); - setName("nearby_chat"); - setIsSingleInstance(TRUE); } + //virtual BOOL LLNearbyChat::postBuild() { + setIsSingleInstance(TRUE); BOOL result = LLIMConversation::postBuild(); mInputEditor->setCommitCallback(boost::bind(&LLNearbyChat::onChatBoxCommit, this)); mInputEditor->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this)); diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 648098113a..da1b58e326 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -45,8 +45,8 @@ class LLNearbyChat { public: // constructor for inline chat-bars (e.g. hosted in chat history window) - LLNearbyChat(const LLSD& key = LLSD()); - ~LLNearbyChat() {} + LLNearbyChat(const LLSD& key = LLSD(LLUUID())); + ~LLNearbyChat() {}; /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); -- cgit v1.2.3 From b28cb6843cdfedbd059ae3961cb528339127fbfd Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 24 Sep 2012 20:59:34 +0300 Subject: CHUI-355 FIXED Nearby chat entries do not appear in torn off nearby chat window when opening from a toast: fix for visual studio and XCode --- indra/newview/llnearbychat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index da1b58e326..3987212e4c 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -46,7 +46,7 @@ class LLNearbyChat public: // constructor for inline chat-bars (e.g. hosted in chat history window) LLNearbyChat(const LLSD& key = LLSD(LLUUID())); - ~LLNearbyChat() {}; + ~LLNearbyChat() {} /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); -- cgit v1.2.3 From 5b0e06108b3c4373c55103dedab3306f06d392c9 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 24 Sep 2012 19:55:31 -0700 Subject: CHUI-340 : Fix dupe items in the conversation model list. Refresh when resorting. --- indra/llui/llfolderviewmodel.h | 10 ++++++++++ indra/newview/llconversationmodel.cpp | 4 ++-- indra/newview/llimfloatercontainer.cpp | 2 ++ indra/newview/llparticipantlist.cpp | 2 ++ 4 files changed, 16 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index c99fa07c8b..c6030c9b71 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -254,6 +254,16 @@ public: virtual void addChild(LLFolderViewModelItem* child) { + // Avoid duplicates: bail out if that child is already present in the list + // Note: this happens when models are created before views + child_list_t::const_iterator iter; + for (iter = mChildren.begin(); iter != mChildren.end(); iter++) + { + if (child == *iter) + { + return; + } + } mChildren.push_back(child); child->setParent(this); dirtyFilter(); diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index b0d691fa13..a94d82bf7c 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -217,7 +217,7 @@ const bool LLConversationItemSession::getTime(F64& time) const void LLConversationItemSession::dumpDebugData() { - llinfos << "Merov debug : session, uuid = " << mUUID << ", name = " << mName << ", is loaded = " << mIsLoaded << llendl; + llinfos << "Merov debug : session " << this << ", uuid = " << mUUID << ", name = " << mName << ", is loaded = " << mIsLoaded << llendl; LLConversationItemParticipant* participant = NULL; child_list_t::iterator iter; for (iter = mChildren.begin(); iter != mChildren.end(); iter++) @@ -262,7 +262,7 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam void LLConversationItemParticipant::dumpDebugData() { - llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; + llinfos << "Merov debug : participant " << this << ", uuid = " << mUUID << ", name = " << mName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; } // diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index cd56ea6081..14d40d4685 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -394,6 +394,8 @@ void LLIMFloaterContainer::draw() } // Reset the need for refresh session_model->resetRefresh(); + mConversationViewModel.requestSortAll(); + mConversationsRoot->arrangeAll(); // Next participant current_participant_model++; } diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 09f2716773..90226e7fba 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -678,8 +678,10 @@ void LLParticipantList::sort() void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) { + // Do not add if already in there or excluded for some reason if (mExcludeAgent && gAgent.getID() == avatar_id) return; if (mAvatarList && mAvatarList->contains(avatar_id)) return; + if (findParticipant(avatar_id)) return; bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(avatar_id); -- cgit v1.2.3 From 7ac4d71c43ec746f7bb30e5cedcfdd2c4c7940f7 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 25 Sep 2012 16:39:11 -0700 Subject: CHUI-329 : WIP : Always sort Nearby Chat to be on top of the list --- indra/newview/llconversationmodel.cpp | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index a94d82bf7c..00cd8ba8f8 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -269,6 +269,7 @@ void LLConversationItemParticipant::dumpDebugData() // LLConversationSort // +// Comparison operator: returns "true" is a comes before b, "false" otherwise bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const { LLConversationItem::EConversationType type_a = a->getType(); @@ -276,7 +277,7 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL if ((type_a == LLConversationItem::CONV_PARTICIPANT) && (type_b == LLConversationItem::CONV_PARTICIPANT)) { - // If both are participants + // If both items are participants U32 sort_order = getSortOrderParticipants(); if (sort_order == LLConversationFilter::SO_DATE) { @@ -286,15 +287,15 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL bool has_time_b = b->getTime(time_b); if (has_time_a && has_time_b) { + // Most recent comes first return (time_a > time_b); } else if (has_time_a || has_time_b) { - // If we have only one time updated, we consider the element with time as the "highest". - // That boils down to "has_time_a" if you think about it. + // If we have only one time available, the element with time must come first return has_time_a; } - // If not time available, we'll default to sort by name at the end of this method + // If no time available, we'll default to sort by name at the end of this method } else if (sort_order == LLConversationFilter::SO_DISTANCE) { @@ -304,52 +305,63 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL bool has_dist_b = b->getDistanceToAgent(dist_b); if (has_dist_a && has_dist_b) { + // Closest comes first return (dist_a < dist_b); } else if (has_dist_a || has_dist_b) { + // If we have only one distance available, the element with it must come first return has_dist_a; } + // If no distance available, we'll default to sort by name at the end of this method } } else if ((type_a > LLConversationItem::CONV_PARTICIPANT) && (type_b > LLConversationItem::CONV_PARTICIPANT)) { // If both are sessions U32 sort_order = getSortOrderSessions(); - if (sort_order == LLConversationFilter::SO_DATE) + if ((type_a == LLConversationItem::CONV_SESSION_NEARBY) || (type_b == LLConversationItem::CONV_SESSION_NEARBY)) + { + // If one is the nearby session, put nearby session *always* first + return (type_a == LLConversationItem::CONV_SESSION_NEARBY); + } + else if (sort_order == LLConversationFilter::SO_DATE) { + // Sort by time F64 time_a = 0.0; F64 time_b = 0.0; bool has_time_a = a->getTime(time_a); bool has_time_b = b->getTime(time_b); if (has_time_a && has_time_b) { + // Most recent comes first return (time_a > time_b); } else if (has_time_a || has_time_b) { - // If we have only one time updated, we consider the element with time as the "highest". - // That boils down to "has_time_a" if you think about it. + // If we have only one time available, the element with time must come first return has_time_a; } - // If not time available, we'll default to sort by name at the end of this method + // If no time available, we'll default to sort by name at the end of this method } else if (sort_order == LLConversationFilter::SO_SESSION_TYPE) { if (type_a != type_b) { + // Lowest types come first. See LLConversationItem definition of types return (type_a < type_b); } + // If types are identical, we'll default to sort by name at the end of this method } } else { - // If one is a participant and the other a session, the session is always "less" than the participant + // If one item is a participant and the other a session, the session comes before the participant // so we simply compare the type // Notes: as a consequence, CONV_UNKNOWN (which should never get created...) always come first - return (type_a < type_b); + return (type_a > type_b); } - // By default, in all other possible cases (including sort order of type LLConversationFilter::SO_NAME of course), + // By default, in all other possible cases (including sort order type LLConversationFilter::SO_NAME of course), // we sort by name S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); return (compare < 0); -- cgit v1.2.3 From 3502e783b7425ba30d92f66697bafa89ae891e60 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 25 Sep 2012 22:02:44 -0700 Subject: CHUI-342 : Fixed : Use user name and display name correctly. Sort according to user names. --- indra/llui/llfolderviewitem.cpp | 2 +- indra/newview/llconversationmodel.cpp | 8 ++++---- indra/newview/llconversationmodel.h | 3 +++ 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 9632612752..5589c5b166 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -230,7 +230,7 @@ void LLFolderViewItem::refresh() mLabel = vmi.getDisplayName(); - setToolTip(mLabel); + setToolTip(vmi.getName()); mIcon = vmi.getIcon(); mIconOpen = vmi.getIconOpen(); mIconOverlay = vmi.getIconOverlay(); diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 00cd8ba8f8..7d0ffa0788 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -251,8 +251,8 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) { - mName = av_name.mDisplayName; - // *TODO : we should also store that one, to be used in the tooltip : av_name.mUsername + mName = av_name.mUsername; + mDisplayName = av_name.mDisplayName; mNeedsRefresh = true; if (mParent) { @@ -262,7 +262,7 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam void LLConversationItemParticipant::dumpDebugData() { - llinfos << "Merov debug : participant " << this << ", uuid = " << mUUID << ", name = " << mName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; + llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", display name = " << mDisplayName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; } // @@ -363,7 +363,7 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL } // By default, in all other possible cases (including sort order type LLConversationFilter::SO_NAME of course), // we sort by name - S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); + S32 compare = LLStringUtil::compareDict(a->getName(), b->getName()); return (compare < 0); } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 18c5dd1ce1..30f94d51ae 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -170,6 +170,8 @@ public: LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItemParticipant() {} + virtual const std::string& getDisplayName() const { return mDisplayName; } + bool isMuted() { return mIsMuted; } bool isModerator() {return mIsModerator; } void setIsMuted(bool is_muted) { mIsMuted = is_muted; mNeedsRefresh = true; } @@ -186,6 +188,7 @@ public: private: bool mIsMuted; // default is false bool mIsModerator; // default is false + std::string mDisplayName; F64 mDistToAgent; // Distance to the agent. A negative (meaningless) value means the distance has not been set. }; -- cgit v1.2.3 From a62a4b60e8a954509a722b96c984b0a798653516 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Wed, 26 Sep 2012 17:43:47 +0300 Subject: CHUI-347 FIXED drawing selected conversation item background. Moved some duplicating pieces of code from LLFolderViewFolder::draw() and LLFolderViewItem::draw() to separate methods to reduce code duplication in LLConversationViewSession::draw(). Changed some static variables in LLFolderViewItem to static members for using them in derived LLConversationViewSession. --- indra/llui/llfolderviewitem.cpp | 95 +++++++++++++++---------- indra/llui/llfolderviewitem.h | 16 +++++ indra/newview/llconversationview.cpp | 131 ++--------------------------------- 3 files changed, 82 insertions(+), 160 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 9632612752..a9da885717 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -44,6 +44,18 @@ static LLDefaultChildRegistry::Register<LLFolderViewItem> r("folder_view_item"); // statics std::map<U8, LLFontGL*> LLFolderViewItem::sFonts; // map of styles to fonts +LLUIColor LLFolderViewItem::sFgColor; +LLUIColor LLFolderViewItem::sHighlightBgColor; +LLUIColor LLFolderViewItem::sHighlightFgColor; +LLUIColor LLFolderViewItem::sFocusOutlineColor; +LLUIColor LLFolderViewItem::sMouseOverColor; +LLUIColor LLFolderViewItem::sFilterBGColor; +LLUIColor LLFolderViewItem::sFilterTextColor; +LLUIColor LLFolderViewItem::sSuffixColor; +LLUIColor LLFolderViewItem::sLibraryColor; +LLUIColor LLFolderViewItem::sLinkColor; +LLUIColor LLFolderViewItem::sSearchStatusColor; + // only integers can be initialized in header const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f; const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f; @@ -130,10 +142,22 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mArrowSize(p.arrow_size), mMaxFolderItemOverlap(p.max_folder_item_overlap) { + sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); + sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); + sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); + sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); + sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); + sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); + sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); + if (mViewModelItem) { mViewModelItem->setFolderViewItem(this); -} + } } BOOL LLFolderViewItem::postBuild() @@ -624,6 +648,22 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, return handled; } +void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color) +{ + //--------------------------------------------------------------------------------// + // Draw open folder arrow + // + const S32 TOP_PAD = default_params.item_top_pad; + + if (hasVisibleChildren() || getViewModelItem()->hasChildren()) + { + LLUIImage* arrow_image = default_params.folder_arrow_image; + gl_draw_scaled_rotated_image( + mIndentation, getRect().getHeight() - mArrowSize - mTextPad - TOP_PAD, + mArrowSize, mArrowSize, mControlLabelRotation, arrow_image->getImage(), fg_color); + } +} + void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor, const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor) { @@ -734,18 +774,6 @@ void LLFolderViewItem::drawLabel(const LLFontGL * font, const F32 x, const F32 y void LLFolderViewItem::draw() { - static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); - static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); - static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); - static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); - static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); - static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); - static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); - static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); - static LLUIColor sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); - static LLUIColor sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); - static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); - const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled @@ -756,17 +784,7 @@ void LLFolderViewItem::draw() getViewModelItem()->update(); - //--------------------------------------------------------------------------------// - // Draw open folder arrow - // - if (hasVisibleChildren() || getViewModelItem()->hasChildren()) - { - LLUIImage* arrow_image = default_params.folder_arrow_image; - gl_draw_scaled_rotated_image( - mIndentation, getRect().getHeight() - mArrowSize - mTextPad - TOP_PAD, - mArrowSize, mArrowSize, mControlLabelRotation, arrow_image->getImage(), sFgColor); - } - + drawOpenFolderArrow(default_params, sFgColor); drawHighlight(show_context, filled, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); @@ -877,6 +895,22 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): { } +void LLFolderViewFolder::updateLabelRotation() +{ + if (mAutoOpenCountdown != 0.f) + { + mControlLabelRotation = mAutoOpenCountdown * -90.f; + } + else if (isOpen()) + { + mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); + } + else + { + mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); + } +} + // Destroys the object LLFolderViewFolder::~LLFolderViewFolder( void ) { @@ -1832,18 +1866,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) void LLFolderViewFolder::draw() { - if (mAutoOpenCountdown != 0.f) - { - mControlLabelRotation = mAutoOpenCountdown * -90.f; - } - else if (isOpen()) - { - mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); - } - else - { - mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); - } + updateLabelRotation(); LLFolderViewItem::draw(); diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index b7e0091aca..d4002c3184 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -116,6 +116,19 @@ protected: mAllowOpen, mSelectPending; + // For now assuming all colors are the same in derived classes. + static LLUIColor sFgColor; + static LLUIColor sHighlightBgColor; + static LLUIColor sHighlightFgColor; + static LLUIColor sFocusOutlineColor; + static LLUIColor sMouseOverColor; + static LLUIColor sFilterBGColor; + static LLUIColor sFilterTextColor; + static LLUIColor sSuffixColor; + static LLUIColor sLibraryColor; + static LLUIColor sLinkColor; + static LLUIColor sSearchStatusColor; + // this is an internal method used for adding items to folders. A // no-op at this level, but reimplemented in derived classes. virtual void addItem(LLFolderViewItem*) { } @@ -247,6 +260,7 @@ public: // virtual void handleDropped(); virtual void draw(); + void drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color); void drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor); void drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, @@ -274,6 +288,8 @@ protected: LLFolderViewFolder( const LLFolderViewItem::Params& ); friend class LLUICtrlFactory; + void updateLabelRotation(); + public: typedef std::list<LLFolderViewItem*> items_t; typedef std::list<LLFolderViewFolder*> folders_t; diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 394a830e5e..a4733bb693 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -72,136 +72,19 @@ BOOL LLConversationViewSession::postBuild() void LLConversationViewSession::draw() { -// *TODO Seth PE: remove the code duplicated from LLFolderViewFolder::draw() -// ***** LLFolderViewFolder::draw() code begin ***** - if (mAutoOpenCountdown != 0.f) - { - mControlLabelRotation = mAutoOpenCountdown * -90.f; - } - else if (isOpen()) - { - mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); - } - else - { - mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); - } -// ***** LLFolderViewFolder::draw() code end ***** - -// *TODO Seth PE: remove the code duplicated from LLFolderViewItem::draw() -// ***** LLFolderViewItem::draw() code begin ***** - - static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); - static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); - static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); - static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + getViewModelItem()->update(); const LLFolderViewItem::Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); - const S32 TOP_PAD = default_params.item_top_pad; - const S32 FOCUS_LEFT = 1; + const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); - getViewModelItem()->update(); + // update the rotation angle of open folder arrow + updateLabelRotation(); - //--------------------------------------------------------------------------------// - // Draw open folder arrow - // - if (hasVisibleChildren() || getViewModelItem()->hasChildren()) - { - LLUIImage* arrow_image = default_params.folder_arrow_image; - gl_draw_scaled_rotated_image( - mIndentation, getRect().getHeight() - mArrowSize - mTextPad - TOP_PAD, - mArrowSize, mArrowSize, mControlLabelRotation, arrow_image->getImage(), sFgColor); - } + drawOpenFolderArrow(default_params, sFgColor); + // draw highlight for selected items + drawHighlight(show_context, true, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); - //--------------------------------------------------------------------------------// - // Draw highlight for selected items - // - const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); - const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled - const S32 focus_top = getRect().getHeight(); - const S32 focus_bottom = getRect().getHeight() - mItemHeight; - const bool folder_open = (getRect().getHeight() > mItemHeight + 4); - if (mIsSelected) // always render "current" item. Only render other selected items if mShowSingleSelection is FALSE - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLColor4 bg_color = sHighlightBgColor; - if (!mIsCurSelection) - { - // do time-based fade of extra objects - F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); - if (getRoot() && getRoot()->getShowSingleSelection()) - { - // fading out - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); - } - else - { - // fading in - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); - } - } - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - bg_color, filled); - if (mIsCurSelection) - { - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sFocusOutlineColor, FALSE); - } - if (folder_open) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, // overlap with bottom edge of above rect - getRect().getWidth() - 2, - 0, - sFocusOutlineColor, FALSE); - if (show_context) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, - getRect().getWidth() - 2, - 0, - sHighlightBgColor, TRUE); - } - } - } - else if (mIsMouseOverTitle) - { - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sMouseOverColor, FALSE); - } - - //--------------------------------------------------------------------------------// - // Draw DragNDrop highlight - // - if (mDragAndDropTarget) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sHighlightBgColor, FALSE); - if (folder_open) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, // overlap with bottom edge of above rect - getRect().getWidth() - 2, - 0, - sHighlightBgColor, FALSE); - } - mDragAndDropTarget = FALSE; - } -// ***** LLFolderViewItem::draw() code end ***** // draw children if root folder, or any other folder that is open or animating to closed state bool draw_children = getRoot() == static_cast<LLFolderViewFolder*>(this) -- cgit v1.2.3 From 976a2f5a442150ef89cff6b39450eabbca956d0f Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Wed, 26 Sep 2012 20:45:18 +0300 Subject: CHUI-344 FIXED (LLConversationViewSession: enable icon update) - This commit also fixes CHUI-345 CHUI-346 --- indra/newview/llconversationview.cpp | 84 ++++++++++++++++++++- indra/newview/llconversationview.h | 13 +++- indra/newview/llnearbychat.cpp | 1 + indra/newview/lloutputmonitorctrl.cpp | 20 ++++- indra/newview/lloutputmonitorctrl.h | 3 + .../default/textures/icons/nearby_chat_icon.png | Bin 0 -> 793 bytes indra/newview/skins/default/textures/textures.xml | 2 + .../xui/en/panel_conversation_list_item.xml | 26 ++++++- 8 files changed, 140 insertions(+), 9 deletions(-) create mode 100644 indra/newview/skins/default/textures/icons/nearby_chat_icon.png (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index a4733bb693..ab15e20d89 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -30,10 +30,12 @@ #include "llconversationview.h" #include <boost/bind.hpp> +#include "llagentdata.h" #include "llconversationmodel.h" #include "llimconversation.h" #include "llimfloatercontainer.h" #include "llfloaterreg.h" +#include "llgroupiconctrl.h" #include "lluictrlfactory.h" // @@ -51,20 +53,79 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes LLFolderViewFolder(p), mContainer(p.container), mItemPanel(NULL), - mSessionTitle(NULL) + mCallIconLayoutPanel(NULL), + mSessionTitle(NULL), + mSpeakingIndicator(NULL) { } +LLConversationViewSession::~LLConversationViewSession() +{ + mActiveVoiceChannelConnection.disconnect(); +} + BOOL LLConversationViewSession::postBuild() { LLFolderViewItem::postBuild(); mItemPanel = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>("panel_conversation_list_item.xml", NULL, LLPanel::child_registry_t::instance()); - addChild(mItemPanel); + mCallIconLayoutPanel = mItemPanel->getChild<LLPanel>("call_icon_panel"); mSessionTitle = mItemPanel->getChild<LLTextBox>("conversation_title"); + mActiveVoiceChannelConnection = LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLConversationViewSession::onCurrentVoiceSessionChanged, this, _1)); + mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicatorn"); + + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); + if (vmi) + { + switch(vmi->getType()) + { + case LLConversationItem::CONV_PARTICIPANT: + case LLConversationItem::CONV_SESSION_1_ON_1: + { + LLIMModel::LLIMSession* session= LLIMModel::instance().findIMSession(vmi->getUUID()); + if (session) + { + LLAvatarIconCtrl* icon = mItemPanel->getChild<LLAvatarIconCtrl>("avatar_icon"); + icon->setVisible(true); + icon->setValue(session->mOtherParticipantID); + mSpeakingIndicator->setSpeakerId(gAgentID, session->mSessionID); + mSpeakingIndicator->setShowParticipantsTalking(true); + } + break; + } + case LLConversationItem::CONV_SESSION_AD_HOC: + { + LLGroupIconCtrl* icon = mItemPanel->getChild<LLGroupIconCtrl>("group_icon"); + icon->setVisible(true); + mSpeakingIndicator->setSpeakerId(gAgentID, vmi->getUUID()); + mSpeakingIndicator->setShowParticipantsTalking(true); + } + case LLConversationItem::CONV_SESSION_GROUP: + { + LLGroupIconCtrl* icon = mItemPanel->getChild<LLGroupIconCtrl>("group_icon"); + icon->setVisible(true); + icon->setValue(vmi->getUUID()); + mSpeakingIndicator->setSpeakerId(gAgentID, vmi->getUUID()); + mSpeakingIndicator->setShowParticipantsTalking(true); + break; + } + case LLConversationItem::CONV_SESSION_NEARBY: + { + LLIconCtrl* icon = mItemPanel->getChild<LLIconCtrl>("nearby_chat_icon"); + icon->setVisible(true); + mSpeakingIndicator->setSpeakerId(gAgentID); + mSpeakingIndicator->setShowParticipantsTalking(true); + break; + } + + default: + break; + } + } + refresh(); return TRUE; @@ -188,6 +249,25 @@ void LLConversationViewSession::refresh() LLFolderViewFolder::refresh(); } +void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& session_id) +{ + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); + + if (vmi) + { + bool is_active = vmi->getUUID() == session_id; + bool is_nearby = vmi->getType() == LLConversationItem::CONV_SESSION_NEARBY; + + if (is_nearby) + { + mSpeakingIndicator->setSpeakerId(is_active ? gAgentID : LLUUID::null); + } + + mSpeakingIndicator->switchIndicator(is_active); + mCallIconLayoutPanel->setVisible(is_active); + } +} + // // Implementation of conversations list participant (avatar) widgets // diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 0b98c34c73..dbc7f3b1bb 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -57,7 +57,7 @@ protected: LLIMFloaterContainer* mContainer; public: - virtual ~LLConversationViewSession( void ) { } + virtual ~LLConversationViewSession(); virtual void selectItem(); /*virtual*/ BOOL postBuild(); @@ -71,8 +71,15 @@ public: virtual void refresh(); private: - LLPanel* mItemPanel; - LLTextBox* mSessionTitle; + + void onCurrentVoiceSessionChanged(const LLUUID& session_id); + + LLPanel* mItemPanel; + LLPanel* mCallIconLayoutPanel; + LLTextBox* mSessionTitle; + LLOutputMonitorCtrl* mSpeakingIndicator; + + boost::signals2::connection mActiveVoiceChannelConnection; }; // Implementation of conversations list participant (avatar) widgets diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 71c4938ae9..75c691d99b 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -110,6 +110,7 @@ BOOL LLNearbyChat::postBuild() mInputEditor->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this)); mInputEditor->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); mInputEditor->setFocusReceivedCallback(boost::bind(&LLNearbyChat::onChatBoxFocusReceived, this)); + mInputEditor->setLabel(LLTrans::getString("NearbyChatTitle")); // mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); // mOutputMonitor->setVisible(FALSE); diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 096e714981..d48826779c 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -74,7 +74,8 @@ LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p) mSpeakerId(p.speaker_id), mIsAgentControl(false), mIsSwitchDirty(false), - mShouldSwitchOn(false) + mShouldSwitchOn(false), + mShowParticipantsTalking(false) { //static LLUIColor output_monitor_muted_color = LLUIColorTable::instance().getColor("OutputMonitorMutedColor", LLColor4::orange); //static LLUIColor output_monitor_overdriven_color = LLUIColorTable::instance().getColor("OutputMonitorOverdrivenColor", LLColor4::red); @@ -157,6 +158,23 @@ void LLOutputMonitorCtrl::draw() } } + if ((mPower == 0.f && !mIsTalking) && mShowParticipantsTalking) + { + std::set<LLUUID> participant_uuids; + LLVoiceClient::instance().getParticipantList(participant_uuids); + std::set<LLUUID>::const_iterator part_it = participant_uuids.begin(); + + F32 power = 0; + for (; part_it != participant_uuids.end(); ++part_it) + { + if (power = LLVoiceClient::instance().getCurrentPower(*part_it)) + { + mPower = power; + break; + } + } + } + LLPointer<LLUIImage> icon; if (mIsMuted) { diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 7b02e84744..44d4d6f64b 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -82,6 +82,8 @@ public: void setIsTalking(bool val) { mIsTalking = val; } + void setShowParticipantsTalking(bool show) { mShowParticipantsTalking = show; } + /** * Sets avatar UUID to interact with voice channel. * @@ -132,6 +134,7 @@ private: bool mIsAgentControl; bool mIsMuted; bool mIsTalking; + bool mShowParticipantsTalking; LLPointer<LLUIImage> mImageMute; LLPointer<LLUIImage> mImageOff; LLPointer<LLUIImage> mImageOn; diff --git a/indra/newview/skins/default/textures/icons/nearby_chat_icon.png b/indra/newview/skins/default/textures/icons/nearby_chat_icon.png new file mode 100644 index 0000000000..7c3ad40381 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/nearby_chat_icon.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 47b0c12fa0..a124041565 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -363,6 +363,8 @@ with the same filename but different name <texture name="NavBar_BG_NoFav_Bevel" file_name="navbar/NavBar_BG_NoFav_Bevel.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" /> <texture name="NavBar_BG_NoNav_Bevel" file_name="navbar/NavBar_BG_NoNav_Bevel.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" /> + <texture name="Nearby_chat_icon" file_name="icons/nearby_chat_icon.png" preload="false" /> + <texture name="Notices_Unread" file_name="bottomtray/Notices_Unread.png" preload="true" /> <texture name="NoEntryLines" file_name="world/NoEntryLines.png" use_mips="true" preload="false" /> diff --git a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml index 375ea79ebe..56056ed560 100644 --- a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml @@ -13,13 +13,33 @@ layout="topleft" left="5" top="2" + visible="false" width="20" /> + <group_icon + follows="top|left" + height="20" + default_icon_name="Generic_Group" + layout="topleft" + left="5" + top="2" + visible="false" + width="20" /> + <icon + follows="top|left" + height="20" + image_name="Nearby_chat_icon" + layout="topleft" + left="5" + name="nearby_chat_icon" + top="2" + visible="false" + width="20"/> <layout_stack animate="false" follows="all" height="24" layout="topleft" - left_pad="5" + left="30" mouse_opaque="false" name="conversation_item_stack" orientation="horizontal" @@ -36,7 +56,7 @@ <icon height="20" follows="top|right|left" - image_name="Conv_toolbar_hang_up" + image_name="Conv_toolbar_open_call" layout="topleft" left="0" name="selected_icon" @@ -70,7 +90,7 @@ layout="topleft" left_pad="5" mouse_opaque="true" - name="speaking_indicator" + name="speaking_indicatorn" visible="false" width="20" /> </layout_panel> -- cgit v1.2.3 From 9e1ea5a1652528dead811dee8904ae8a6833d163 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 26 Sep 2012 12:05:27 -0700 Subject: CHUI-364 : WIP : Suppress unused code --- indra/newview/llimfloatercontainer.cpp | 50 ---------------------------------- indra/newview/llimfloatercontainer.h | 1 - 2 files changed, 51 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 14d40d4685..e64247cd60 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -661,56 +661,6 @@ void LLIMFloaterContainer::setSortOrder(const LLConversationSort& order) gSavedSettings.setU32("ConversationSortOrder", (U32)order); } -void LLIMFloaterContainer::repositioningWidgets() -{ - if (!mInitialized) - { - return; - } - - if (!mConversationsPane->isCollapsed()) - { - S32 list_width = (mConversationsPane->getRect()).getWidth(); - gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", list_width); - } - LLRect panel_rect = mConversationsListPanel->getRect(); - S32 item_height = 16; - int index = 0; - for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); - widget_it != mConversationsWidgets.end(); - widget_it++) - { - LLFolderViewFolder* widget = dynamic_cast<LLFolderViewFolder*>(widget_it->second); - widget->setVisible(TRUE); - widget->setRect(LLRect(0, - panel_rect.getHeight() - item_height*index, - panel_rect.getWidth(), - panel_rect.getHeight() - item_height*(index+1))); - index++; - // Reposition the children as well - // Merov : This is highly suspiscious but gets the debug hack to work. This needs to be revised though. - if (widget->getItemsCount() != 0) - { - BOOL is_open = widget->isOpen(); - widget->setOpen(TRUE); - LLFolderViewFolder::items_t::const_iterator current = widget->getItemsBegin(); - LLFolderViewFolder::items_t::const_iterator end = widget->getItemsEnd(); - while (current != end) - { - LLFolderViewItem* item = (*current); - item->setVisible(TRUE); - item->setRect(LLRect(0, - panel_rect.getHeight() - item_height*index, - panel_rect.getWidth(), - panel_rect.getHeight() - item_height*(index+1))); - index++; - current++; - } - widget->setOpen(is_open); - } - } -} - void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id) { LLFolderViewItem* widget = mConversationsWidgets[session_id]; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index e8d185297c..070feb3273 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -100,7 +100,6 @@ private: void collapseConversationsPane(bool collapse); void updateState(bool collapse, S32 delta_width); - void repositioningWidgets(); void onAddButtonClicked(); void onAvatarPicked(const uuid_vec_t& ids); -- cgit v1.2.3 From 30ea13381884bca7a07e2bca16e5bde0ccacb530 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 26 Sep 2012 17:30:52 -0700 Subject: CHUI-344 : Fix Mac build issue introduced by previous fix attempt --- indra/newview/lloutputmonitorctrl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index d48826779c..1c412b15f7 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -167,7 +167,8 @@ void LLOutputMonitorCtrl::draw() F32 power = 0; for (; part_it != participant_uuids.end(); ++part_it) { - if (power = LLVoiceClient::instance().getCurrentPower(*part_it)) + power = LLVoiceClient::instance().getCurrentPower(*part_it); + if (power) { mPower = power; break; -- cgit v1.2.3 From f7f15900ea4c61c499427a8b6416dc08e9a972f7 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Thu, 27 Sep 2012 17:46:11 +0300 Subject: CHUI-346 ADDITIONAL FIX (LLConversationViewSession: enable current voice channel indicator) - When voice initialized show voice channel indicator for nearby chat session --- indra/newview/llconversationview.cpp | 58 +++++++++++++++++++++++++++++------ indra/newview/llconversationview.h | 6 ++++ indra/newview/lloutputmonitorctrl.cpp | 7 +++-- indra/newview/lloutputmonitorctrl.h | 6 ++-- 4 files changed, 61 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index ab15e20d89..c2898d9a47 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -45,6 +45,30 @@ static LLDefaultChildRegistry::Register<LLConversationViewSession> r_conversatio const LLColor4U DEFAULT_WHITE(255, 255, 255); +class LLNearbyVoiceClientStatusObserver : public LLVoiceClientStatusObserver +{ +public: + + LLNearbyVoiceClientStatusObserver(LLConversationViewSession* conv) + : conversation(conv) + {} + + virtual void onChange(EStatusType status, const std::string &channelURI, bool proximal) + { + if (conversation + && status != STATUS_JOINING + && status != STATUS_LEFT_CHANNEL + && LLVoiceClient::getInstance()->voiceEnabled() + && LLVoiceClient::getInstance()->isVoiceWorking()) + { + conversation->showVoiceIndicator(); + } + } + +private: + LLConversationViewSession* conversation; +}; + LLConversationViewSession::Params::Params() : container() {} @@ -55,13 +79,19 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes mItemPanel(NULL), mCallIconLayoutPanel(NULL), mSessionTitle(NULL), - mSpeakingIndicator(NULL) + mSpeakingIndicator(NULL), + mVoiceClientObserver(NULL) { } LLConversationViewSession::~LLConversationViewSession() { mActiveVoiceChannelConnection.disconnect(); + + if(LLVoiceClient::instanceExists() && mVoiceClientObserver) + { + LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); + } } BOOL LLConversationViewSession::postBuild() @@ -91,8 +121,7 @@ BOOL LLConversationViewSession::postBuild() LLAvatarIconCtrl* icon = mItemPanel->getChild<LLAvatarIconCtrl>("avatar_icon"); icon->setVisible(true); icon->setValue(session->mOtherParticipantID); - mSpeakingIndicator->setSpeakerId(gAgentID, session->mSessionID); - mSpeakingIndicator->setShowParticipantsTalking(true); + mSpeakingIndicator->setSpeakerId(gAgentID, session->mSessionID, true); } break; } @@ -100,27 +129,28 @@ BOOL LLConversationViewSession::postBuild() { LLGroupIconCtrl* icon = mItemPanel->getChild<LLGroupIconCtrl>("group_icon"); icon->setVisible(true); - mSpeakingIndicator->setSpeakerId(gAgentID, vmi->getUUID()); - mSpeakingIndicator->setShowParticipantsTalking(true); + mSpeakingIndicator->setSpeakerId(gAgentID, vmi->getUUID(), true); } case LLConversationItem::CONV_SESSION_GROUP: { LLGroupIconCtrl* icon = mItemPanel->getChild<LLGroupIconCtrl>("group_icon"); icon->setVisible(true); icon->setValue(vmi->getUUID()); - mSpeakingIndicator->setSpeakerId(gAgentID, vmi->getUUID()); - mSpeakingIndicator->setShowParticipantsTalking(true); + mSpeakingIndicator->setSpeakerId(gAgentID, vmi->getUUID(), true); break; } case LLConversationItem::CONV_SESSION_NEARBY: { LLIconCtrl* icon = mItemPanel->getChild<LLIconCtrl>("nearby_chat_icon"); icon->setVisible(true); - mSpeakingIndicator->setSpeakerId(gAgentID); - mSpeakingIndicator->setShowParticipantsTalking(true); + mSpeakingIndicator->setSpeakerId(gAgentID, LLUUID::null, true); + if(LLVoiceClient::instanceExists()) + { + LLNearbyVoiceClientStatusObserver* mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this); + LLVoiceClient::getInstance()->addObserver(mVoiceClientObserver); + } break; } - default: break; } @@ -232,6 +262,14 @@ LLConversationViewParticipant* LLConversationViewSession::findParticipant(const return (iter == getItemsEnd() ? NULL : participant); } +void LLConversationViewSession::showVoiceIndicator() +{ + if (LLVoiceChannel::getCurrentVoiceChannel()->getSessionID().isNull()) + { + mCallIconLayoutPanel->setVisible(true); + } +} + void LLConversationViewSession::refresh() { // Refresh the session view from its model data diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index dbc7f3b1bb..064239eeb1 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -38,6 +38,8 @@ class LLIMFloaterContainer; class LLConversationViewSession; class LLConversationViewParticipant; +class LLVoiceClientStatusObserver; + // Implementation of conversations list session widgets class LLConversationViewSession : public LLFolderViewFolder @@ -68,6 +70,8 @@ public: void setVisibleIfDetached(BOOL visible); LLConversationViewParticipant* findParticipant(const LLUUID& participant_id); + void showVoiceIndicator(); + virtual void refresh(); private: @@ -79,6 +83,8 @@ private: LLTextBox* mSessionTitle; LLOutputMonitorCtrl* mSpeakingIndicator; + LLVoiceClientStatusObserver* mVoiceClientObserver; + boost::signals2::connection mActiveVoiceChannelConnection; }; diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 1c412b15f7..c3cbca68c7 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -75,7 +75,7 @@ LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p) mIsAgentControl(false), mIsSwitchDirty(false), mShouldSwitchOn(false), - mShowParticipantsTalking(false) + mShowParticipantsSpeaking(false) { //static LLUIColor output_monitor_muted_color = LLUIColorTable::instance().getColor("OutputMonitorMutedColor", LLColor4::orange); //static LLUIColor output_monitor_overdriven_color = LLUIColorTable::instance().getColor("OutputMonitorOverdrivenColor", LLColor4::red); @@ -158,7 +158,7 @@ void LLOutputMonitorCtrl::draw() } } - if ((mPower == 0.f && !mIsTalking) && mShowParticipantsTalking) + if ((mPower == 0.f && !mIsTalking) && mShowParticipantsSpeaking) { std::set<LLUUID> participant_uuids; LLVoiceClient::instance().getParticipantList(participant_uuids); @@ -272,7 +272,7 @@ BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) return TRUE; } -void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/) +void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/, bool show_other_participants_speaking /* = false */) { if (speaker_id.isNull() && mSpeakerId.notNull()) { @@ -287,6 +287,7 @@ void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& s LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); } + mShowParticipantsSpeaking = show_other_participants_speaking; mSpeakerId = speaker_id; LLSpeakingIndicatorManager::registerSpeakingIndicator(mSpeakerId, this, session_id); diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 44d4d6f64b..1fa6ef41f8 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -82,7 +82,7 @@ public: void setIsTalking(bool val) { mIsTalking = val; } - void setShowParticipantsTalking(bool show) { mShowParticipantsTalking = show; } + void setShowParticipantsSpeaking(bool show) { mShowParticipantsSpeaking = show; } /** * Sets avatar UUID to interact with voice channel. @@ -92,7 +92,7 @@ public: * If this parameter is set registered indicator will be shown only in voice channel * which has the same session id (EXT-5562). */ - void setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id = LLUUID::null); + void setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id = LLUUID::null, bool show_other_participants_speaking = false); //called by mute list virtual void onChange(); @@ -134,7 +134,7 @@ private: bool mIsAgentControl; bool mIsMuted; bool mIsTalking; - bool mShowParticipantsTalking; + bool mShowParticipantsSpeaking; LLPointer<LLUIImage> mImageMute; LLPointer<LLUIImage> mImageOff; LLPointer<LLUIImage> mImageOn; -- cgit v1.2.3 From 6daf27cd0f89e324f6fa67792e60bb8452af5adb Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 27 Sep 2012 17:14:15 +0300 Subject: CHUI-352 FIXED (Viewer crash when dropping a worn attachment): getting the item's id before destruction corresponding viewmodel's item --- indra/newview/llinventorypanel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 2a84616ddf..a77b57638f 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -441,8 +441,9 @@ void LLInventoryPanel::modelChanged(U32 mask) handled = true; if (model_item && view_item && viewmodel_item) { + const LLUUID& idp = viewmodel_item->getUUID(); view_item->destroyView(); - removeItemID(viewmodel_item->getUUID()); + removeItemID(idp); } view_item = buildNewViews(item_id); viewmodel_item = -- cgit v1.2.3 From 483cbd74d78b8fa7ce94e3d3c7d264bcdaa331b5 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Thu, 27 Sep 2012 20:09:22 +0300 Subject: CHUI-165 FIXED Add access to Conversation Log and Chat History from the People floater. --- indra/newview/llavataractions.cpp | 6 ++++++ indra/newview/llavataractions.h | 5 +++++ indra/newview/llpanelpeoplemenus.cpp | 1 + .../newview/skins/default/xui/en/menu_people_friends_view.xml | 8 ++++++++ indra/newview/skins/default/xui/en/menu_people_nearby.xml | 10 +++++++++- 5 files changed, 29 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 42a0376774..a76dbcac53 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -897,6 +897,12 @@ void LLAvatarActions::inviteToGroup(const LLUUID& id) } } +// static +void LLAvatarActions::viewChatHistory(const LLUUID& id) +{ + LLFloaterReg::showInstance("preview_conversation", id, true); +} + //== private methods ======================================================================================== // static diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 473b9cecc3..6e60f624ad 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -218,6 +218,11 @@ public: */ static void buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string); + /** + * Opens the chat history for avatar + */ + static void viewChatHistory(const LLUUID& id); + static std::set<LLUUID> getInventorySelectedUUIDs(); private: diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index c9eebe24d3..899771f3b9 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -69,6 +69,7 @@ LLContextMenu* NearbyMenu::createMenu() registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, id)); registrar.add("Avatar.BlockUnblock", boost::bind(&LLAvatarActions::toggleBlock, id)); registrar.add("Avatar.InviteToGroup", boost::bind(&LLAvatarActions::inviteToGroup, id)); + registrar.add("Avatar.Calllog", boost::bind(&LLAvatarActions::viewChatHistory, id)); enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2)); enable_registrar.add("Avatar.CheckItem", boost::bind(&NearbyMenu::checkContextMenuItem, this, _2)); diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml index eab7b8c085..dde9432867 100644 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml @@ -40,4 +40,12 @@ function="CheckControl" parameter="FriendsListShowPermissions" /> </menu_item_check> + <menu_item_check name="view_conversation" label="View Conversation Log..."> + <menu_item_check.on_check + function="Floater.Visible" + parameter="conversation" /> + <menu_item_check.on_click + function="Floater.Toggle" + parameter="conversation" /> + </menu_item_check> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index b7c9ab1fe3..8014e81469 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -36,6 +36,14 @@ parameter="can_call" /> </menu_item_call> <menu_item_separator /> + <menu_item_call + label="View chat history..." + layout="topleft" + name="Chat history"> + <menu_item_call.on_click + function="Avatar.Calllog" /> + </menu_item_call> + <menu_item_separator /> <menu_item_call label="Add Friend" layout="topleft" @@ -101,5 +109,5 @@ function="Avatar.EnableItem" parameter="can_block" /> </menu_item_check> - + <menu_item_separator /> </context_menu> -- cgit v1.2.3 From 78e6b910a5012352ab265e52a78b0d340ac7ce27 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 27 Sep 2012 20:04:26 +0300 Subject: CHUI-370, CHUI-372 FIXED Viewer crash when voice calling another user from people panel then opening conversation floater or when starting a IM chat when conversation floater has not been previously opened: connecting floater to the host postponed until the end of its initialization --- indra/newview/llnearbychat.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 75c691d99b..2982f30102 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -122,8 +122,6 @@ BOOL LLNearbyChat::postBuild() // it is used for show the item's name in the conversations list setTitle(LLTrans::getString("NearbyChatTitle")); - addToHost(); - //for menu LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; @@ -312,6 +310,7 @@ void LLNearbyChat::addToHost() // virtual void LLNearbyChat::onOpen(const LLSD& key) { + addToHost(); LLIMConversation::onOpen(key); showTranslationCheckbox(LLTranslate::isTranslationConfigured()); } -- cgit v1.2.3 From 3e3735c16b47402d8fc2da8afa6086638fb5b948 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine <pguslisty@productengine.com> Date: Fri, 28 Sep 2012 15:02:31 +0300 Subject: CHUI-345 ADDITIONAL FIX (LLConversationViewSession: enable speaking indicator) - Clicking on the conversation speaking icon brings up the volume floater for voice conversations --- indra/newview/CMakeLists.txt | 2 + indra/newview/llfloaterchatvoicevolume.cpp | 26 ++++++++++++ indra/newview/llfloaterchatvoicevolume.h | 26 ++++++++++++ indra/newview/lloutputmonitorctrl.cpp | 6 ++- indra/newview/llviewerfloaterreg.cpp | 2 + .../default/xui/en/floater_voice_chat_volume.xml | 48 ++++++++++++++++++++++ 6 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 indra/newview/llfloaterchatvoicevolume.cpp create mode 100644 indra/newview/llfloaterchatvoicevolume.h create mode 100644 indra/newview/skins/default/xui/en/floater_voice_chat_volume.xml (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b94c33587b..ec1562a4c1 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -197,6 +197,7 @@ set(viewer_SOURCE_FILES llfloaterbuycurrencyhtml.cpp llfloaterbuyland.cpp llfloatercamera.cpp + llfloaterchatvoicevolume.cpp llfloatercolorpicker.cpp llfloaterconversationlog.cpp llfloaterconversationpreview.cpp @@ -781,6 +782,7 @@ set(viewer_HEADER_FILES llfloaterbuycurrencyhtml.h llfloaterbuyland.h llfloatercamera.h + llfloaterchatvoicevolume.h llfloatercolorpicker.h llfloaterconversationlog.h llfloaterconversationpreview.h diff --git a/indra/newview/llfloaterchatvoicevolume.cpp b/indra/newview/llfloaterchatvoicevolume.cpp new file mode 100644 index 0000000000..d10c3c6504 --- /dev/null +++ b/indra/newview/llfloaterchatvoicevolume.cpp @@ -0,0 +1,26 @@ +/* + * llfloaterchatvoicevolume.cpp + * + * Created on: Sep 27, 2012 + * Author: pguslisty + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterchatvoicevolume.h" + +LLFloaterChatVoiceVolume::LLFloaterChatVoiceVolume(const LLSD& key) +: LLInspect(key) +{ +} + +void LLFloaterChatVoiceVolume::onOpen(const LLSD& key) +{ + LLInspect::onOpen(key); + LLUI::positionViewNearMouse(this); +} + +LLFloaterChatVoiceVolume::~LLFloaterChatVoiceVolume() +{ + LLTransientFloaterMgr::getInstance()->removeControlView(this); +}; diff --git a/indra/newview/llfloaterchatvoicevolume.h b/indra/newview/llfloaterchatvoicevolume.h new file mode 100644 index 0000000000..0aeab7874c --- /dev/null +++ b/indra/newview/llfloaterchatvoicevolume.h @@ -0,0 +1,26 @@ +/* + * llfloaterchatvoicevolume.h + * + * Created on: Sep 27, 2012 + * Author: pguslisty + */ + +#ifndef LLFLOATERCHATVOICEVOLUME_H_ +#define LLFLOATERCHATVOICEVOLUME_H_ + +#include "llinspect.h" +#include "lltransientfloatermgr.h" + +class LLFloaterChatVoiceVolume : public LLInspect, LLTransientFloater +{ +public: + + LLFloaterChatVoiceVolume(const LLSD& key); + virtual ~LLFloaterChatVoiceVolume(); + + virtual void onOpen(const LLSD& key); + + /*virtual*/ LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; } +}; + +#endif /* LLFLOATERCHATVOICEVOLUME_H_ */ diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index c3cbca68c7..4a9a50d96a 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -264,10 +264,14 @@ void LLOutputMonitorCtrl::draw() // virtual BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) { - if (mSpeakerId != gAgentID) + if (mSpeakerId != gAgentID && !mShowParticipantsSpeaking) { LLFloaterReg::showInstance("floater_voice_volume", LLSD().with("avatar_id", mSpeakerId)); } + else if(mShowParticipantsSpeaking) + { + LLFloaterReg::showInstance("chat_voice", LLSD()); + } return TRUE; } diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 927ee8f380..4cd5ecc754 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -50,6 +50,7 @@ #include "llfloaterbump.h" #include "llfloaterbvhpreview.h" #include "llfloatercamera.h" +#include "llfloaterchatvoicevolume.h" #include "llfloaterconversationlog.h" #include "llfloaterconversationpreview.h" #include "llfloaterdeleteenvpreset.h" @@ -192,6 +193,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>); LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>); + LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatVoiceVolume>); LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>); LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>); LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>); diff --git a/indra/newview/skins/default/xui/en/floater_voice_chat_volume.xml b/indra/newview/skins/default/xui/en/floater_voice_chat_volume.xml new file mode 100644 index 0000000000..5c71fd3bc6 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_voice_chat_volume.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> + +<floater + legacy_header_height="25" + bevel_style="in" + bg_opaque_image="Inspector_Background" + can_close="false" + can_minimize="false" + height="90" + layout="topleft" + name="floater_voice_volume" + single_instance="true" + sound_flags="0" + title="VOICE CHAT VOLUME" + visible="true" + width="245"> + <slider + control_name="AudioLevelVoice" + disabled_control="MuteAudio" + follows="left|top" + height="16" + increment="0.025" + initial_value="0.5" + label="Voice Chat" + label_width="50" + layout="topleft" + left="15" + top="50" + name="chat_voice_volume" + show_text="false" + slider_label.halign="right" + volume="true" + width="200"> + </slider> + <button + control_name="MuteVoice" + disabled_control="MuteAudio" + follows="top|left" + height="16" + image_selected="AudioMute_Off" + image_unselected="Audio_Off" + is_toggle="true" + layout="topleft" + left_pad="5" + name="mute_audio" + tab_stop="false" + width="16" /> +</floater> \ No newline at end of file -- cgit v1.2.3 From 8b2ed2e2050fcb8836be120902f44417613adb13 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 28 Sep 2012 18:22:00 +0300 Subject: CHUI-370, CHUI-372 ADDITIONAL FIX (Viewer crash when voice calling another user from people panel then opening conversation floater or when starting a IM chat when conversation floater has not been previously opened): fixed nearby chat positioning --- indra/newview/llimfloatercontainer.cpp | 1 + indra/newview/llnearbychat.cpp | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 indra/newview/llimfloatercontainer.cpp (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp old mode 100755 new mode 100644 index e64247cd60..a74ebdae7a --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -432,6 +432,7 @@ void LLIMFloaterContainer::setVisible(BOOL visible) // *TODO: find a way to move this to XML as a default panel or something like that LLSD name("nearby_chat"); LLFloaterReg::toggleInstanceOrBringToFront(name); + LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat")->addToHost(); } } diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 2982f30102..4b35092f2d 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -310,7 +310,6 @@ void LLNearbyChat::addToHost() // virtual void LLNearbyChat::onOpen(const LLSD& key) { - addToHost(); LLIMConversation::onOpen(key); showTranslationCheckbox(LLTranslate::isTranslationConfigured()); } -- cgit v1.2.3 From 0651e10afff81a6e32828c122753d87b8503a79b Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 28 Sep 2012 11:15:45 -0700 Subject: CHUI-342, CHUI-366 and CHUI-367 : WIP : Allow a NO_TOOLTIP value for tooltips, update display/user names and sort on display/user names --- indra/llui/llview.cpp | 22 ++++++++++++---------- indra/llui/llview.h | 1 + indra/newview/llconversationmodel.cpp | 10 +++++++--- indra/newview/llconversationmodel.h | 2 ++ indra/newview/llimfloatercontainer.cpp | 33 ++++++++++++++++++++++++++++++--- indra/newview/llimfloatercontainer.h | 1 + 6 files changed, 53 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 5c2b3236f6..49e7eaef99 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -870,16 +870,18 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask) std::string tooltip = getToolTip(); if (!tooltip.empty()) { - // allow "scrubbing" over ui by showing next tooltip immediately - // if previous one was still visible - F32 timeout = LLToolTipMgr::instance().toolTipVisible() - ? LLUI::sSettingGroups["config"]->getF32( "ToolTipFastDelay" ) - : LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" ); - LLToolTipMgr::instance().show(LLToolTip::Params() - .message(tooltip) - .sticky_rect(calcScreenRect()) - .delay_time(timeout)); - + if (tooltip != NO_TOOLTIP_STRING) + { + // allow "scrubbing" over ui by showing next tooltip immediately + // if previous one was still visible + F32 timeout = LLToolTipMgr::instance().toolTipVisible() + ? LLUI::sSettingGroups["config"]->getF32( "ToolTipFastDelay" ) + : LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" ); + LLToolTipMgr::instance().show(LLToolTip::Params() + .message(tooltip) + .sticky_rect(calcScreenRect()) + .delay_time(timeout)); + } handled = TRUE; } diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 1c35349510..ba896b65a4 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -67,6 +67,7 @@ const BOOL NOT_MOUSE_OPAQUE = FALSE; const U32 GL_NAME_UI_RESERVED = 2; +static const std::string NO_TOOLTIP_STRING = " "; // maintains render state during traversal of UI tree class LLViewDrawContext diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 7d0ffa0788..176c05248d 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -36,6 +36,7 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(display_name), + mUseNameForSort(true), mUUID(uuid), mNeedsRefresh(true), mConvType(CONV_UNKNOWN), @@ -46,6 +47,7 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& u LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(""), + mUseNameForSort(true), mUUID(uuid), mNeedsRefresh(true), mConvType(CONV_UNKNOWN), @@ -56,6 +58,7 @@ LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInte LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(""), + mUseNameForSort(true), mUUID(), mNeedsRefresh(true), mConvType(CONV_UNKNOWN), @@ -251,8 +254,9 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) { - mName = av_name.mUsername; - mDisplayName = av_name.mDisplayName; + mUseNameForSort = !av_name.mUsername.empty(); + mName = (mUseNameForSort ? av_name.mUsername : NO_TOOLTIP_STRING); + mDisplayName = (av_name.mDisplayName.empty() ? mName : av_name.mDisplayName); mNeedsRefresh = true; if (mParent) { @@ -363,7 +367,7 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL } // By default, in all other possible cases (including sort order type LLConversationFilter::SO_NAME of course), // we sort by name - S32 compare = LLStringUtil::compareDict(a->getName(), b->getName()); + S32 compare = LLStringUtil::compareDict((a->useNameForSort() ? a->getName() : a->getDisplayName()), (b->useNameForSort() ? b->getName() : b->getDisplayName())); return (compare < 0); } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 30f94d51ae..82d4f0a710 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -123,9 +123,11 @@ public: void resetRefresh() { mNeedsRefresh = false; } bool needsRefresh() { return mNeedsRefresh; } + bool const useNameForSort() const { return mUseNameForSort; } protected: std::string mName; // Name of the session or the participant + bool mUseNameForSort; LLUUID mUUID; // UUID of the session or the participant EConversationType mConvType; // Type of conversation item bool mNeedsRefresh; // Flag signaling to the view that something changed for this item diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index e64247cd60..26b4e6c903 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -158,8 +158,7 @@ BOOL LLIMFloaterContainer::postBuild() collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); - LLAvatarNameCache::addUseDisplayNamesCallback( - boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); + LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); if (! mMessagesPane->isCollapsed()) { @@ -176,8 +175,11 @@ BOOL LLIMFloaterContainer::postBuild() mInitialized = true; - // Add callback: we'll take care of view updates on idle + // Add callbacks: + // We'll take care of view updates on idle gIdleCallbacks.addFunction(idle, this); + // When display name option change, we need to reload all participant names + LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLIMFloaterContainer::processParticipantsStyleUpdate, this)); return TRUE; } @@ -330,6 +332,31 @@ void LLIMFloaterContainer::setMinimized(BOOL b) } } +// Update all participants in the conversation lists +void LLIMFloaterContainer::processParticipantsStyleUpdate() +{ + // On each session in mConversationsItems + for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) + { + // Get the current session descriptors + LLConversationItem* session_model = it_session->second; + // Iterate through each model participant child + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = session_model->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = session_model->getChildrenEnd(); + while (current_participant_model != end_participant_model) + { + LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); + // Get the avatar name for this participant id from the cache and update the model + LLUUID participant_id = participant_model->getUUID(); + LLAvatarName av_name; + LLAvatarNameCache::get(participant_id,&av_name); + participant_model->onAvatarNameCache(av_name); + // Next participant + current_participant_model++; + } + } +} + // static void LLIMFloaterContainer::idle(void* user_data) { diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 070feb3273..2debc2455b 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -96,6 +96,7 @@ private: void onNewMessageReceived(const LLSD& data); void onExpandCollapseButtonClicked(); + void processParticipantsStyleUpdate(); void collapseConversationsPane(bool collapse); -- cgit v1.2.3 From 166ff2b1b8dc21ad1a88c715a480ce1d2c5c2e07 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 28 Sep 2012 15:08:56 -0700 Subject: CHUI-366 : Completed : Update participants names when the display name pref is toggled on and off. --- indra/newview/llimfloatercontainer.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 26b4e6c903..45d63ce4f9 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -350,7 +350,13 @@ void LLIMFloaterContainer::processParticipantsStyleUpdate() LLUUID participant_id = participant_model->getUUID(); LLAvatarName av_name; LLAvatarNameCache::get(participant_id,&av_name); - participant_model->onAvatarNameCache(av_name); + // Avoid updating the model though if the cache is still waiting for its first update + if (!av_name.mDisplayName.empty()) + { + participant_model->onAvatarNameCache(av_name); + } + // Bind update to the next cache name signal + LLAvatarNameCache::get(participant_id, boost::bind(&LLConversationItemParticipant::onAvatarNameCache, participant_model, _2)); // Next participant current_participant_model++; } @@ -368,7 +374,6 @@ void LLIMFloaterContainer::idle(void* user_data) { self->setNearbyDistances(); } - self->mConversationsRoot->update(); } -- cgit v1.2.3 From 7fc33cc47fdc080bbc7674cf118011b689ba1485 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 28 Sep 2012 17:30:18 -0700 Subject: CHUI-367 : Completed : Show user name tooltip in all situations so to avoid the conversation name showing up --- indra/llui/llview.cpp | 21 +++++++++------------ indra/llui/llview.h | 2 -- indra/newview/llconversationmodel.cpp | 10 +++------- indra/newview/llconversationmodel.h | 2 -- 4 files changed, 12 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 49e7eaef99..8323bfc12f 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -870,18 +870,15 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask) std::string tooltip = getToolTip(); if (!tooltip.empty()) { - if (tooltip != NO_TOOLTIP_STRING) - { - // allow "scrubbing" over ui by showing next tooltip immediately - // if previous one was still visible - F32 timeout = LLToolTipMgr::instance().toolTipVisible() - ? LLUI::sSettingGroups["config"]->getF32( "ToolTipFastDelay" ) - : LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" ); - LLToolTipMgr::instance().show(LLToolTip::Params() - .message(tooltip) - .sticky_rect(calcScreenRect()) - .delay_time(timeout)); - } + // allow "scrubbing" over ui by showing next tooltip immediately + // if previous one was still visible + F32 timeout = LLToolTipMgr::instance().toolTipVisible() + ? LLUI::sSettingGroups["config"]->getF32( "ToolTipFastDelay" ) + : LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" ); + LLToolTipMgr::instance().show(LLToolTip::Params() + .message(tooltip) + .sticky_rect(calcScreenRect()) + .delay_time(timeout)); handled = TRUE; } diff --git a/indra/llui/llview.h b/indra/llui/llview.h index ba896b65a4..15b85a6418 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -67,8 +67,6 @@ const BOOL NOT_MOUSE_OPAQUE = FALSE; const U32 GL_NAME_UI_RESERVED = 2; -static const std::string NO_TOOLTIP_STRING = " "; - // maintains render state during traversal of UI tree class LLViewDrawContext { diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 176c05248d..9fa8758d11 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -36,7 +36,6 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(display_name), - mUseNameForSort(true), mUUID(uuid), mNeedsRefresh(true), mConvType(CONV_UNKNOWN), @@ -47,7 +46,6 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& u LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(""), - mUseNameForSort(true), mUUID(uuid), mNeedsRefresh(true), mConvType(CONV_UNKNOWN), @@ -58,7 +56,6 @@ LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInte LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(""), - mUseNameForSort(true), mUUID(), mNeedsRefresh(true), mConvType(CONV_UNKNOWN), @@ -254,9 +251,8 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) { - mUseNameForSort = !av_name.mUsername.empty(); - mName = (mUseNameForSort ? av_name.mUsername : NO_TOOLTIP_STRING); - mDisplayName = (av_name.mDisplayName.empty() ? mName : av_name.mDisplayName); + mName = (av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername); + mDisplayName = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); mNeedsRefresh = true; if (mParent) { @@ -367,7 +363,7 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL } // By default, in all other possible cases (including sort order type LLConversationFilter::SO_NAME of course), // we sort by name - S32 compare = LLStringUtil::compareDict((a->useNameForSort() ? a->getName() : a->getDisplayName()), (b->useNameForSort() ? b->getName() : b->getDisplayName())); + S32 compare = LLStringUtil::compareDict(a->getName(), b->getName()); return (compare < 0); } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 82d4f0a710..30f94d51ae 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -123,11 +123,9 @@ public: void resetRefresh() { mNeedsRefresh = false; } bool needsRefresh() { return mNeedsRefresh; } - bool const useNameForSort() const { return mUseNameForSort; } protected: std::string mName; // Name of the session or the participant - bool mUseNameForSort; LLUUID mUUID; // UUID of the session or the participant EConversationType mConvType; // Type of conversation item bool mNeedsRefresh; // Flag signaling to the view that something changed for this item -- cgit v1.2.3 From 4a41aa8fad7f4a0c1daab5d159920745a03a5950 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 28 Sep 2012 18:39:55 -0700 Subject: CHUI-345 : Add mandatory license to the files --- indra/newview/llfloaterchatvoicevolume.cpp | 26 ++++++++++++++++++++++---- indra/newview/llfloaterchatvoicevolume.h | 26 ++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterchatvoicevolume.cpp b/indra/newview/llfloaterchatvoicevolume.cpp index d10c3c6504..3c76a3a43c 100644 --- a/indra/newview/llfloaterchatvoicevolume.cpp +++ b/indra/newview/llfloaterchatvoicevolume.cpp @@ -1,8 +1,26 @@ -/* - * llfloaterchatvoicevolume.cpp +/** + * @file llfloaterchatvoicevolume.cpp * - * Created on: Sep 27, 2012 - * Author: pguslisty + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" diff --git a/indra/newview/llfloaterchatvoicevolume.h b/indra/newview/llfloaterchatvoicevolume.h index 0aeab7874c..61ad92b6da 100644 --- a/indra/newview/llfloaterchatvoicevolume.h +++ b/indra/newview/llfloaterchatvoicevolume.h @@ -1,8 +1,26 @@ -/* - * llfloaterchatvoicevolume.h +/** + * @file llfloaterchatvoicevolume.h * - * Created on: Sep 27, 2012 - * Author: pguslisty + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ */ #ifndef LLFLOATERCHATVOICEVOLUME_H_ -- cgit v1.2.3 From 507b66aeb1614a1293890ffacbab53ccecc25e20 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 28 Sep 2012 19:40:17 +0300 Subject: CHUI-349 (Crash when clicking on nearby chat toast): removed a faulty method LLIMFloater::addToIMContainer; replaced it's calls to calls of its correct twin - LLIMFloater::addToHost --- indra/newview/llimfloater.cpp | 47 ++++++++++++---------------------- indra/newview/llimfloater.h | 3 +-- indra/newview/llimfloatercontainer.cpp | 4 +-- 3 files changed, 20 insertions(+), 34 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 43adfdfd08..d11504d312 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -582,13 +582,14 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) build_names_string(temp_uuids, ui_title); updateSessionName(ui_title, ui_title); } - } +} -//static -LLIMFloater* LLIMFloater::addToIMContainer(const LLUUID& session_id) +void LLIMFloater::addToHost(const LLUUID& session_id, const bool force) { - if (!gIMMgr->hasSession(session_id)) - return NULL; + if (!LLIMConversation::isChatMultiTab() || !gIMMgr->hasSession(session_id)) + { + return; + } // Test the existence of the floater before we try to create it bool exist = findInstance(session_id); @@ -612,19 +613,22 @@ LLIMFloater* LLIMFloater::addToIMContainer(const LLUUID& session_id) } } - if (floater_container && floater_container->getVisible()) + if (force) { - floater->openFloater(floater->getKey()); - floater->setVisible(TRUE); - } - else - { - floater->setVisible(FALSE); + if (floater_container && floater_container->getVisible()) + { + floater->openFloater(floater->getKey()); + floater->setVisible(TRUE); + } + else + { + floater->setVisible(FALSE); + } } } - return floater; } + //static LLIMFloater* LLIMFloater::show(const LLUUID& session_id) { @@ -1323,23 +1327,6 @@ void LLIMFloater::onIMChicletCreated( const LLUUID& session_id ) { LLIMFloater::addToHost(session_id); } -void LLIMFloater::addToHost(const LLUUID& session_id) - { - if (LLIMConversation::isChatMultiTab()) -{ - LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); - if (!im_box) - { - im_box = LLIMFloaterContainer::getInstance(); - } - - if (im_box && !LLIMFloater::findInstance(session_id)) - { - LLIMFloater* new_tab = LLIMFloater::getInstance(session_id); - im_box->addFloater(new_tab, FALSE, LLTabContainer::END); - } - } -} boost::signals2::connection LLIMFloater::setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb) { diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index e4a67a3d56..d444270716 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -71,14 +71,13 @@ public: static LLIMFloater* findInstance(const LLUUID& session_id); static LLIMFloater* getInstance(const LLUUID& session_id); - static void addToHost(const LLUUID& session_id); + static void addToHost(const LLUUID& session_id, const bool force = false); // LLFloater overrides /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); // Make IM conversion visible and update the message history static LLIMFloater* show(const LLUUID& session_id); - static LLIMFloater* addToIMContainer(const LLUUID& session_id); // Toggle panel specified by session_id // Returns true iff panel became visible diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index ffbdae305b..ca77f05545 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -86,13 +86,13 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - LLIMFloater::addToIMContainer(session_id); + LLIMFloater::addToHost(session_id, true); addConversationListItem(session_id); } void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { - LLIMFloater::addToIMContainer(session_id); + LLIMFloater::addToHost(session_id, true); addConversationListItem(session_id); } -- cgit v1.2.3 From 14307b099bdb0e7c5b56d052a55e010ecd69b5c3 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 28 Sep 2012 19:06:36 +0300 Subject: CHUI-361 FIXED (Viewer crash when selecting to start IM with user from right click menu in people floater ): prevent destruction of im_container; suppress warning for the nearby_chat --- indra/newview/llimfloatercontainer.cpp | 4 ++-- indra/newview/skins/default/xui/en/floater_im_container.xml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index ca77f05545..c6f0607b35 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -223,8 +223,8 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, session_id)); } else - { - LLUUID avatar_id = LLIMModel::getInstance()->getOtherParticipantID(session_id); + { LLUUID avatar_id = session_id.notNull()? + LLIMModel::getInstance()->getOtherParticipantID(session_id) : LLUUID(); LLAvatarIconCtrl::Params icon_params; icon_params.avatar_id = avatar_id; diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index d23ff28fd0..590ce45c33 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -11,6 +11,7 @@ save_rect="true" save_visibility="true" single_instance="true" + reuse_instance="true" title="CONVERSATIONS" width="680"> <string -- cgit v1.2.3 From d54eded93ba270402349f5f337bbe12339255ece Mon Sep 17 00:00:00 2001 From: Seth ProductEngine <slitovchuk@productengine.com> Date: Fri, 28 Sep 2012 20:48:24 +0300 Subject: CHUI-357 FIXED moved conversation icon to prevent it being obscured when conversations list is minimized. Added minimized mode for LLConversationViewSession: this mode is used to move the conversation icon within the item when the conversations panel is minimized. --- indra/newview/llconversationview.cpp | 39 ++++++++++++++++++++++++++++------ indra/newview/llconversationview.h | 6 ++++++ indra/newview/llimfloatercontainer.cpp | 20 +++++++++++++++++ 3 files changed, 59 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index c2898d9a47..d4eb551f7a 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -80,7 +80,8 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes mCallIconLayoutPanel(NULL), mSessionTitle(NULL), mSpeakingIndicator(NULL), - mVoiceClientObserver(NULL) + mVoiceClientObserver(NULL), + mMinimizedMode(false) { } @@ -168,15 +169,18 @@ void LLConversationViewSession::draw() const LLFolderViewItem::Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); - // update the rotation angle of open folder arrow - updateLabelRotation(); + // we don't draw the open folder arrow in minimized mode + if (!mMinimizedMode) + { + // update the rotation angle of open folder arrow + updateLabelRotation(); - drawOpenFolderArrow(default_params, sFgColor); + drawOpenFolderArrow(default_params, sFgColor); + } // draw highlight for selected items drawHighlight(show_context, true, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); - // draw children if root folder, or any other folder that is open or animating to closed state bool draw_children = getRoot() == static_cast<LLFolderViewFolder*>(this) || isOpen() @@ -201,7 +205,8 @@ void LLConversationViewSession::draw() // virtual S32 LLConversationViewSession::arrange(S32* width, S32* height) { - LLRect rect(getIndentation() + mArrowSize, + S32 h_pad = getIndentation() + mArrowSize; + LLRect rect(mMinimizedMode ? getLocalRect().mLeft : h_pad, getLocalRect().mTop, getLocalRect().mRight, getLocalRect().mTop - getItemHeight()); @@ -210,6 +215,16 @@ S32 LLConversationViewSession::arrange(S32* width, S32* height) return LLFolderViewFolder::arrange(width, height); } +// virtual +void LLConversationViewSession::toggleOpen() +{ + // conversations should not be opened while in minimized mode + if (!mMinimizedMode) + { + LLFolderViewFolder::toggleOpen(); + } +} + void LLConversationViewSession::selectItem() { @@ -231,6 +246,18 @@ void LLConversationViewSession::selectItem() LLFolderViewItem::selectItem(); } +void LLConversationViewSession::toggleMinimizedMode(bool is_minimized) +{ + mMinimizedMode = is_minimized; + + // hide the layout stack which contains all item's child widgets + // except for the icon which we display in minimized mode + getChild<LLView>("conversation_item_stack")->setVisible(!mMinimizedMode); + + S32 h_pad = getIndentation() + mArrowSize; + mItemPanel->translate(mMinimizedMode ? -h_pad : h_pad, 0); +} + void LLConversationViewSession::setVisibleIfDetached(BOOL visible) { // Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 064239eeb1..c81c70b456 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -67,6 +67,10 @@ public: /*virtual*/ S32 arrange(S32* width, S32* height); + /*virtual*/ void toggleOpen(); + + void toggleMinimizedMode(bool is_minimized); + void setVisibleIfDetached(BOOL visible); LLConversationViewParticipant* findParticipant(const LLUUID& participant_id); @@ -83,6 +87,8 @@ private: LLTextBox* mSessionTitle; LLOutputMonitorCtrl* mSpeakingIndicator; + bool mMinimizedMode; + LLVoiceClientStatusObserver* mVoiceClientObserver; boost::signals2::connection mActiveVoiceChannelConnection; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index c6f0607b35..6f7eb7822a 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -133,6 +133,7 @@ BOOL LLIMFloaterContainer::postBuild() p.listener = base_item; p.view_model = &mConversationViewModel; p.root = NULL; + p.use_ellipses = true; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); // a scroller for folder view @@ -532,6 +533,22 @@ void LLIMFloaterContainer::collapseConversationsPane(bool collapse) S32 collapsed_width = mConversationsPane->getMinDim(); updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - collapsed_width); + + for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + widget_it != mConversationsWidgets.end(); ++widget_it) + { + LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); + if (widget) + { + widget->toggleMinimizedMode(collapse); + + // force closing all open conversations when collapsing to minimized state + if (collapse) + { + widget->setOpen(false); + } + } + } } void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) @@ -806,6 +823,9 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) setConvItemSelect(uuid); + // set the widget to minimized mode if conversations pane is collapsed + widget->toggleMinimizedMode(mConversationsPane->isCollapsed()); + return; } -- cgit v1.2.3 From 11a148415e810706f2a1835b6b717a0a062d458f Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 28 Sep 2012 18:22:05 -0700 Subject: CHUI-102: Now the participants and one-on-one conversations have right-click-menus. These menus are functional as well, but 'chat history' does not yet work. --- indra/llui/llfolderview.cpp | 5 +- indra/llui/llfolderview.h | 2 + indra/newview/llconversationmodel.cpp | 44 +++++ indra/newview/llconversationmodel.h | 18 +- indra/newview/llimfloater.h | 1 + indra/newview/llimfloatercontainer.cpp | 192 ++++++++++++++++++++- indra/newview/llimfloatercontainer.h | 5 + indra/newview/llinventorypanel.cpp | 1 + .../skins/default/xui/en/menu_conversation.xml | 109 ++++++++++++ 9 files changed, 372 insertions(+), 5 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/menu_conversation.xml (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index ce1bc5914c..327a064228 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -138,7 +138,8 @@ LLFolderView::Params::Params() use_label_suffix("use_label_suffix"), allow_multiselect("allow_multiselect", true), show_empty_message("show_empty_message", true), - use_ellipses("use_ellipses", false) + use_ellipses("use_ellipses", false), + options_menu("options_menu", "") { folder_indentation = -4; } @@ -228,7 +229,7 @@ LLFolderView::LLFolderView(const Params& p) // make the popup menu available - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(p.options_menu, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); if (!menu) { menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu"); diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 81b0f087e8..260275269d 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -94,6 +94,8 @@ public: use_ellipses, show_item_link_overlays; Mandatory<LLFolderViewModelInterface*> view_model; + Optional<std::string> options_menu; + Params(); }; diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 7d0ffa0788..1c4c7aefae 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -28,6 +28,7 @@ #include "llviewerprecompiledheaders.h" #include "llconversationmodel.h" +#include "llmenugl.h" // // Conversation items : common behaviors @@ -84,6 +85,24 @@ void LLConversationItem::showProperties(void) { } +void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items) +{ + items.push_back(std::string("view_profile")); + items.push_back(std::string("im")); + items.push_back(std::string("offer_teleport")); + items.push_back(std::string("voice_call")); + items.push_back(std::string("chat_history")); + items.push_back(std::string("separator_chat_history")); + items.push_back(std::string("add_friend")); + items.push_back(std::string("remove_friend")); + items.push_back(std::string("invite_to_group")); + items.push_back(std::string("separator_invite_to_group")); + items.push_back(std::string("map")); + items.push_back(std::string("share")); + items.push_back(std::string("pay")); + items.push_back(std::string("block_unblock")); +} + // // LLConversationItemSession // @@ -191,6 +210,22 @@ void LLConversationItemSession::setDistance(const LLUUID& participant_id, F64 di } } +void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLConversationItemParticipant::buildContextMenu()" << llendl; + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + if(this->getType() == CONV_SESSION_1_ON_1) + { + items.push_back(std::string("close_conversation")); + items.push_back(std::string("separator_disconnect_from_voice")); + buildParticipantMenuOptions(items); + } + + hide_context_entries(menu, items, disabled_items); +} + // The time of activity of a session is the time of the most recent activity, session and participants included const bool LLConversationItemSession::getTime(F64& time) const { @@ -249,6 +284,15 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, mConvType = CONV_PARTICIPANT; } +void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + buildParticipantMenuOptions(items); + hide_context_entries(menu, items, disabled_items); +} + void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) { mName = av_name.mUsername; diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 30f94d51ae..43fa66e8e2 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -41,6 +41,8 @@ class LLConversationItemParticipant; typedef std::map<LLUUID, LLConversationItem*> conversations_items_map; typedef std::map<LLUUID, LLFolderViewItem*> conversations_widgets_map; +typedef std::vector<std::string> menuentry_vec_t; + // Conversation items: we hold a list of those and create an LLFolderViewItem widget for each // that we tuck into the mConversationsListPanel. class LLConversationItem : public LLFolderViewModelItemCommon @@ -124,6 +126,8 @@ public: void resetRefresh() { mNeedsRefresh = false; } bool needsRefresh() { return mNeedsRefresh; } + void buildParticipantMenuOptions(menuentry_vec_t& items); + protected: std::string mName; // Name of the session or the participant LLUUID mUUID; // UUID of the session or the participant @@ -155,6 +159,7 @@ public: bool isLoaded() { return mIsLoaded; } + void buildContextMenu(LLMenuGL& menu, U32 flags); virtual const bool getTime(F64& time) const; void dumpDebugData(); @@ -178,7 +183,8 @@ public: void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; } void setTimeNow() { mLastActiveTime = LLFrameTimer::getElapsedSeconds(); mNeedsRefresh = true; } void setDistance(F64 dist) { mDistToAgent = dist; mNeedsRefresh = true; } - + + void buildContextMenu(LLMenuGL& menu, U32 flags); void onAvatarNameCache(const LLAvatarName& av_name); virtual const bool getDistanceToAgent(F64& dist) const { dist = mDistToAgent; return (dist >= 0.0); } @@ -273,4 +279,14 @@ public: private: }; +// Utility function to hide all entries except those in the list +// Can be called multiple times on the same menu (e.g. if multiple items +// are selected). If "append" is false, then only common enabled items +// are set as enabled. + +//(defined in inventorybridge.cpp) +void hide_context_entries(LLMenuGL& menu, + const menuentry_vec_t &entries_to_show, + const menuentry_vec_t &disabled_entries); + #endif // LL_LLCONVERSATIONMODEL_H diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index e4a67a3d56..fbaf009939 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -128,6 +128,7 @@ public: static void onIMChicletCreated(const LLUUID& session_id); bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; } + LLUUID getOtherParticipantUUID() {return mOtherParticipantUUID;} static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); static floater_showed_signal_t sIMFloaterShowedSignal; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 14d40d4685..b4802c71f9 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -58,8 +58,12 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) mConversationsRoot(NULL), mInitialized(false) { + mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLIMFloaterContainer::isActionChecked, this, _2)); mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLIMFloaterContainer::onCustomAction, this, _2)); - mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLIMFloaterContainer::isActionChecked, this, _2)); + + mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLIMFloaterContainer::checkContextMenuItem, this, _2)); + mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLIMFloaterContainer::enableContextMenuItem, this, _2)); + mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLIMFloaterContainer::doToSelected, this, _2)); // Firstly add our self to IMSession observers, so we catch session events LLIMMgr::getInstance()->addSessionObserver(this); @@ -133,7 +137,9 @@ BOOL LLIMFloaterContainer::postBuild() p.listener = base_item; p.view_model = &mConversationViewModel; p.root = NULL; + p.options_menu = "menu_conversation.xml"; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); + mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); // a scroller for folder view LLRect scroller_view_rect = mConversationsListPanel->getRect(); @@ -341,7 +347,7 @@ void LLIMFloaterContainer::idle(void* user_data) { self->setNearbyDistances(); } - + self->mConversationsRoot->update(); } @@ -661,6 +667,188 @@ void LLIMFloaterContainer::setSortOrder(const LLConversationSort& order) gSavedSettings.setU32("ConversationSortOrder", (U32)order); } +void LLIMFloaterContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids) +{ + const std::set<LLFolderViewItem*> selectedItems = mConversationsRoot->getSelectionList(); + + std::set<LLFolderViewItem*>::const_iterator it = selectedItems.begin(); + const std::set<LLFolderViewItem*>::const_iterator it_end = selectedItems.end(); + LLConversationItem * conversationItem; + + for (; it != it_end; ++it) + { + conversationItem = static_cast<LLConversationItem *>((*it)->getViewModelItem()); + selected_uuids.push_back(conversationItem->getUUID()); + } +} +void LLIMFloaterContainer::doToSelected(const LLSD& userdata) +{ + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; + LLUUID currentSelectedUUID; + LLIMFloater * conversation; + + getSelectedUUIDs(selected_uuids); + conversation = LLIMFloater::findInstance(selected_uuids.front()); + + if(conversation && + static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem())->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + { + currentSelectedUUID = conversation->getOtherParticipantUUID(); + } + else + { + currentSelectedUUID = selected_uuids.front(); + } + + //Close the selected conversation + if(conversation && "close_conversation" == command) + { + LLFloater::onClickClose(conversation); + } + else if ("view_profile" == command) + { + LLAvatarActions::showProfile(currentSelectedUUID); + } + else if("im" == command) + { + LLAvatarActions::startIM(currentSelectedUUID); + } + else if("offer_teleport" == command) + { + LLAvatarActions::offerTeleport(selected_uuids); + } + else if("voice_call" == command) + { + LLAvatarActions::startCall(currentSelectedUUID); + } + else if("add_friend" == command) + { + LLAvatarActions::requestFriendshipDialog(currentSelectedUUID); + } + else if("remove_friend" == command) + { + LLAvatarActions::removeFriendDialog(currentSelectedUUID); + } + else if("invite_to_group" == command) + { + LLAvatarActions::inviteToGroup(currentSelectedUUID); + } + else if("map" == command) + { + LLAvatarActions::showOnMap(currentSelectedUUID); + } + else if("share" == command) + { + LLAvatarActions::share(currentSelectedUUID); + } + else if("pay" == command) + { + LLAvatarActions::pay(currentSelectedUUID); + } + else if("block_unblock" == command) + { + LLAvatarActions::toggleBlock(currentSelectedUUID); + } +} + +bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) +{ + std::string item = userdata.asString(); + uuid_vec_t mUUIDs; + getSelectedUUIDs(mUUIDs); + + // Note: can_block and can_delete is used only for one person selected menu + // so we don't need to go over all uuids. + + if (item == std::string("can_block")) + { + const LLUUID& id = mUUIDs.front(); + return LLAvatarActions::canBlock(id); + } + else if (item == std::string("can_add")) + { + // We can add friends if: + // - there are selected people + // - and there are no friends among selection yet. + + //EXT-7389 - disable for more than 1 + if(mUUIDs.size() > 1) + { + return false; + } + + bool result = (mUUIDs.size() > 0); + + uuid_vec_t::const_iterator + id = mUUIDs.begin(), + uuids_end = mUUIDs.end(); + + for (;id != uuids_end; ++id) + { + if ( LLAvatarActions::isFriend(*id) ) + { + result = false; + break; + } + } + + return result; + } + else if (item == std::string("can_delete")) + { + // We can remove friends if: + // - there are selected people + // - and there are only friends among selection. + + bool result = (mUUIDs.size() > 0); + + uuid_vec_t::const_iterator + id = mUUIDs.begin(), + uuids_end = mUUIDs.end(); + + for (;id != uuids_end; ++id) + { + if ( !LLAvatarActions::isFriend(*id) ) + { + result = false; + break; + } + } + + return result; + } + else if (item == std::string("can_call")) + { + return LLAvatarActions::canCall(); + } + else if (item == std::string("can_show_on_map")) + { + const LLUUID& id = mUUIDs.front(); + + return (LLAvatarTracker::instance().isBuddyOnline(id) && is_agent_mappable(id)) + || gAgent.isGodlike(); + } + else if(item == std::string("can_offer_teleport")) + { + return LLAvatarActions::canOfferTeleport(mUUIDs); + } + return false; +} + +bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata) +{ + std::string item = userdata.asString(); + const LLUUID& id = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem())->getUUID(); + + if (item == std::string("is_blocked")) + { + return LLAvatarActions::isBlocked(id); + } + + return false; +} + void LLIMFloaterContainer::repositioningWidgets() { if (!mInitialized) diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index e8d185297c..cc2d0ce6ab 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -111,6 +111,11 @@ private: void setSortOrderParticipants(const LLConversationFilter::ESortOrderType order); void setSortOrder(const LLConversationSort& order); + void getSelectedUUIDs(uuid_vec_t& selected_uuids); + void doToSelected(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); + bool enableContextMenuItem(const LLSD& userdata); + LLButton* mExpandCollapseBtn; LLLayoutPanel* mMessagesPane; LLLayoutPanel* mConversationsPane; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 2a84616ddf..6e692adf2a 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -172,6 +172,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id ) p.show_empty_message = mShowEmptyMessage; p.show_item_link_overlays = mShowItemLinkOverlays; p.root = NULL; + p.options_menu = "menu_inventory.xml"; return LLUICtrlFactory::create<LLFolderView>(p); } diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml new file mode 100644 index 0000000000..94399be61c --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + bottom="806" + layout="topleft" + left="0" + mouse_opaque="false" + name="menu_conversation_participant" + visible="false"> + <menu_item_call + label="Close conversation" + layout="topleft" + name="close_conversation"> + <on_click function="Avatar.DoToSelected" parameter="close_conversation"/> + </menu_item_call> + <menu_item_call + label="Open voice conversation" + layout="topleft" + name="open_voice_conversation"> + <on_click function="Avatar.DoToSelected" parameter="open_voice_conversation"/> + </menu_item_call> + <menu_item_call + label="Disconnect from voice" + layout="topleft" + name="disconnect_from_voice"> + <on_click function="Avatar.DoToSelected" parameter="disconnect_from_voice"/> + </menu_item_call> + <menu_item_separator layout="topleft" name="separator_disconnect_from_voice"/> + <menu_item_call + label="View Profile" + layout="topleft" + name="view_profile"> + <on_click function="Avatar.DoToSelected" parameter="view_profile"/> + </menu_item_call> + <menu_item_call + label="IM" + layout="topleft" + name="im"> + <on_click function="Avatar.DoToSelected" parameter="im"/> + </menu_item_call> + <menu_item_call + label="Offer teleport" + layout="topleft" + name="offer_teleport"> + <on_click function="Avatar.DoToSelected" parameter="offer_teleport"/> + <on_enable function="Avatar.EnableItem" parameter="can_offer_teleport"/> + </menu_item_call> + <menu_item_call + label="Voice call" + layout="topleft" + name="voice_call"> + <on_click function="Avatar.DoToSelected" parameter="voice_call"/> + <on_enable function="Avatar.EnableItem" parameter="can_call" /> + </menu_item_call> + <menu_item_call + label="Chat history..." + layout="topleft" + name="chat_history"> + <on_click function="Avatar.DoToSelected" parameter="chat_history"/> + </menu_item_call> + <menu_item_separator layout="topleft" name="separator_chat_history"/> + <menu_item_call + label="Add friend" + layout="topleft" + name="add_friend"> + <on_click function="Avatar.DoToSelected" parameter="add_friend"/> + <on_enable function="Avatar.EnableItem" parameter="can_add" /> + </menu_item_call> + <menu_item_call + label="Remove friend" + layout="topleft" + name="remove_friend"> + <on_click function="Avatar.DoToSelected" parameter="remove_friend" /> + <on_enable function="Avatar.EnableItem" parameter="can_delete" /> + </menu_item_call> + <menu_item_call + label="Invite to group..." + layout="topleft" + name="invite_to_group"> + <on_click function="Avatar.DoToSelected" parameter="invite_to_group" /> + </menu_item_call> + <menu_item_separator layout="topleft" name="separator_invite_to_group"/> + <menu_item_call + label="Map" + layout="topleft" + name="map"> + <on_click function="Avatar.DoToSelected" parameter="map" /> + <on_enable function="Avatar.EnableItem" parameter="can_show_on_map" /> + </menu_item_call> + <menu_item_call + label="Share" + layout="topleft" + name="share"> + <on_click function="Avatar.DoToSelected" parameter="share" /> + </menu_item_call> + <menu_item_call + label="Pay" + layout="topleft" + name="pay"> + <on_click function="Avatar.DoToSelected" parameter="pay" /> + </menu_item_call> + <menu_item_check + label="Block / unblock" + layout="topleft" + name="block_unblock"> + <on_click function="Avatar.DoToSelected" parameter="block_unblock" /> + <on_check function="Avatar.CheckItem" parameter="is_blocked" /> + <on_enable function="Avatar.EnableItem" parameter="can_block" /> + </menu_item_check> +</toggleable_menu> -- cgit v1.2.3 From 5e6f224b5eb3591e9ecea981613cf64a2ce56b8a Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Mon, 1 Oct 2012 20:02:28 +0300 Subject: CHUI-368 FIXED Lock icon shown when clicking on items in inventory --- indra/llui/llfolderviewitem.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 5639c4d5a3..0b04288950 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -537,7 +537,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > drag_and_drop_threshold() * drag_and_drop_threshold() && root->getCurSelectedItem() && root->startDrag()) - { + { // RN: when starting drag and drop, clear out last auto-open root->autoOpenTest(NULL); root->setShowSelectionContext(TRUE); @@ -548,13 +548,13 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) gFocusMgr.setKeyboardFocus(NULL); getWindow()->setCursor(UI_CURSOR_ARROW); - return TRUE; - } - else + } + else if (x != mDragStartX || y != mDragStartY) { getWindow()->setCursor(UI_CURSOR_NOLOCKED); - return TRUE; } + + return TRUE; } else { -- cgit v1.2.3 From 8e1a9e2813da6b9d5c17795b375098fb6a386ee1 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 1 Oct 2012 13:54:53 -0700 Subject: CHUI-102: Cleaned up code after code review. --- indra/llui/llfolderview.cpp | 4 ++++ indra/llui/llfolderview.h | 2 +- indra/newview/llconversationmodel.cpp | 1 - indra/newview/llconversationmodel.h | 1 + indra/newview/llimfloater.h | 2 +- indra/newview/llimfloatercontainer.cpp | 9 ++++++++- 6 files changed, 15 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 327a064228..9a4a90206b 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1531,14 +1531,18 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) && menu ) { if (mCallbackRegistrar) + { mCallbackRegistrar->pushScope(); + } updateMenuOptions(menu); menu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(this, menu, x, y); if (mCallbackRegistrar) + { mCallbackRegistrar->popScope(); + } } else { diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 260275269d..487391a477 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -94,7 +94,7 @@ public: use_ellipses, show_item_link_overlays; Mandatory<LLFolderViewModelInterface*> view_model; - Optional<std::string> options_menu; + Mandatory<std::string> options_menu; Params(); diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 1c4c7aefae..f587ef8428 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -28,7 +28,6 @@ #include "llviewerprecompiledheaders.h" #include "llconversationmodel.h" -#include "llmenugl.h" // // Conversation items : common behaviors diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 43fa66e8e2..f84fbe39f1 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -285,6 +285,7 @@ private: // are set as enabled. //(defined in inventorybridge.cpp) +//TODO: Gilbert Linden - Refactor to make this function non-global void hide_context_entries(LLMenuGL& menu, const menuentry_vec_t &entries_to_show, const menuentry_vec_t &disabled_entries); diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index fbaf009939..489e430b26 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -128,7 +128,7 @@ public: static void onIMChicletCreated(const LLUUID& session_id); bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; } - LLUUID getOtherParticipantUUID() {return mOtherParticipantUUID;} + const LLUUID& getOtherParticipantUUID() {return mOtherParticipantUUID;} static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); static floater_showed_signal_t sIMFloaterShowedSignal; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index b4802c71f9..58d2020801 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -689,13 +689,20 @@ void LLIMFloaterContainer::doToSelected(const LLSD& userdata) LLIMFloater * conversation; getSelectedUUIDs(selected_uuids); + //Find the conversation floater associated with the selected id conversation = LLIMFloater::findInstance(selected_uuids.front()); - + + //When a one-on-one conversation exists, retrieve the participant id from the conversation floater b/c + //selected_uuids.front() does not pertain to the UUID of the person you are having the conversation with. if(conversation && + mConversationsRoot && + mConversationsRoot->getCurSelectedItem() && + mConversationsRoot->getCurSelectedItem()->getViewModelItem() && static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem())->getType() == LLConversationItem::CONV_SESSION_1_ON_1) { currentSelectedUUID = conversation->getOtherParticipantUUID(); } + //Otherwise can get the UUID directly from selected_uuids else { currentSelectedUUID = selected_uuids.front(); -- cgit v1.2.3 From 598f5345866c58abdd971935d80f9b53756042c9 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 1 Oct 2012 17:04:13 -0700 Subject: CHUI-102: Right clicking on a group conversation brings up the correct menu. The user can now view the group profile, activate the group and leave the group. --- indra/newview/llconversationmodel.cpp | 8 ++++ indra/newview/llimfloatercontainer.cpp | 48 ++++++++++++++++++---- indra/newview/llimfloatercontainer.h | 4 +- .../skins/default/xui/en/menu_conversation.xml | 18 ++++++++ 4 files changed, 69 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 265f77365f..3d1523c874 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -221,6 +221,14 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags) items.push_back(std::string("separator_disconnect_from_voice")); buildParticipantMenuOptions(items); } + else if(this->getType() == CONV_SESSION_GROUP) + { + items.push_back(std::string("close_conversation")); + items.push_back(std::string("separator_disconnect_from_voice")); + items.push_back(std::string("group_profile")); + items.push_back(std::string("activate_group")); + items.push_back(std::string("leave_group")); + } hide_context_entries(menu, items, disabled_items); } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index d25a195f33..b7f83e3c23 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -39,6 +39,7 @@ #include "llavatariconctrl.h" #include "llavatarnamecache.h" #include "llcallbacklist.h" +#include "llgroupactions.h" #include "llgroupiconctrl.h" #include "llfloateravatarpicker.h" #include "llfloaterpreference.h" @@ -63,7 +64,9 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLIMFloaterContainer::checkContextMenuItem, this, _2)); mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLIMFloaterContainer::enableContextMenuItem, this, _2)); - mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLIMFloaterContainer::doToSelected, this, _2)); + mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLIMFloaterContainer::doToSelectedAvatar, this, _2)); + + mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&LLIMFloaterContainer::doToSelectedGroup, this, _2)); // Firstly add our self to IMSession observers, so we catch session events LLIMMgr::getInstance()->addSessionObserver(this); @@ -731,7 +734,20 @@ void LLIMFloaterContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids) selected_uuids.push_back(conversationItem->getUUID()); } } -void LLIMFloaterContainer::doToSelected(const LLSD& userdata) + +const LLConversationItem * LLIMFloaterContainer::getCurSelectedViewModelItem() +{ + if(mConversationsRoot && + mConversationsRoot->getCurSelectedItem() && + mConversationsRoot->getCurSelectedItem()->getViewModelItem()) + { + return static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem()); + } + + return NULL; +} + +void LLIMFloaterContainer::doToSelectedAvatar(const LLSD& userdata) { std::string command = userdata.asString(); uuid_vec_t selected_uuids; @@ -741,14 +757,11 @@ void LLIMFloaterContainer::doToSelected(const LLSD& userdata) getSelectedUUIDs(selected_uuids); //Find the conversation floater associated with the selected id conversation = LLIMFloater::findInstance(selected_uuids.front()); + const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); //When a one-on-one conversation exists, retrieve the participant id from the conversation floater b/c //selected_uuids.front() does not pertain to the UUID of the person you are having the conversation with. - if(conversation && - mConversationsRoot && - mConversationsRoot->getCurSelectedItem() && - mConversationsRoot->getCurSelectedItem()->getViewModelItem() && - static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem())->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + if(conversation && conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) { currentSelectedUUID = conversation->getOtherParticipantUUID(); } @@ -809,6 +822,25 @@ void LLIMFloaterContainer::doToSelected(const LLSD& userdata) } } +void LLIMFloaterContainer::doToSelectedGroup(const LLSD& userdata) +{ + std::string action = userdata.asString(); + LLUUID selected_group = getCurSelectedViewModelItem()->getUUID(); + + if (action == "group_profile") + { + LLGroupActions::show(selected_group); + } + else if (action == "activate_group") + { + LLGroupActions::activate(selected_group); + } + else if (action == "leave_group") + { + LLGroupActions::leave(selected_group); + } +} + bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) { std::string item = userdata.asString(); @@ -896,7 +928,7 @@ bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata) { std::string item = userdata.asString(); - const LLUUID& id = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem())->getUUID(); + const LLUUID& id = getCurSelectedViewModelItem()->getUUID(); if (item == std::string("is_blocked")) { diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 49a41e5cdd..9754f04fbe 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -112,7 +112,9 @@ private: void setSortOrder(const LLConversationSort& order); void getSelectedUUIDs(uuid_vec_t& selected_uuids); - void doToSelected(const LLSD& userdata); + const LLConversationItem * getCurSelectedViewModelItem(); + void doToSelectedAvatar(const LLSD& userdata); + void doToSelectedGroup(const LLSD& userdata); bool checkContextMenuItem(const LLSD& userdata); bool enableContextMenuItem(const LLSD& userdata); diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index 94399be61c..bf834ee9ff 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -25,6 +25,24 @@ <on_click function="Avatar.DoToSelected" parameter="disconnect_from_voice"/> </menu_item_call> <menu_item_separator layout="topleft" name="separator_disconnect_from_voice"/> + <menu_item_call + label="Group Profile" + layout="topleft" + name="group_profile"> + <on_click function="Group.DoToSelected" parameter="group_profile"/> + </menu_item_call> + <menu_item_call + label="Activate Group" + layout="topleft" + name="activate_group"> + <on_click function="Group.DoToSelected" parameter="activate_group"/> + </menu_item_call> + <menu_item_call + label="Leave Group" + layout="topleft" + name="leave_group"> + <on_click function="Group.DoToSelected" parameter="leave_group"/> + </menu_item_call> <menu_item_call label="View Profile" layout="topleft" -- cgit v1.2.3 From 1ed2915796f610ced2387f5c76b6d10cc508962f Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 2 Oct 2012 11:09:58 -0700 Subject: CHUI-102: Code cleanup, decoupling code and made specific methods for handling menu events for conversations or participants. --- indra/newview/llimfloatercontainer.cpp | 113 +++++++++++++++++++++------------ indra/newview/llimfloatercontainer.h | 5 +- 2 files changed, 76 insertions(+), 42 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index b7f83e3c23..ad77a7510c 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -64,7 +64,7 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLIMFloaterContainer::checkContextMenuItem, this, _2)); mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLIMFloaterContainer::enableContextMenuItem, this, _2)); - mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLIMFloaterContainer::doToSelectedAvatar, this, _2)); + mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLIMFloaterContainer::doToSelected, this, _2)); mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&LLIMFloaterContainer::doToSelectedGroup, this, _2)); @@ -747,78 +747,109 @@ const LLConversationItem * LLIMFloaterContainer::getCurSelectedViewModelItem() return NULL; } -void LLIMFloaterContainer::doToSelectedAvatar(const LLSD& userdata) -{ - std::string command = userdata.asString(); - uuid_vec_t selected_uuids; - LLUUID currentSelectedUUID; - LLIMFloater * conversation; - - getSelectedUUIDs(selected_uuids); - //Find the conversation floater associated with the selected id - conversation = LLIMFloater::findInstance(selected_uuids.front()); - const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); - - //When a one-on-one conversation exists, retrieve the participant id from the conversation floater b/c - //selected_uuids.front() does not pertain to the UUID of the person you are having the conversation with. - if(conversation && conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) - { - currentSelectedUUID = conversation->getOtherParticipantUUID(); - } - //Otherwise can get the UUID directly from selected_uuids - else - { - currentSelectedUUID = selected_uuids.front(); - } +void LLIMFloaterContainer::doToUsers(const std::string& command, uuid_vec_t selectedIDS) +{dd + LLUUID userID; + userID = selectedIDS.front(); - //Close the selected conversation - if(conversation && "close_conversation" == command) - { - LLFloater::onClickClose(conversation); - } - else if ("view_profile" == command) + if ("view_profile" == command) { - LLAvatarActions::showProfile(currentSelectedUUID); + LLAvatarActions::showProfile(userID); } else if("im" == command) { - LLAvatarActions::startIM(currentSelectedUUID); + LLAvatarActions::startIM(userID); } else if("offer_teleport" == command) { - LLAvatarActions::offerTeleport(selected_uuids); + LLAvatarActions::offerTeleport(selectedIDS); } else if("voice_call" == command) { - LLAvatarActions::startCall(currentSelectedUUID); + LLAvatarActions::startCall(userID); } else if("add_friend" == command) { - LLAvatarActions::requestFriendshipDialog(currentSelectedUUID); + LLAvatarActions::requestFriendshipDialog(userID); } else if("remove_friend" == command) { - LLAvatarActions::removeFriendDialog(currentSelectedUUID); + LLAvatarActions::removeFriendDialog(userID); } else if("invite_to_group" == command) { - LLAvatarActions::inviteToGroup(currentSelectedUUID); + LLAvatarActions::inviteToGroup(userID); } else if("map" == command) { - LLAvatarActions::showOnMap(currentSelectedUUID); + LLAvatarActions::showOnMap(userID); } else if("share" == command) { - LLAvatarActions::share(currentSelectedUUID); + LLAvatarActions::share(userID); } else if("pay" == command) { - LLAvatarActions::pay(currentSelectedUUID); + LLAvatarActions::pay(userID); } else if("block_unblock" == command) { - LLAvatarActions::toggleBlock(currentSelectedUUID); + LLAvatarActions::toggleBlock(userID); + } +} + +void LLIMFloaterContainer::doToSelectedParticipant(const std::string& command) +{ + uuid_vec_t selected_uuids; + getSelectedUUIDs(selected_uuids); + + doToUsers(command, selected_uuids); +} + +void LLIMFloaterContainer::doToSelectedConversation(const std::string& command) +{ + LLUUID participantID; + + //Find the conversation floater associated with the selected id + const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); + LLIMFloater *conversationFloater = LLIMFloater::findInstance(conversationItem->getUUID()); + + if(conversationFloater) + { + //When a one-on-one conversation exists, retrieve the participant id from the conversation floater b/c + //selected_uuids.front() does not pertain to the UUID of the person you are having the conversation with. + if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + { + participantID = conversationFloater->getOtherParticipantUUID(); + } + + //Close the selected conversation + if("close_conversation" == command) + { + LLFloater::onClickClose(conversationFloater); + } + else + { + uuid_vec_t selected_uuids; + selected_uuids.push_back(participantID); + doToUsers(command, selected_uuids); + } + } +} + +void LLIMFloaterContainer::doToSelected(const LLSD& userdata) +{ + std::string command = userdata.asString(); + const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); + + if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1 || + conversationItem->getType() == LLConversationItem::CONV_SESSION_GROUP) + { + doToSelectedConversation(command); + } + else + { + doToSelectedParticipant(command); } } diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 9754f04fbe..a622ddfc8c 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -113,7 +113,10 @@ private: void getSelectedUUIDs(uuid_vec_t& selected_uuids); const LLConversationItem * getCurSelectedViewModelItem(); - void doToSelectedAvatar(const LLSD& userdata); + void doToSelected(const LLSD& userdata); + void doToSelectedConversation(const std::string& command); + void doToSelectedParticipant(const std::string& command); + void doToUsers(const std::string& command, uuid_vec_t selectedIDS); void doToSelectedGroup(const LLSD& userdata); bool checkContextMenuItem(const LLSD& userdata); bool enableContextMenuItem(const LLSD& userdata); -- cgit v1.2.3 From 7ba6111d9149baea48869c2f30506581d2c6babf Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 2 Oct 2012 21:32:23 +0300 Subject: CHUI-190 (Remove the Voice Settings floater): removed the menu item "Communicate > Voice settings" and the FUI button (headphones) from the Toybox (Toolbox). I left a floater in the project to be able to reconnect it to a different location. --- indra/newview/app_settings/commands.xml | 10 ---------- indra/newview/skins/default/xui/en/menu_viewer.xml | 10 ---------- 2 files changed, 20 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 51211a8ce5..d4bbd84d0f 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -239,14 +239,4 @@ is_running_function="Floater.IsOpen" is_running_parameters="camera" /> - <command name="voice" - available_in_toybox="true" - icon="Command_Voice_Icon" - label_ref="Command_Voice_Label" - tooltip_ref="Command_Voice_Tooltip" - execute_function="Floater.ToggleOrBringToFront" - execute_parameters="voice_controls" - is_running_function="Floater.IsOpen" - is_running_parameters="voice_controls" - /> </commands> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index aa131035ed..4bbf253e4a 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -243,16 +243,6 @@ function="Agent.ToggleMicrophone" parameter="speak" /> </menu_item_check> - <menu_item_check - label="Voice settings..." - name="Nearby Voice"> - <menu_item_check.on_check - function="Floater.Visible" - parameter="voice_controls" /> - <menu_item_check.on_click - function="Floater.Toggle" - parameter="voice_controls" /> - </menu_item_check> <menu_item_check label="Voice morphing..." name="ShowVoice" -- cgit v1.2.3 From 9d989feede2dbef934cdc459b4758c024df862d6 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 2 Oct 2012 15:10:12 -0700 Subject: CHUI-102: Now the user can select a conversation and use the right-click-menu to enable/disable voice. --- indra/newview/llconversationmodel.cpp | 21 +++++++++++++++++++++ indra/newview/llconversationmodel.h | 1 + indra/newview/llimfloatercontainer.cpp | 13 +++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 3d1523c874..a3ec154ac6 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -28,6 +28,7 @@ #include "llviewerprecompiledheaders.h" #include "llconversationmodel.h" +#include "llimview.h" //For LLIMModel // // Conversation items : common behaviors @@ -224,15 +225,35 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags) else if(this->getType() == CONV_SESSION_GROUP) { items.push_back(std::string("close_conversation")); + addVoiceOptions(items); items.push_back(std::string("separator_disconnect_from_voice")); items.push_back(std::string("group_profile")); items.push_back(std::string("activate_group")); items.push_back(std::string("leave_group")); } + else if(this->getType() == CONV_SESSION_AD_HOC) + { + items.push_back(std::string("close_conversation")); + addVoiceOptions(items); + } hide_context_entries(menu, items, disabled_items); } +void LLConversationItemSession::addVoiceOptions(menuentry_vec_t& items) +{ + LLVoiceChannel* voice_channel = LLIMModel::getInstance() ? LLIMModel::getInstance()->getVoiceChannel(this->getUUID()) : NULL; + + if(voice_channel != LLVoiceChannel::getCurrentVoiceChannel()) + { + items.push_back(std::string("open_voice_conversation")); + } + else + { + items.push_back(std::string("disconnect_from_voice")); + } +} + // The time of activity of a session is the time of the most recent activity, session and participants included const bool LLConversationItemSession::getTime(F64& time) const { diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index f84fbe39f1..bc72cd96ea 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -160,6 +160,7 @@ public: bool isLoaded() { return mIsLoaded; } void buildContextMenu(LLMenuGL& menu, U32 flags); + void addVoiceOptions(menuentry_vec_t& items); virtual const bool getTime(F64& time) const; void dumpDebugData(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index ad77a7510c..7130926212 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -748,7 +748,7 @@ const LLConversationItem * LLIMFloaterContainer::getCurSelectedViewModelItem() } void LLIMFloaterContainer::doToUsers(const std::string& command, uuid_vec_t selectedIDS) -{dd +{ LLUUID userID; userID = selectedIDS.front(); @@ -828,6 +828,14 @@ void LLIMFloaterContainer::doToSelectedConversation(const std::string& command) { LLFloater::onClickClose(conversationFloater); } + else if("open_voice_conversation" == command) + { + gIMMgr->startCall(conversationItem->getUUID()); + } + else if("disconnect_from_voice" == command) + { + gIMMgr->endCall(conversationItem->getUUID()); + } else { uuid_vec_t selected_uuids; @@ -843,7 +851,8 @@ void LLIMFloaterContainer::doToSelected(const LLSD& userdata) const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1 || - conversationItem->getType() == LLConversationItem::CONV_SESSION_GROUP) + conversationItem->getType() == LLConversationItem::CONV_SESSION_GROUP || + conversationItem->getType() == LLConversationItem::CONV_SESSION_AD_HOC) { doToSelectedConversation(command); } -- cgit v1.2.3 From ed9ade7d50b699ac60eb69a979ea32a60eefa630 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 2 Oct 2012 17:03:46 -0700 Subject: CHUI-102: Now the options menu (right-click menu) for a participant/conversation will open the 'Chat history' dialog when selected. --- indra/newview/llconversationmodel.cpp | 4 ++- indra/newview/llimfloatercontainer.cpp | 8 +++++ .../skins/default/xui/en/menu_conversation.xml | 36 +++++++++++----------- 3 files changed, 29 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index a3ec154ac6..5fc305da81 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -226,7 +226,8 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags) { items.push_back(std::string("close_conversation")); addVoiceOptions(items); - items.push_back(std::string("separator_disconnect_from_voice")); + items.push_back(std::string("chat_history")); + items.push_back(std::string("separator_chat_history")); items.push_back(std::string("group_profile")); items.push_back(std::string("activate_group")); items.push_back(std::string("leave_group")); @@ -235,6 +236,7 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags) { items.push_back(std::string("close_conversation")); addVoiceOptions(items); + items.push_back(std::string("chat_history")); } hide_context_entries(menu, items, disabled_items); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 7130926212..11aecde6e2 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -768,6 +768,10 @@ void LLIMFloaterContainer::doToUsers(const std::string& command, uuid_vec_t sele { LLAvatarActions::startCall(userID); } + else if("chat_history" == command) + { + LLAvatarActions::viewChatHistory(userID); + } else if("add_friend" == command) { LLAvatarActions::requestFriendshipDialog(userID); @@ -836,6 +840,10 @@ void LLIMFloaterContainer::doToSelectedConversation(const std::string& command) { gIMMgr->endCall(conversationItem->getUUID()); } + else if("chat_history" == command) + { + LLAvatarActions::viewChatHistory(conversationItem->getUUID()); + } else { uuid_vec_t selected_uuids; diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index bf834ee9ff..912ff811d9 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -25,24 +25,6 @@ <on_click function="Avatar.DoToSelected" parameter="disconnect_from_voice"/> </menu_item_call> <menu_item_separator layout="topleft" name="separator_disconnect_from_voice"/> - <menu_item_call - label="Group Profile" - layout="topleft" - name="group_profile"> - <on_click function="Group.DoToSelected" parameter="group_profile"/> - </menu_item_call> - <menu_item_call - label="Activate Group" - layout="topleft" - name="activate_group"> - <on_click function="Group.DoToSelected" parameter="activate_group"/> - </menu_item_call> - <menu_item_call - label="Leave Group" - layout="topleft" - name="leave_group"> - <on_click function="Group.DoToSelected" parameter="leave_group"/> - </menu_item_call> <menu_item_call label="View Profile" layout="topleft" @@ -124,4 +106,22 @@ <on_check function="Avatar.CheckItem" parameter="is_blocked" /> <on_enable function="Avatar.EnableItem" parameter="can_block" /> </menu_item_check> + <menu_item_call + label="Group Profile" + layout="topleft" + name="group_profile"> + <on_click function="Group.DoToSelected" parameter="group_profile"/> + </menu_item_call> + <menu_item_call + label="Activate Group" + layout="topleft" + name="activate_group"> + <on_click function="Group.DoToSelected" parameter="activate_group"/> + </menu_item_call> + <menu_item_call + label="Leave Group" + layout="topleft" + name="leave_group"> + <on_click function="Group.DoToSelected" parameter="leave_group"/> + </menu_item_call> </toggleable_menu> -- cgit v1.2.3 From 7e1fbd1a897e3238a101f1db2d155f0493beaac5 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 2 Oct 2012 17:56:01 -0700 Subject: CHUI-102: Code review, just changed function getCurSelectedViewModelItem() to have a single return statement. --- indra/newview/llimfloatercontainer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 11aecde6e2..a33fc2c57e 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -737,14 +737,16 @@ void LLIMFloaterContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids) const LLConversationItem * LLIMFloaterContainer::getCurSelectedViewModelItem() { + LLConversationItem * conversationItem = NULL; + if(mConversationsRoot && mConversationsRoot->getCurSelectedItem() && mConversationsRoot->getCurSelectedItem()->getViewModelItem()) { - return static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem()); + conversationItem = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem()); } - return NULL; + return conversationItem; } void LLIMFloaterContainer::doToUsers(const std::string& command, uuid_vec_t selectedIDS) -- cgit v1.2.3 From a8159facdeb478abf094d8ba8ad229c0e282f9f6 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 2 Oct 2012 19:36:46 +0300 Subject: CHUI-374 FIXED (Nearby chat is torn off and cannot be docked if nearby chat is received while conversation floater is closed) Nearby_chat is created only after the creation of the im_container --- indra/newview/llimfloater.cpp | 28 +++++++++++++++------------- indra/newview/llimfloatercontainer.cpp | 11 ++++++++--- indra/newview/llnearbychat.cpp | 16 +++++++++++++++- indra/newview/llnearbychat.h | 5 +++++ indra/newview/llnearbychathandler.cpp | 1 + indra/newview/llviewerfloaterreg.cpp | 2 +- 6 files changed, 45 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index d11504d312..99337bd5f3 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -111,23 +111,25 @@ void LLIMFloater::onClickCloseBtn() { LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); - if (session == NULL) + if (session != NULL) { - llwarns << "Empty session with id: " << (mSessionID.asString()) << llendl; - return; - } + bool is_call_with_chat = session->isGroupSessionType() + || session->isAdHocSessionType() || session->isP2PSessionType(); - bool is_call_with_chat = session->isGroupSessionType() - || session->isAdHocSessionType() || session->isP2PSessionType(); + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - - if (is_call_with_chat && voice_channel != NULL - && voice_channel->isActive()) + if (is_call_with_chat && voice_channel != NULL + && voice_channel->isActive()) + { + LLSD payload; + payload["session_id"] = mSessionID; + LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); + return; + } + } + else { - LLSD payload; - payload["session_id"] = mSessionID; - LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); + llwarns << "Empty session with id: " << (mSessionID.asString()) << llendl; return; } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index a33fc2c57e..237748179c 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -463,21 +463,26 @@ void LLIMFloaterContainer::tabClose() } void LLIMFloaterContainer::setVisible(BOOL visible) -{ +{ LLNearbyChat* nearby_chat; if (visible) { // Make sure we have the Nearby Chat present when showing the conversation container - LLIMConversation* nearby_chat = LLFloaterReg::findTypedInstance<LLIMConversation>("nearby_chat"); + nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); if (nearby_chat == NULL) { // If not found, force the creation of the nearby chat conversation panel // *TODO: find a way to move this to XML as a default panel or something like that LLSD name("nearby_chat"); LLFloaterReg::toggleInstanceOrBringToFront(name); - LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat")->addToHost(); } } + nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); + if (nearby_chat && !nearby_chat->isHostSet()) + { + nearby_chat->addToHost(); + } + // We need to show/hide all the associated conversations that have been torn off // (and therefore, are not longer managed by the multifloater), // so that they show/hide with the conversations manager. diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 4b35092f2d..b96b486868 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -91,7 +91,8 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd) : LLIMConversation(llsd), //mOutputMonitor(NULL), mSpeakerMgr(NULL), - mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) + mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT), + mIsHostSet(false) { mIsP2PChat = false; mIsNearbyChat = true; @@ -100,6 +101,12 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd) mSessionID = LLUUID(); } +//static +LLNearbyChat* LLNearbyChat::buildFloater(const LLSD& key) +{ + LLFloaterReg::getInstance("im_container"); + return new LLNearbyChat(key); +} //virtual BOOL LLNearbyChat::postBuild() @@ -304,9 +311,16 @@ void LLNearbyChat::addToHost() setHost(NULL); } } + + mIsHostSet = true; } } +bool LLNearbyChat::isHostSet() +{ + return mIsHostSet; +} + // virtual void LLNearbyChat::onOpen(const LLSD& key) { diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 3987212e4c..93168ba96a 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -48,6 +48,8 @@ public: LLNearbyChat(const LLSD& key = LLSD(LLUUID())); ~LLNearbyChat() {} + static LLNearbyChat* buildFloater(const LLSD& key); + /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); @@ -76,6 +78,8 @@ public: static void startChat(const char* line); static void stopChat(); + bool isHostSet(); + static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate); static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); @@ -117,6 +121,7 @@ private: LLHandle<LLView> mPopupMenuHandle; std::vector<LLChat> mMessageArchive; + bool mIsHostSet; }; #endif diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index f3e17ea61b..7834f6d320 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -487,6 +487,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, if(chat_msg.mText.empty()) return;//don't process empty messages + LLFloaterReg::getInstance("im_container"); LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); // Build notification data diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 4cd5ecc754..c751550523 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -194,7 +194,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>); LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatVoiceVolume>); - LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>); + LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLNearbyChat::buildFloater); LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>); LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>); -- cgit v1.2.3 From 4a25ce8b9d5d56b160d0d13c4681cd916c4ea4e0 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 2 Oct 2012 22:34:44 -0700 Subject: CHUI-341 : Implement the use of LLEventStream and LLEventPump to signal conversation model changes, picked by LLIMFloaterContainer. Suppress pooling on draw(). --- indra/newview/llconversationmodel.cpp | 16 +++++++++++++ indra/newview/llconversationmodel.h | 2 ++ indra/newview/llimfloatercontainer.cpp | 41 +++++++++++++++++++++++++--------- indra/newview/llimfloatercontainer.h | 3 +++ 4 files changed, 52 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 9fa8758d11..1057dbaf31 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" +#include "llevents.h" #include "llconversationmodel.h" // @@ -63,6 +64,18 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod { } +void LLConversationItem::postEvent(const std::string& event_type) +{ + LLSD event; + event["pump"] = "ConversationModelEvent"; + LLSD payload; + payload["type"] = event_type; + payload["name"] = getName(); + payload["uuid"] = getUUID(); + event["payload"] = payload; + LLEventPumps::instance().obtain("ConversationsEvents").post(event); +} + // Virtual action callbacks void LLConversationItem::performAction(LLInventoryModel* model, std::string action) { @@ -111,12 +124,14 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa addChild(participant); mIsLoaded = true; mNeedsRefresh = true; + postEvent("add_participant"); } void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* participant) { removeChild(participant); mNeedsRefresh = true; + postEvent("remove_participant"); } void LLConversationItemSession::removeParticipant(const LLUUID& participant_id) @@ -254,6 +269,7 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam mName = (av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername); mDisplayName = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); mNeedsRefresh = true; + postEvent("update_participant"); if (mParent) { mParent->requestSort(); diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 30f94d51ae..97e5b0fc31 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -124,6 +124,8 @@ public: void resetRefresh() { mNeedsRefresh = false; } bool needsRefresh() { return mNeedsRefresh; } + void postEvent(const std::string& event_type); + protected: std::string mName; // Name of the session or the participant LLUUID mUUID; // UUID of the session or the participant diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 6f7eb7822a..8642eaf5e1 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -49,6 +49,7 @@ #include "llcallbacklist.h" #include "llworld.h" +#include "llsdserialize.h" // // LLIMFloaterContainer // @@ -56,6 +57,7 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) : LLMultiFloater(seed), mExpandCollapseBtn(NULL), mConversationsRoot(NULL), + mStream("ConversationsEvents"), mInitialized(false) { mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLIMFloaterContainer::onCustomAction, this, _2)); @@ -136,6 +138,9 @@ BOOL LLIMFloaterContainer::postBuild() p.use_ellipses = true; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); + // Add listener to conversation model events + mStream.listen("ConversationsRefresh", boost::bind(&LLIMFloaterContainer::onConversationModelEvent, this, _1)); + // a scroller for folder view LLRect scroller_view_rect = mConversationsListPanel->getRect(); scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); @@ -378,18 +383,29 @@ void LLIMFloaterContainer::idle(void* user_data) self->mConversationsRoot->update(); } -void LLIMFloaterContainer::draw() +bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) { - // CHUI Notes - // Currently, the model is not responsible for creating the view which is a good thing. This means that + // For debug only + //std::ostringstream llsd_value; + //llsd_value << LLSDOStreamer<LLSDNotationFormatter>(event) << std::endl; + //llinfos << "Merov debug : onConversationModelEvent, event = " << llsd_value.str() << llendl; + // end debug + + // Note: In conversations, the model is not responsible for creating the view which is a good thing. This means that // the model could change substantially and the view could decide to echo only a portion of this model. // Consequently, the participant views need to be created either by the session view or by the container panel. - // For the moment, we create them here (which makes for complicated code...) to conform to the pattern - // implemented in llinventorypanel.cpp (see LLInventoryPanel::buildNewViews()). - // The best however would be to have an observer on the model so that we would not pool on each draw to know - // if the view needs refresh. The current implementation (testing for change on draw) is less - // efficient perf wise than a listener/observer scheme. We will implement that shortly. - + // For the moment, we create them here to conform to the pattern implemented in llinventorypanel.cpp + // (see LLInventoryPanel::buildNewViews()). + + // Note: For the moment, we're not very smart about the event paramter and we just refresh the whole set of views/widgets + // according to the current state of the whole model. + // We should at least analyze the event payload and do things differently for a handful of useful cases: + // - add session or participant + // - remove session or participant + // - update session or participant (e.g. rename, change sort order, etc...) + // see LLConversationItem::postEvent() for the payload formatting. + // *TODO: Add handling for various event signatures (add, remove, update, resort) + // On each session in mConversationsItems for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) { @@ -418,7 +434,7 @@ void LLIMFloaterContainer::draw() participant_view->setVisible(TRUE); } else - // Else, see if it needs refresh + // Else, see if it needs refresh { if (participant_model->needsRefresh()) { @@ -434,6 +450,11 @@ void LLIMFloaterContainer::draw() } } + return false; +} + +void LLIMFloaterContainer::draw() +{ if (mTabContainer->getTabCount() == 0) { // Do not close the container when every conversation is torn off because the user diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 2debc2455b..8e953025bc 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -31,6 +31,7 @@ #include <vector> #include "llimview.h" +#include "llevents.h" #include "llfloater.h" #include "llmultifloater.h" #include "llavatarpropertiesprocessor.h" @@ -130,6 +131,7 @@ public: private: LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item); + bool onConversationModelEvent(const LLSD& event); // Conversation list data LLPanel* mConversationsListPanel; // This is the main widget we add conversation widget to @@ -137,6 +139,7 @@ private: conversations_widgets_map mConversationsWidgets; LLConversationViewModel mConversationViewModel; LLFolderView* mConversationsRoot; + LLEventStream mStream; }; #endif // LL_LLIMFLOATERCONTAINER_H -- cgit v1.2.3 From 2c15f6eca629e65c9c87dc87e4da59718aada039 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Wed, 3 Oct 2012 13:30:17 +0300 Subject: CHUI-354 FIXED getIconOverlay() is added for LLItemBridge --- indra/newview/llinventorybridge.cpp | 9 +++++++++ indra/newview/llinventorybridge.h | 1 + 2 files changed, 10 insertions(+) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 72c54e5ce2..139713b96e 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1531,6 +1531,15 @@ LLUIImagePtr LLItemBridge::getIcon() const return LLInventoryIcon::getIcon(LLInventoryIcon::ICONNAME_OBJECT); } +LLUIImagePtr LLItemBridge::getIconOverlay() const +{ + if (getItem() && getItem()->getIsLinkType()) + { + return LLUI::getUIImage("Inv_Link"); + } + return NULL; +} + PermissionMask LLItemBridge::getPermissionMask() const { LLViewerInventoryItem* item = getItem(); diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 6beccf19ae..b33972167c 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -228,6 +228,7 @@ public: virtual BOOL isItemCopyable() const; virtual bool hasChildren() const { return FALSE; } virtual BOOL isUpToDate() const { return TRUE; } + virtual LLUIImagePtr getIconOverlay() const; LLViewerInventoryItem* getItem() const; -- cgit v1.2.3 From bb2f48cb93a142deed863287d009017177e6a0be Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Wed, 3 Oct 2012 13:55:09 +0300 Subject: CHUI-301 FIXED Tooltips for buttons are added --- indra/newview/skins/default/xui/en/floater_conversation_log.xml | 2 ++ .../newview/skins/default/xui/en/panel_conversation_log_list_item.xml | 3 +++ 2 files changed, 5 insertions(+) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml index 12d17e6b37..c9c52e5ce5 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -49,6 +49,7 @@ menu_filename="menu_conversation_log_view.xml" menu_position="bottomleft" name="conversation_view_btn" + tool_tip="View/sort options" top="3" width="31" /> <menu_button @@ -61,6 +62,7 @@ layout="topleft" left_pad="2" name="conversations_gear_btn" + tool_tip="Actions on selected person or group" top="3" width="31" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml index 8a58eb1ca6..78d4c174d2 100644 --- a/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml @@ -35,6 +35,7 @@ image_name="Conv_toolbar_open_call" mouse_opaque="true" name="voice_session_icon" + tool_tip="Included a voice conversation" top="2" visible="false" width="20" /> @@ -46,6 +47,7 @@ image_name="Conv_log_inbox" mouse_opaque="false" name="unread_ims_icon" + tool_tip="Messages arrived while you were logged out" top="2" visible="false" width="20" /> @@ -92,6 +94,7 @@ width="110"/> <button name="delete_btn" + tool_tip="Remove this entry" layout="topleft" follows="top|right" image_unselected="Conv_toolbar_close" -- cgit v1.2.3 From 7535d3b5daa235540bbd5f0e784fc3fba484d614 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Wed, 3 Oct 2012 14:07:01 +0300 Subject: CHUI-322 FIXED Call SideTray.PanelPeopleTab with parameter="blocked_panel" instead of Communicate.BlockList --- indra/newview/llviewermenu.cpp | 16 ++-------------- indra/newview/skins/default/xui/en/menu_viewer.xml | 3 ++- 2 files changed, 4 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index a993d195b5..6da9296ea3 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3466,7 +3466,8 @@ class LLTogglePanelPeopleTab : public view_listener_t if ( panel_name == "friends_panel" || panel_name == "groups_panel" - || panel_name == "nearby_panel") + || panel_name == "nearby_panel" + || panel_name == "blocked_panel") { return togglePeoplePanel(panel_name, param); } @@ -5490,16 +5491,6 @@ void toggle_debug_menus(void*) // gExportDialog = LLUploadDialog::modalUploadDialog("Exporting selected objects..."); // } // - -class LLCommunicateBlockList : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); - return true; - } -}; - class LLWorldSetHomeLocation : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -8290,9 +8281,6 @@ void initialize_menus() // Me > Movement view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying"); - // Communicate - view_listener_t::addMenu(new LLCommunicateBlockList(), "Communicate.BlockList"); - // World menu view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun"); view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark"); diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 4bbf253e4a..88b30c8272 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -294,7 +294,8 @@ label="Block List" name="Block List"> <menu_item_call.on_click - function="Communicate.BlockList" /> + function="SideTray.PanelPeopleTab" + parameter="blocked_panel" /> </menu_item_call> </menu> <menu -- cgit v1.2.3 From 7f3f5cc408d7b36478c7dd707e32f921c1e1b720 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 3 Oct 2012 16:56:27 +0300 Subject: CHUI-378 FIXED (Conversation floater is not opened if call initiated and accepted with conversation floater closed - goes to voice settings floater): added open conversation floater on the voice channel's changing --- indra/newview/llappviewer.cpp | 3 ++- indra/newview/llcallfloater.cpp | 3 ++- indra/newview/llcallfloater.h | 4 ++-- indra/newview/llimfloatercontainer.cpp | 10 ++++++++++ indra/newview/llimfloatercontainer.h | 4 ++-- 5 files changed, 18 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 08a1a237f5..6b15e4b21a 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -42,6 +42,7 @@ #include "llagentcamera.h" #include "llagentlanguage.h" #include "llagentwearables.h" +#include "llimfloatercontainer.h" #include "llwindow.h" #include "llviewerstats.h" #include "llviewerstatsrecorder.h" @@ -1204,7 +1205,7 @@ bool LLAppViewer::mainLoop() LLVoiceChannel::initClass(); LLVoiceClient::getInstance()->init(gServicePump); - LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1), true); + LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLIMFloaterContainer::onCurrentChannelChanged, _1), true); LLTimer frameTimer,idleTimer; LLTimer debugTime; LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index 38b755004c..e767609d74 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -364,7 +364,8 @@ void LLCallFloater::onAvatarListRefreshed() } // static -void LLCallFloater::sOnCurrentChannelChanged(const LLUUID& /*session_id*/) +// This entry point now disable, but left for later use. +void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/) { LLVoiceChannel* channel = LLVoiceChannel::getCurrentVoiceChannel(); diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index 181c92276d..e1c7b3f43a 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -74,7 +74,7 @@ public: */ /*virtual*/ void onParticipantsChanged(); - static void sOnCurrentChannelChanged(const LLUUID& session_id); + static void onCurrentChannelChanged(const LLUUID& session_id); private: typedef enum e_voice_controls_type @@ -260,7 +260,7 @@ private: * * Is used to ignore voice channel changed callback for the same channel. * - * @see sOnCurrentChannelChanged() + * @see onCurrentChannelChanged() */ static LLVoiceChannel* sCurrentVoiceChannel; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 237748179c..5a323583b8 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -114,6 +114,16 @@ void LLIMFloaterContainer::sessionRemoved(const LLUUID& session_id) removeConversationListItem(session_id); } +// static +void LLIMFloaterContainer::onCurrentChannelChanged(const LLUUID& session_id) +{ + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } +} + + BOOL LLIMFloaterContainer::postBuild() { mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLIMFloaterContainer::onNewMessageReceived, this, _1)); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index a622ddfc8c..081c733884 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -66,11 +66,11 @@ public: /*virtual*/ void tabClose(); static LLFloater* getCurrentVoiceFloater(); - static LLIMFloaterContainer* findInstance(); - static LLIMFloaterContainer* getInstance(); + static void onCurrentChannelChanged(const LLUUID& session_id); + virtual void setMinimized(BOOL b); void collapseMessagesPane(bool collapse); -- cgit v1.2.3 From 9c3bbd378332a3dca8c58d0e3e351fd038e3f61b Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 3 Oct 2012 14:31:13 -0700 Subject: CHUI-102: Now the options enabled in the one-on-one conversation menu are the same as the participants menu. In prior commits the one-on-one conversations menu was not enabling/disabling the proper menu options. --- indra/newview/llimfloatercontainer.cpp | 75 +++++++++++++++++++--------------- indra/newview/llimfloatercontainer.h | 6 +-- 2 files changed, 46 insertions(+), 35 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 5a323583b8..4af170b3db 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -764,10 +764,29 @@ const LLConversationItem * LLIMFloaterContainer::getCurSelectedViewModelItem() return conversationItem; } -void LLIMFloaterContainer::doToUsers(const std::string& command, uuid_vec_t selectedIDS) +void LLIMFloaterContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) { - LLUUID userID; - userID = selectedIDS.front(); + //Find the conversation floater associated with the selected id + const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); + + if(conversationItem->getType() == LLConversationItem::CONV_PARTICIPANT) + { + getSelectedUUIDs(selected_uuids); + } + //When a one-on-one conversation exists, retrieve the participant id from the conversation floater + else if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + { + LLIMFloater *conversationFloater = LLIMFloater::findInstance(conversationItem->getUUID()); + LLUUID participantID = conversationFloater->getOtherParticipantUUID(); + selected_uuids.push_back(participantID); + } +} + +void LLIMFloaterContainer::doToParticipants(const std::string& command, uuid_vec_t& selectedIDS) +{ + if(selectedIDS.size() > 0) +{ + const LLUUID userID = selectedIDS.front(); if ("view_profile" == command) { @@ -818,32 +837,16 @@ void LLIMFloaterContainer::doToUsers(const std::string& command, uuid_vec_t sele LLAvatarActions::toggleBlock(userID); } } - -void LLIMFloaterContainer::doToSelectedParticipant(const std::string& command) -{ - uuid_vec_t selected_uuids; - getSelectedUUIDs(selected_uuids); - - doToUsers(command, selected_uuids); } -void LLIMFloaterContainer::doToSelectedConversation(const std::string& command) +void LLIMFloaterContainer::doToSelectedConversation(const std::string& command, uuid_vec_t& selectedIDS) { - LLUUID participantID; - //Find the conversation floater associated with the selected id const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); LLIMFloater *conversationFloater = LLIMFloater::findInstance(conversationItem->getUUID()); if(conversationFloater) { - //When a one-on-one conversation exists, retrieve the participant id from the conversation floater b/c - //selected_uuids.front() does not pertain to the UUID of the person you are having the conversation with. - if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) - { - participantID = conversationFloater->getOtherParticipantUUID(); - } - //Close the selected conversation if("close_conversation" == command) { @@ -863,9 +866,7 @@ void LLIMFloaterContainer::doToSelectedConversation(const std::string& command) } else { - uuid_vec_t selected_uuids; - selected_uuids.push_back(participantID); - doToUsers(command, selected_uuids); + doToParticipants(command, selectedIDS); } } } @@ -874,16 +875,17 @@ void LLIMFloaterContainer::doToSelected(const LLSD& userdata) { std::string command = userdata.asString(); const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); + uuid_vec_t selected_uuids; + + getParticipantUUIDs(selected_uuids); - if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1 || - conversationItem->getType() == LLConversationItem::CONV_SESSION_GROUP || - conversationItem->getType() == LLConversationItem::CONV_SESSION_AD_HOC) + if(conversationItem->getType() == LLConversationItem::CONV_PARTICIPANT) { - doToSelectedConversation(command); + doToParticipants(command, selected_uuids); } else { - doToSelectedParticipant(command); + doToSelectedConversation(command, selected_uuids); } } @@ -910,7 +912,12 @@ bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) { std::string item = userdata.asString(); uuid_vec_t mUUIDs; - getSelectedUUIDs(mUUIDs); + getParticipantUUIDs(mUUIDs); + + if(mUUIDs.size() <= 0) + { + return false; + } // Note: can_block and can_delete is used only for one person selected menu // so we don't need to go over all uuids. @@ -932,7 +939,7 @@ bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) return false; } - bool result = (mUUIDs.size() > 0); + bool result = true; uuid_vec_t::const_iterator id = mUUIDs.begin(), @@ -993,11 +1000,15 @@ bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata) { std::string item = userdata.asString(); - const LLUUID& id = getCurSelectedViewModelItem()->getUUID(); + uuid_vec_t mUUIDs; + getParticipantUUIDs(mUUIDs); + if(mUUIDs.size() > 0 ) + { if (item == std::string("is_blocked")) { - return LLAvatarActions::isBlocked(id); + return LLAvatarActions::isBlocked(mUUIDs.front()); + } } return false; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 081c733884..76e468f979 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -113,10 +113,10 @@ private: void getSelectedUUIDs(uuid_vec_t& selected_uuids); const LLConversationItem * getCurSelectedViewModelItem(); + void getParticipantUUIDs(uuid_vec_t& selected_uuids); void doToSelected(const LLSD& userdata); - void doToSelectedConversation(const std::string& command); - void doToSelectedParticipant(const std::string& command); - void doToUsers(const std::string& command, uuid_vec_t selectedIDS); + void doToSelectedConversation(const std::string& command, uuid_vec_t& selectedIDS); + void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS); void doToSelectedGroup(const LLSD& userdata); bool checkContextMenuItem(const LLSD& userdata); bool enableContextMenuItem(const LLSD& userdata); -- cgit v1.2.3 From efd8910069a01d8440e45f350979054f88e794cb Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Thu, 4 Oct 2012 00:57:43 +0300 Subject: CHUI-331 FIXED (Resizing conversation list when message panel is collapsed does not resize list) --- indra/llui/lllayoutstack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 4c730286da..be6d359c9a 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -767,7 +767,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& { // freeze new size as fraction F32 new_fractional_size = (updated_auto_resize_headroom == 0.f) ? MAX_FRACTIONAL_SIZE - : llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); + : llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim() - 1) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); fraction_given_up -= new_fractional_size - panelp->mFractionalSize; fraction_remaining -= panelp->mFractionalSize; panelp->mFractionalSize = new_fractional_size; -- cgit v1.2.3 From f2510ca0d629a2cd6cd85588698672f5a0c4e64a Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Thu, 4 Oct 2012 02:26:48 +0300 Subject: CHUI-165 FIXED Add access to Conversation Log and Chat History from the People floater: the 'View Chat History' action was updated; --- indra/newview/llavataractions.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index a76dbcac53..248685b964 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -42,6 +42,7 @@ #include "llappviewer.h" // for gLastVersionChannel #include "llcachename.h" #include "llcallingcard.h" // for LLAvatarTracker +#include "llconversationlog.h" #include "llfloateravatarpicker.h" // for LLFloaterAvatarPicker #include "llfloatergroupinvite.h" #include "llfloatergroups.h" @@ -900,7 +901,17 @@ void LLAvatarActions::inviteToGroup(const LLUUID& id) // static void LLAvatarActions::viewChatHistory(const LLUUID& id) { - LLFloaterReg::showInstance("preview_conversation", id, true); + const std::vector<LLConversation>& conversations = LLConversationLog::instance().getConversations(); + std::vector<LLConversation>::const_iterator iter = conversations.begin(); + + for (; iter != conversations.end(); ++iter) + { + if (iter->getParticipantID() == id) + { + LLFloaterReg::showInstance("preview_conversation", iter->getSessionID(), true); + break; + } + } } //== private methods ======================================================================================== -- cgit v1.2.3 From bd64c483639ae33518609398fce7c51ddc73dae7 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 3 Oct 2012 16:46:46 -0700 Subject: CHUI-358 : Fixed the removal of participants as they leave conversations. Used the event mechanism for this. --- indra/newview/llconversationmodel.cpp | 18 ++++++++---------- indra/newview/llconversationmodel.h | 2 +- indra/newview/llimfloatercontainer.cpp | 31 +++++++++++++++++++++++++------ 3 files changed, 34 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 1057dbaf31..7ddb725fb1 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -64,15 +64,13 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod { } -void LLConversationItem::postEvent(const std::string& event_type) +void LLConversationItem::postEvent(const std::string& event_type, LLConversationItemParticipant* participant) { LLSD event; - event["pump"] = "ConversationModelEvent"; - LLSD payload; - payload["type"] = event_type; - payload["name"] = getName(); - payload["uuid"] = getUUID(); - event["payload"] = payload; + event["type"] = event_type; + event["session_uuid"] = getUUID(); + event["participant_name"] = participant->getName(); + event["participant_uuid"] = participant->getUUID(); LLEventPumps::instance().obtain("ConversationsEvents").post(event); } @@ -124,14 +122,14 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa addChild(participant); mIsLoaded = true; mNeedsRefresh = true; - postEvent("add_participant"); + postEvent("add_participant", participant); } void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* participant) { removeChild(participant); mNeedsRefresh = true; - postEvent("remove_participant"); + postEvent("remove_participant", participant); } void LLConversationItemSession::removeParticipant(const LLUUID& participant_id) @@ -269,7 +267,7 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam mName = (av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername); mDisplayName = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); mNeedsRefresh = true; - postEvent("update_participant"); + postEvent("update_participant", this); if (mParent) { mParent->requestSort(); diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 97e5b0fc31..32280f3293 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -124,7 +124,7 @@ public: void resetRefresh() { mNeedsRefresh = false; } bool needsRefresh() { return mNeedsRefresh; } - void postEvent(const std::string& event_type); + void postEvent(const std::string& event_type, LLConversationItemParticipant* participant); protected: std::string mName; // Name of the session or the participant diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 8642eaf5e1..e58154b2a2 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -391,21 +391,39 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) //llinfos << "Merov debug : onConversationModelEvent, event = " << llsd_value.str() << llendl; // end debug - // Note: In conversations, the model is not responsible for creating the view which is a good thing. This means that - // the model could change substantially and the view could decide to echo only a portion of this model. + // Note: In conversations, the model is not responsible for creating the view, which is a good thing. This means that + // the model could change substantially and the view could echo only a portion of this model (though currently the + // conversation view does echo the conversation model 1 to 1). // Consequently, the participant views need to be created either by the session view or by the container panel. - // For the moment, we create them here to conform to the pattern implemented in llinventorypanel.cpp + // For the moment, we create them here, at the container level, to conform to the pattern implemented in llinventorypanel.cpp // (see LLInventoryPanel::buildNewViews()). - // Note: For the moment, we're not very smart about the event paramter and we just refresh the whole set of views/widgets + // Note: For the moment, we're not very smart about the event parameter and we just refresh the whole set of views/widgets // according to the current state of the whole model. - // We should at least analyze the event payload and do things differently for a handful of useful cases: + // We should at least analyze the event payload and do things differently for a handful of cases: // - add session or participant // - remove session or participant // - update session or participant (e.g. rename, change sort order, etc...) - // see LLConversationItem::postEvent() for the payload formatting. + // Please see LLConversationItem::postEvent() for the payload formatting. // *TODO: Add handling for various event signatures (add, remove, update, resort) + std::string type = event.get("type").asString(); + if (type == "remove_participant") + { + LLUUID session_id = event.get("session_uuid").asUUID(); + LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[session_id]); + LLUUID participant_id = event.get("participant_uuid").asUUID(); + LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); + if (participant_view) + { + session_view->extractItem(participant_view); + delete participant_view; + session_view->refresh(); + mConversationsRoot->arrangeAll(); + } + } + else + { // On each session in mConversationsItems for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) { @@ -449,6 +467,7 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) current_participant_model++; } } + } return false; } -- cgit v1.2.3 From 5d846e141464f02a1d896ffa82d639f973f8044b Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 3 Oct 2012 19:06:33 -0700 Subject: CHUI-341 : Fixed. Took Nat's review comments into account. --- indra/newview/llconversationmodel.cpp | 7 ++----- indra/newview/llimfloatercontainer.cpp | 2 ++ 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 0f29ffe77f..3c111c919a 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -28,6 +28,7 @@ #include "llviewerprecompiledheaders.h" #include "llevents.h" +#include "llsdutil.h" #include "llconversationmodel.h" #include "llimview.h" //For LLIMModel @@ -67,11 +68,7 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod void LLConversationItem::postEvent(const std::string& event_type, LLConversationItemParticipant* participant) { - LLSD event; - event["type"] = event_type; - event["session_uuid"] = getUUID(); - event["participant_name"] = participant->getName(); - event["participant_uuid"] = participant->getUUID(); + LLSD event(LLSDMap("type", event_type)("session_uuid", getUUID())("participant_name",participant->getName())("participant_uuid",participant->getUUID())); LLEventPumps::instance().obtain("ConversationsEvents").post(event); } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 36c39f5717..78bd90fb96 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -79,6 +79,8 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) LLIMFloaterContainer::~LLIMFloaterContainer() { + mStream.stopListening("ConversationsRefresh"); + gIdleCallbacks.deleteFunction(idle, this); mNewMessageConnection.disconnect(); -- cgit v1.2.3 From 8013e645603d1075b848ef91178af0fa3f9dc38c Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Thu, 4 Oct 2012 14:30:16 +0300 Subject: CHUI-313 FIXED "Conversations", "Conversations Log" menu items are added --- indra/newview/skins/default/xui/en/menu_viewer.xml | 25 ++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 88b30c8272..c805b6db42 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -218,8 +218,18 @@ label="Communicate" name="Communicate" tear_off="true"> - <menu_item_check - label="Chat..." + <menu_item_check + label="Conversations..." + name="Conversations"> + <menu_item_check.on_check + function="Floater.IsOpen" + parameter="im_container" /> + <menu_item_check.on_click + function="Floater.ToggleOrBringToFront" + parameter="im_container" /> + </menu_item_check> + <menu_item_check + label="Nearby Chat..." name="Nearby Chat" shortcut="control|H" use_mac_ctrl="true"> @@ -243,6 +253,17 @@ function="Agent.ToggleMicrophone" parameter="speak" /> </menu_item_check> + <menu_item_check + label="Conversations Log..." + name="ConversationsLog"> + <menu_item_check.on_check + function="Floater.Visible" + parameter="conversation" /> + <menu_item_check.on_click + function="Floater.Toggle" + parameter="conversation" /> + </menu_item_check> + <menu_item_separator/> <menu_item_check label="Voice morphing..." name="ShowVoice" -- cgit v1.2.3 From 050146ce5ef889d254624ee456f04703fce357d3 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Thu, 4 Oct 2012 14:53:36 +0300 Subject: CHUI-327 FIXED Set "left" property for chat_history element --- indra/newview/skins/default/xui/en/floater_im_session.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 5c74f7f9bb..8cd0463de8 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -246,7 +246,7 @@ parse_highlights="true" parse_urls="true" width="230" - left="0"> + left="5"> </chat_history> </layout_panel> </layout_stack> -- cgit v1.2.3 From 06a7bd27cb07bd692d02604dcce735122456be6b Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Thu, 4 Oct 2012 17:13:10 +0300 Subject: CHUI-331 FIXED (Resizing conversation list when message panel is collapsed does not resize list) *fixed missing parentheses from last push --- indra/llui/lllayoutstack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index be6d359c9a..1f2496a8e7 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -767,7 +767,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& { // freeze new size as fraction F32 new_fractional_size = (updated_auto_resize_headroom == 0.f) ? MAX_FRACTIONAL_SIZE - : llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim() - 1) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); + : llclamp(total_visible_fraction * (F32)(new_dim - (panelp->getRelevantMinDim() - 1)) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); fraction_given_up -= new_fractional_size - panelp->mFractionalSize; fraction_remaining -= panelp->mFractionalSize; panelp->mFractionalSize = new_fractional_size; -- cgit v1.2.3 From f533a251553d95045ab7c1d37a149004cd1e2ef0 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 4 Oct 2012 20:36:04 -0700 Subject: CHUI-381 : Implement add_participant and update_participant events handling. --- indra/newview/llconversationmodel.cpp | 12 +++-- indra/newview/llconversationmodel.h | 2 +- indra/newview/llimfloatercontainer.cpp | 86 +++++++++++++--------------------- indra/newview/llimfloatercontainer.h | 2 +- 4 files changed, 42 insertions(+), 60 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 3c111c919a..b2b768bf9a 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -66,9 +66,11 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod { } -void LLConversationItem::postEvent(const std::string& event_type, LLConversationItemParticipant* participant) +void LLConversationItem::postEvent(const std::string& event_type, LLConversationItemSession* session, LLConversationItemParticipant* participant) { - LLSD event(LLSDMap("type", event_type)("session_uuid", getUUID())("participant_name",participant->getName())("participant_uuid",participant->getUUID())); + LLUUID session_id = (session ? session->getUUID() : LLUUID()); + LLUUID participant_id = (participant ? participant->getUUID() : LLUUID()); + LLSD event(LLSDMap("type", event_type)("session_uuid", session_id)("participant_uuid", participant_id)); LLEventPumps::instance().obtain("ConversationsEvents").post(event); } @@ -138,14 +140,14 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa addChild(participant); mIsLoaded = true; mNeedsRefresh = true; - postEvent("add_participant", participant); + postEvent("add_participant", this, participant); } void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* participant) { removeChild(participant); mNeedsRefresh = true; - postEvent("remove_participant", participant); + postEvent("remove_participant", this, participant); } void LLConversationItemSession::removeParticipant(const LLUUID& participant_id) @@ -338,11 +340,11 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam mName = (av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername); mDisplayName = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); mNeedsRefresh = true; - postEvent("update_participant", this); if (mParent) { mParent->requestSort(); } + postEvent("update_participant", dynamic_cast<LLConversationItemSession*>(mParent), this); } void LLConversationItemParticipant::dumpDebugData() diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 7218cdf25a..d5f7e1a56b 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -126,7 +126,7 @@ public: void resetRefresh() { mNeedsRefresh = false; } bool needsRefresh() { return mNeedsRefresh; } - void postEvent(const std::string& event_type, LLConversationItemParticipant* participant); + void postEvent(const std::string& event_type, LLConversationItemSession* session, LLConversationItemParticipant* participant); void buildParticipantMenuOptions(menuentry_vec_t& items); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 78bd90fb96..4022ebdf5b 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -58,7 +58,7 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) : LLMultiFloater(seed), mExpandCollapseBtn(NULL), mConversationsRoot(NULL), - mStream("ConversationsEvents"), + mConversationsEventStream("ConversationsEvents"), mInitialized(false) { mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLIMFloaterContainer::isActionChecked, this, _2)); @@ -79,7 +79,7 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) LLIMFloaterContainer::~LLIMFloaterContainer() { - mStream.stopListening("ConversationsRefresh"); + mConversationsEventStream.stopListening("ConversationsRefresh"); gIdleCallbacks.deleteFunction(idle, this); @@ -160,7 +160,7 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); // Add listener to conversation model events - mStream.listen("ConversationsRefresh", boost::bind(&LLIMFloaterContainer::onConversationModelEvent, this, _1)); + mConversationsEventStream.listen("ConversationsRefresh", boost::bind(&LLIMFloaterContainer::onConversationModelEvent, this, _1)); // a scroller for folder view LLRect scroller_view_rect = mConversationsListPanel->getRect(); @@ -419,22 +419,20 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) // For the moment, we create them here, at the container level, to conform to the pattern implemented in llinventorypanel.cpp // (see LLInventoryPanel::buildNewViews()). - // Note: For the moment, we're not very smart about the event parameter and we just refresh the whole set of views/widgets - // according to the current state of the whole model. - // We should at least analyze the event payload and do things differently for a handful of cases: - // - add session or participant - // - remove session or participant - // - update session or participant (e.g. rename, change sort order, etc...) - // Please see LLConversationItem::postEvent() for the payload formatting. - // *TODO: Add handling for various event signatures (add, remove, update, resort) - std::string type = event.get("type").asString(); + LLUUID session_id = event.get("session_uuid").asUUID(); + LLUUID participant_id = event.get("participant_uuid").asUUID(); + + LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[session_id]); + if (!session_view) + { + // We skip events that are not associated to a session + return false; + } + LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); + if (type == "remove_participant") { - LLUUID session_id = event.get("session_uuid").asUUID(); - LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[session_id]); - LLUUID participant_id = event.get("participant_uuid").asUUID(); - LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); if (participant_view) { session_view->extractItem(participant_view); @@ -443,52 +441,34 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) mConversationsRoot->arrangeAll(); } } - else - { - // On each session in mConversationsItems - for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) + else if (type == "add_participant") { - // Get the current session descriptors - LLConversationItem* session_model = it_session->second; - LLUUID session_id = it_session->first; - LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[session_id]); - // If the session model has been changed, refresh the corresponding view - if (session_model->needsRefresh()) + if (!participant_view) { - session_view->refresh(); - } - // Iterate through each model participant child - LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = session_model->getChildrenBegin(); - LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = session_model->getChildrenEnd(); - while (current_participant_model != end_participant_model) - { - LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); - LLUUID participant_id = participant_model->getUUID(); - LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); - // Is there a corresponding view? If not create it - if (!participant_view) - { - participant_view = createConversationViewParticipant(participant_model); - participant_view->addToFolder(session_view); - participant_view->setVisible(TRUE); - } - else - // Else, see if it needs refresh + LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]); + if (session_model) { - if (participant_model->needsRefresh()) + LLConversationItemParticipant* participant_model = session_model->findParticipant(participant_id); + if (participant_model) { - participant_view->refresh(); + participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(session_view); + participant_view->setVisible(TRUE); } } - // Reset the need for refresh - session_model->resetRefresh(); - mConversationViewModel.requestSortAll(); - mConversationsRoot->arrangeAll(); - // Next participant - current_participant_model++; + } } + else if (type == "update_participant") + { + if (participant_view) + { + participant_view->refresh(); + } } + + mConversationViewModel.requestSortAll(); + mConversationsRoot->arrangeAll(); return false; } diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 832e67ae23..ceb054dfa3 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -149,7 +149,7 @@ private: conversations_widgets_map mConversationsWidgets; LLConversationViewModel mConversationViewModel; LLFolderView* mConversationsRoot; - LLEventStream mStream; + LLEventStream mConversationsEventStream; }; #endif // LL_LLIMFLOATERCONTAINER_H -- cgit v1.2.3 From aeeeae2690c9ea612667ed46021e17cb083510e5 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 5 Oct 2012 12:51:31 -0700 Subject: CHUI-364 : Fixed. Do not render participants widgets when closing a conversation handle. --- indra/newview/llconversationview.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index d4eb551f7a..416e6da2da 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -181,10 +181,8 @@ void LLConversationViewSession::draw() // draw highlight for selected items drawHighlight(show_context, true, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); - // draw children if root folder, or any other folder that is open or animating to closed state - bool draw_children = getRoot() == static_cast<LLFolderViewFolder*>(this) - || isOpen() - || mCurHeight != mTargetHeight; + // Draw children if root folder, or any other folder that is open. Do not draw children when animating to closed state or you get rendering overlap. + bool draw_children = getRoot() == static_cast<LLFolderViewFolder*>(this) || isOpen(); for (folders_t::iterator iter = mFolders.begin(); iter != mFolders.end();) -- cgit v1.2.3 From db452823e5cc615225f3f163d827954447cf9bd8 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 5 Oct 2012 20:28:11 -0700 Subject: CHUI-194 : WIP : Update the ad-hoc conversation line item title, add a new update_session event. Still some clean up to do. --- indra/newview/llavataractions.cpp | 22 +++++++++++++++ indra/newview/llavataractions.h | 8 ++++++ indra/newview/llconversationmodel.cpp | 49 +++++++++++++++++++++++++++++++--- indra/newview/llconversationmodel.h | 1 + indra/newview/llimfloater.cpp | 30 ++------------------- indra/newview/llimfloatercontainer.cpp | 9 +++++-- 6 files changed, 86 insertions(+), 33 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 248685b964..50697d1885 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -714,6 +714,28 @@ void LLAvatarActions::buildResidentsString(const std::vector<LLAvatarName> avata } } +// static +void LLAvatarActions::buildResidentsString(const uuid_vec_t& avatar_uuids, std::string& residents_string) +{ + std::vector<LLAvatarName> avatar_names; + uuid_vec_t::const_iterator it = avatar_uuids.begin(); + for (; it != avatar_uuids.end(); ++it) + { + LLAvatarName av_name; + if (LLAvatarNameCache::get(*it, &av_name)) + { + avatar_names.push_back(av_name); + } + } + + // We should check whether the vector is not empty to pass the assertion + // that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. + if (!avatar_names.empty()) + { + LLAvatarActions::buildResidentsString(avatar_names, residents_string); + } +} + //static std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs() { diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 6e60f624ad..e7cef587c2 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -218,6 +218,14 @@ public: */ static void buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string); + /** + * Builds a string of residents' display names separated by "words_separator" string. + * + * @param avatar_uuids - a vector of given avatar uuids from which resulting string is built + * @param residents_string - the resulting string + */ + static void buildResidentsString(const uuid_vec_t& avatar_uuids, std::string& residents_string); + /** * Opens the chat history for avatar */ diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index b2b768bf9a..15824704fd 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -27,6 +27,8 @@ #include "llviewerprecompiledheaders.h" +#include "llavatarnamecache.h" +#include "llavataractions.h" #include "llevents.h" #include "llsdutil.h" #include "llconversationmodel.h" @@ -140,9 +142,48 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa addChild(participant); mIsLoaded = true; mNeedsRefresh = true; + updateParticipantName(participant); postEvent("add_participant", this, participant); } +void LLConversationItemSession::updateParticipantName(LLConversationItemParticipant* participant) +{ + // We modify the session name only in the case of an ad-hoc session, exit otherwise (nothing to do) + if (getType() != CONV_SESSION_AD_HOC) + { + return; + } + // Avoid changing the default name if no participant present yet + if (mChildren.size() == 0) + { + return; + } + // Build a string containing the participants names and check if ready for display (we don't want "(waiting)" in there) + // *TODO: Further factor out common code with LLIMFloater::onParticipantsListChanged() + bool all_names_resolved = true; + uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string + child_list_t::iterator iter = mChildren.begin(); + while (iter != mChildren.end()) + { + LLConversationItemParticipant* current_participant = dynamic_cast<LLConversationItemParticipant*>(*iter); + temp_uuids.push_back(current_participant->getUUID()); + LLAvatarName av_name; + if (!LLAvatarNameCache::get(current_participant->getUUID(), &av_name)) + { + all_names_resolved = false; + break; + } + iter++; + } + if (all_names_resolved) + { + std::string new_session_name; + LLAvatarActions::buildResidentsString(temp_uuids, new_session_name); + renameItem(new_session_name); + postEvent("update_session", this, NULL); + } +} + void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* participant) { removeChild(participant); @@ -340,11 +381,13 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam mName = (av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername); mDisplayName = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); mNeedsRefresh = true; - if (mParent) + LLConversationItemSession* parent_session = dynamic_cast<LLConversationItemSession*>(mParent); + if (parent_session) { - mParent->requestSort(); + parent_session->requestSort(); + parent_session->updateParticipantName(this); } - postEvent("update_participant", dynamic_cast<LLConversationItemSession*>(mParent), this); + postEvent("update_participant", parent_session, this); } void LLConversationItemParticipant::dumpDebugData() diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index d5f7e1a56b..1d082852f5 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -149,6 +149,7 @@ public: LLPointer<LLUIImage> getIcon() const { return NULL; } void setSessionID(const LLUUID& session_id) { mUUID = session_id; mNeedsRefresh = true; } void addParticipant(LLConversationItemParticipant* participant); + void updateParticipantName(LLConversationItemParticipant* participant); void removeParticipant(LLConversationItemParticipant* participant); void removeParticipant(const LLUUID& participant_id); void clearParticipants(); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 99337bd5f3..467f48600a 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -60,10 +60,6 @@ #include "llnotificationmanager.h" #include "llautoreplace.h" -/// Helper function to resolve resident names from given uuids -/// and form a string of names separated by "words_separator". -static void build_names_string(const uuid_vec_t& uuids, std::string& names_string); - floater_showed_signal_t LLIMFloater::sIMFloaterShowedSignal; LLIMFloater::LLIMFloater(const LLUUID& session_id) @@ -476,7 +472,7 @@ void LLIMFloater::addP2PSessionParticipants(const LLSD& notification, const LLSD void LLIMFloater::sendParticipantsAddedNotification(const uuid_vec_t& uuids) { std::string names_string; - build_names_string(uuids, names_string); + LLAvatarActions::buildResidentsString(uuids, names_string); LLStringUtil::format_map_t args; args["[NAME]"] = names_string; @@ -581,7 +577,7 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) if (all_names_resolved) { std::string ui_title; - build_names_string(temp_uuids, ui_title); + LLAvatarActions::buildResidentsString(temp_uuids, ui_title); updateSessionName(ui_title, ui_title); } } @@ -1334,25 +1330,3 @@ boost::signals2::connection LLIMFloater::setIMFloaterShowedCallback(const floate { return LLIMFloater::sIMFloaterShowedSignal.connect(cb); } - -// static -void build_names_string(const uuid_vec_t& uuids, std::string& names_string) -{ - std::vector<LLAvatarName> avatar_names; - uuid_vec_t::const_iterator it = uuids.begin(); - for (; it != uuids.end(); ++it) - { - LLAvatarName av_name; - if (LLAvatarNameCache::get(*it, &av_name)) - { - avatar_names.push_back(av_name); - } - } - - // We should check whether the vector is not empty to pass the assertion - // that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. - if (!avatar_names.empty()) - { - LLAvatarActions::buildResidentsString(avatar_names, names_string); - } -} diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 4022ebdf5b..7c5aaa7d0f 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -466,7 +466,11 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) participant_view->refresh(); } } - + else if (type == "update_session") + { + session_view->refresh(); + } + mConversationViewModel.requestSortAll(); mConversationsRoot->arrangeAll(); @@ -1111,7 +1115,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) removeConversationListItem(uuid,false); // Create a conversation session model - LLConversationItem* item = NULL; + LLConversationItemSession* item = NULL; LLSpeakerMgr* speaker_manager = (is_nearby_chat ? (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()) : LLIMModel::getInstance()->getSpeakerManager(uuid)); if (speaker_manager) { @@ -1123,6 +1127,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) return; } item->renameItem(display_name); + item->updateParticipantName(NULL); mConversationsItems[uuid] = item; -- cgit v1.2.3 From 698cfc2811a6ce976a153a1a0d87d31c56dd52ec Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Mon, 8 Oct 2012 15:19:00 +0300 Subject: CHUI-390 FIXED Selecting Chat History option from right click menu on a conversation name does not open chat history viewer --- indra/newview/llimfloatercontainer.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 7c5aaa7d0f..94e7f1000b 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -888,7 +888,13 @@ void LLIMFloaterContainer::doToSelectedConversation(const std::string& command, } else if("chat_history" == command) { - LLAvatarActions::viewChatHistory(conversationItem->getUUID()); + const LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(conversationItem->getUUID()); + + if (NULL != session) + { + const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID; + LLFloaterReg::showInstance("preview_conversation", session_id, true); + } } else { -- cgit v1.2.3 From 93e36340ec895a44d0b0bc73157fe23279883863 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Mon, 8 Oct 2012 22:20:58 +0300 Subject: CHUI-331 (Resizing conversation list when message panel is collapsed does not resize list) fixed --- indra/newview/llimfloatercontainer.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 94e7f1000b..5f111b39d4 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -553,12 +553,25 @@ void LLIMFloaterContainer::collapseMessagesPane(bool collapse) gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", mConversationsPane->isCollapsed()); } + // Save left pane rectangle before collapsing/expanding right pane. + LLRect prevRect = mConversationsPane->getRect(); + // Show/hide the messages pane. mConversationsStack->collapsePanel(mMessagesPane, collapse); + if (!collapse) + { + // Make sure layout is updated before resizing conversation pane. + mConversationsStack->updateLayout(); + } + updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); + if (!collapse) + { + // Restore conversation's pane previous width after expanding messages pane. + mConversationsPane->setTargetDim(prevRect.getWidth()); + } } - void LLIMFloaterContainer::collapseConversationsPane(bool collapse) { if (mConversationsPane->isCollapsed() == collapse) -- cgit v1.2.3 From 0d619bcdc1fbb7869a6376749b0bd46b1d40c91e Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 8 Oct 2012 18:20:37 -0700 Subject: CHUI-147 : Sort the residents names when getting a resident string list --- indra/newview/llavataractions.cpp | 8 ++++---- indra/newview/llavataractions.h | 2 +- indra/newview/llconversationmodel.cpp | 4 +++- 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 50697d1885..3326103d03 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -697,15 +697,15 @@ namespace action_give_inventory } // static -void LLAvatarActions::buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string) +void LLAvatarActions::buildResidentsString(std::vector<LLAvatarName> avatar_names, std::string& residents_string) { llassert(avatar_names.size() > 0); - + + std::sort(avatar_names.begin(), avatar_names.end()); const std::string& separator = LLTrans::getString("words_separator"); for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; ) { - LLAvatarName av_name = *it; - residents_string.append(av_name.mDisplayName); + residents_string.append((*it).mDisplayName); if (++it == avatar_names.end()) { break; diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index e7cef587c2..6e1198cd09 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -216,7 +216,7 @@ public: * @param avatar_names - a vector of given avatar names from which resulting string is built * @param residents_string - the resulting string */ - static void buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string); + static void buildResidentsString(std::vector<LLAvatarName> avatar_names, std::string& residents_string); /** * Builds a string of residents' display names separated by "words_separator" string. diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 15824704fd..29e7ac4e12 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -159,7 +159,6 @@ void LLConversationItemSession::updateParticipantName(LLConversationItemParticip return; } // Build a string containing the participants names and check if ready for display (we don't want "(waiting)" in there) - // *TODO: Further factor out common code with LLIMFloater::onParticipantsListChanged() bool all_names_resolved = true; uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string child_list_t::iterator iter = mChildren.begin(); @@ -170,6 +169,9 @@ void LLConversationItemSession::updateParticipantName(LLConversationItemParticip LLAvatarName av_name; if (!LLAvatarNameCache::get(current_participant->getUUID(), &av_name)) { + // If the name is not in the cache yet, bail out + // Note: we don't bind ourselves to the LLAvatarNameCache event as we are called by + // onAvatarNameCache() which is itself attached to the same event. all_names_resolved = false; break; } -- cgit v1.2.3 From 1db55ab6da9f6fcc9f51d4c09ed5fa2b88afd7c4 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 9 Oct 2012 12:07:35 -0700 Subject: CHUI-393 : Suppress the sort participants by distance from you menu item. Kept the code around. --- indra/newview/skins/default/xui/en/menu_participant_view.xml | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml index 0043c14479..6fa0707eea 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_view.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -59,17 +59,6 @@ function="IMFloaterContainer.Check" parameter="sort_participants_by_recent" /> </menu_item_check> - <menu_item_check - label="Sort participants by distance from you" - layout="topleft" - name="sort_participants_by_distance"> - <on_click - function="IMFloaterContainer.Action" - parameter="sort_participants_by_distance" /> - <on_check - function="IMFloaterContainer.Check" - parameter="sort_participants_by_distance" /> - </menu_item_check> <menu_item_separator layout="topleft" /> <menu_item_call -- cgit v1.2.3 From ad371c2cfd9d39a4d615cb709b8f85fada0154c6 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 9 Oct 2012 20:31:15 -0700 Subject: CHUI-375 : Fixed default parameters changed in methods profile but not in binding calls. --- indra/llui/llui.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 41a948e545..f43409a1ff 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1629,10 +1629,10 @@ void LLUI::initClass(const settings_map_t& settings, LLUICtrl::CommitCallbackRegistry::Registrar& reg = LLUICtrl::CommitCallbackRegistry::defaultRegistrar(); // Callbacks for associating controls with floater visibility: - reg.add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleInstance, _2, LLSD())); - reg.add("Floater.ToggleOrBringToFront", boost::bind(&LLFloaterReg::toggleInstanceOrBringToFront, _2, LLSD())); - reg.add("Floater.Show", boost::bind(&LLFloaterReg::showInstance, _2, LLSD(), FALSE)); - reg.add("Floater.Hide", boost::bind(&LLFloaterReg::hideInstance, _2, LLSD())); + reg.add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleInstance, _2, LLSD(LLUUID()))); + reg.add("Floater.ToggleOrBringToFront", boost::bind(&LLFloaterReg::toggleInstanceOrBringToFront, _2, LLSD(LLUUID()))); + reg.add("Floater.Show", boost::bind(&LLFloaterReg::showInstance, _2, LLSD(LLUUID()), FALSE)); + reg.add("Floater.Hide", boost::bind(&LLFloaterReg::hideInstance, _2, LLSD(LLUUID()))); // Button initialization callback for toggle buttons reg.add("Button.SetFloaterToggle", boost::bind(&LLButton::setFloaterToggle, _1, _2)); @@ -1647,8 +1647,8 @@ void LLUI::initClass(const settings_map_t& settings, reg.add("Button.ToggleFloater", boost::bind(&LLButton::toggleFloaterAndSetToggleState, _1, _2)); // Used by menus along with Floater.Toggle to display visibility as a check-mark - LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.Visible", boost::bind(&LLFloaterReg::instanceVisible, _2, LLSD())); - LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.IsOpen", boost::bind(&LLFloaterReg::instanceVisible, _2, LLSD())); + LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.Visible", boost::bind(&LLFloaterReg::instanceVisible, _2, LLSD(LLUUID()))); + LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.IsOpen", boost::bind(&LLFloaterReg::instanceVisible, _2, LLSD(LLUUID()))); // Parse the master list of commands LLCommandManager::load(); -- cgit v1.2.3 From 8b4423d428a0a209711eb18cc003d9ca4970e17a Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Wed, 10 Oct 2012 20:04:56 +0300 Subject: CHUI-377 (Icons in message panel out of position when nearby chat conversation selected) FIXED --- indra/newview/llimconversation.cpp | 33 ++++++++++++++++++++++----------- indra/newview/llimconversation.h | 2 ++ 2 files changed, 24 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 2ad7f9b193..3b334df189 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -393,7 +393,7 @@ void LLIMConversation::updateHeaderAndToolbar() // prevent start conversation before its container LLIMFloaterContainer::getInstance(); - bool is_torn_off = !getHost(); + bool is_torn_off = checkIfTornOff(); if (!is_torn_off) { hideAllStandardButtons(); @@ -505,16 +505,7 @@ void LLIMConversation::onSlide(LLIMConversation* self) /*virtual*/ void LLIMConversation::onOpen(const LLSD& key) { - LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); - bool is_hosted = !!host_floater; - if (is_hosted) - { - // Show the messages pane when opening a floater hosted in the Conversations - host_floater->collapseMessagesPane(false); - } - - setTornOff(!is_hosted); - updateHeaderAndToolbar(); + checkIfTornOff(); } // virtual @@ -546,3 +537,23 @@ bool LLIMConversation::isChatMultiTab() // Restart is required in order to change chat window type. return true; } + +bool LLIMConversation::checkIfTornOff() +{ + bool isTorn = !getHost(); + if (!isTorn) + { + LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); + + // Show the messages pane when opening a floater hosted in the Conversations + host_floater->collapseMessagesPane(false); + } + + if (isTorn != isTornOff()) + { + setTornOff(isTorn); + updateHeaderAndToolbar(); + } + + return isTorn; +} \ No newline at end of file diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index c54081d316..0960d6db88 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -138,6 +138,8 @@ private: */ void reshapeChatHistory(); + bool checkIfTornOff(); + LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. bool mHadFocus; -- cgit v1.2.3 From 82e5649fba22f7fa0cb4744f632aa836f0855f85 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Thu, 11 Oct 2012 14:06:35 +0300 Subject: CHUI-377 (Icons in message panel out of position when nearby chat conversation selected) Fixed bug with collapsing messages pane --- indra/newview/llimconversation.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 3b334df189..9f3c6d0f3d 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -505,7 +505,12 @@ void LLIMConversation::onSlide(LLIMConversation* self) /*virtual*/ void LLIMConversation::onOpen(const LLSD& key) { - checkIfTornOff(); + if (!checkIfTornOff()) + { + LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); + // Show the messages pane when opening a floater hosted in the Conversations + host_floater->collapseMessagesPane(false); + } } // virtual @@ -541,13 +546,6 @@ bool LLIMConversation::isChatMultiTab() bool LLIMConversation::checkIfTornOff() { bool isTorn = !getHost(); - if (!isTorn) - { - LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); - - // Show the messages pane when opening a floater hosted in the Conversations - host_floater->collapseMessagesPane(false); - } if (isTorn != isTornOff()) { @@ -556,4 +554,4 @@ bool LLIMConversation::checkIfTornOff() } return isTorn; -} \ No newline at end of file +} -- cgit v1.2.3 From 0ff5a0c8ceebfab0d786aaf027c7c548170afe8d Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Thu, 11 Oct 2012 19:58:26 +0300 Subject: CHUI-356 FIXED Call notifyObserverSessionIDUpdated() only after initing IM floater with new session id --- indra/newview/llimview.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index b45903835a..a604c884ca 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -643,6 +643,12 @@ void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, con { session->sessionInitReplyReceived(new_session_id); + LLIMFloater* im_floater = LLIMFloater::findInstance(old_session_id); + if (im_floater) + { + im_floater->sessionInitReplyReceived(new_session_id); + } + if (old_session_id != new_session_id) { mId2SessionMap.erase(old_session_id); @@ -651,12 +657,6 @@ void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, con gIMMgr->notifyObserverSessionIDUpdated(old_session_id, new_session_id); } - LLIMFloater* im_floater = LLIMFloater::findInstance(old_session_id); - if (im_floater) - { - im_floater->sessionInitReplyReceived(new_session_id); - } - // auto-start the call on session initialization? if (session->mStartCallOnInitialize) { -- cgit v1.2.3 From 8aa424128ad06567f4c32c6672dc63d9b2111efa Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 11 Oct 2012 10:38:34 -0700 Subject: CHUI-380: Before code review changes. Now the user selects a conversation or participant of a conversation the correct chat floater will appear. Focus will be redirected to the chat input text box automatically allowing the user to type into the input text box. --- indra/newview/llconversationview.cpp | 28 ++++++++++++++++++++++++--- indra/newview/llconversationview.h | 1 + indra/newview/llimfloater.cpp | 37 +++++++++++++++++++++--------------- indra/newview/llimfloater.h | 1 + indra/newview/llnearbychat.cpp | 20 +++++++++++++++++++ indra/newview/llnearbychat.h | 2 +- 6 files changed, 70 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index d4eb551f7a..112c38d8b8 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -32,6 +32,8 @@ #include <boost/bind.hpp> #include "llagentdata.h" #include "llconversationmodel.h" +#include "llimfloater.h" +#include "llnearbychat.h" #include "llimconversation.h" #include "llimfloatercontainer.h" #include "llfloaterreg.h" @@ -407,21 +409,41 @@ void LLConversationViewParticipant::draw() static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); - const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled const LLFontGL* font = getLabelFontForStyle(mLabelStyle); F32 right_x = 0; F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad; F32 text_left = (F32)getLabelXPos(); - LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; + LLColor4 color = mIsSelected ? sHighlightFgColor : sFgColor; - drawHighlight(show_context, filled, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); + drawHighlight(show_context, true, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); drawLabel(font, text_left, y, color, right_x); LLView::draw(); } +void LLConversationViewParticipant::selectItem() +{ + LLConversationItem* vmi = this->getParentFolder() ? static_cast<LLConversationItem*>(this->getParentFolder()->getViewModelItem()) : NULL; + + if(vmi) + { + //When null, show the nearby chat conversation floater + if(vmi->getUUID().isNull()) + { + LLNearbyChat* nearbyChat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); + nearbyChat->show(); + } + //Otherwise, show the IM conversation floater + else + { + LLIMFloater::show(vmi->getUUID()); + } + } + + LLFolderViewItem::selectItem(); +} void LLConversationViewParticipant::refresh() { diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index c81c70b456..bd95387bbe 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -113,6 +113,7 @@ public: }; virtual ~LLConversationViewParticipant( void ) { } + void selectItem(); bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } virtual void refresh(); void addToFolder(LLFolderViewFolder* folder); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 99337bd5f3..990b9c45f9 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -719,6 +719,27 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock) } } +void LLIMFloater::setFocus(BOOL focusFlag) +{ + LLTransientDockableFloater::setFocus(focusFlag); + + BOOL is_minimized = focusFlag && isChatMultiTab() + ? LLIMFloaterContainer::getInstance()->isMinimized() + : !focusFlag; + + //Redirect focus to input editor + if (!is_minimized && mChatHistory && mInputEditor) + { + //only if floater was construced and initialized from xml + updateMessages(); + //prevent stealing focus when opening a background IM tab (EXT-5387, checking focus for EXT-6781) + if (!isChatMultiTab() || hasFocus()) + { + mInputEditor->setFocus(TRUE); + } + } +} + void LLIMFloater::setVisible(BOOL visible) { LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> @@ -734,21 +755,6 @@ void LLIMFloater::setVisible(BOOL visible) channel->redrawToasts(); } - BOOL is_minimized = visible && isChatMultiTab() - ? LLIMFloaterContainer::getInstance()->isMinimized() - : !visible; - - if (!is_minimized && mChatHistory && mInputEditor) - { - //only if floater was construced and initialized from xml - updateMessages(); - //prevent stealing focus when opening a background IM tab (EXT-5387, checking focus for EXT-6781) - if (!isChatMultiTab() || hasFocus()) - { - mInputEditor->setFocus(TRUE); - } - } - if(!visible) { LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(mSessionID); @@ -761,6 +767,7 @@ void LLIMFloater::setVisible(BOOL visible) if (visible && isInVisibleChain()) { sIMFloaterShowedSignal(mSessionID); + setFocus(TRUE); } } diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 5ed1d1ab35..26daf00afd 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -65,6 +65,7 @@ public: // LLView overrides /*virtual*/ BOOL postBuild(); + /*virtual*/ void setFocus(BOOL focusFlag); /*virtual*/ void setVisible(BOOL visible); /*virtual*/ BOOL getVisible(); // Check typing timeout timer. diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index b96b486868..e0778afd86 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -271,11 +271,31 @@ void LLNearbyChat::removeScreenChat() } } +void LLNearbyChat::setFocus(BOOL focusFlag) +{ + LLTransientDockableFloater::setFocus(focusFlag); + + BOOL is_minimized = focusFlag && isChatMultiTab() + ? LLIMFloaterContainer::getInstance()->isMinimized() + : !focusFlag; + + //Redirect focus to input editor + if (!is_minimized && mChatHistory && mInputEditor) + { + //prevent stealing focus when opening a background IM tab (EXT-5387, checking focus for EXT-6781) + if (!isChatMultiTab() || hasFocus()) + { + mInputEditor->setFocus(TRUE); + } + } +} + void LLNearbyChat::setVisible(BOOL visible) { if(visible) { removeScreenChat(); + setFocus(TRUE); } LLIMConversation::setVisible(visible); diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 93168ba96a..7ada4daea8 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -52,7 +52,7 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); - + /*virtual*/ void setFocus(BOOL focusFlag); /*virtual*/ void setVisible(BOOL visible); void loadHistory(); -- cgit v1.2.3 From 375f380ea388b37c34ace9570822d0c117b3d2f1 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 11 Oct 2012 12:17:46 -0700 Subject: CHUI-380: Code cleanup after code review. --- indra/newview/llimfloater.cpp | 13 ++----------- indra/newview/llnearbychat.cpp | 12 ++---------- 2 files changed, 4 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 990b9c45f9..a1ed1e0b01 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -723,20 +723,11 @@ void LLIMFloater::setFocus(BOOL focusFlag) { LLTransientDockableFloater::setFocus(focusFlag); - BOOL is_minimized = focusFlag && isChatMultiTab() - ? LLIMFloaterContainer::getInstance()->isMinimized() - : !focusFlag; - //Redirect focus to input editor - if (!is_minimized && mChatHistory && mInputEditor) + if (focusFlag) { - //only if floater was construced and initialized from xml updateMessages(); - //prevent stealing focus when opening a background IM tab (EXT-5387, checking focus for EXT-6781) - if (!isChatMultiTab() || hasFocus()) - { - mInputEditor->setFocus(TRUE); - } + mInputEditor->setFocus(TRUE); } } diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index e0778afd86..a0ddc9b52b 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -275,18 +275,10 @@ void LLNearbyChat::setFocus(BOOL focusFlag) { LLTransientDockableFloater::setFocus(focusFlag); - BOOL is_minimized = focusFlag && isChatMultiTab() - ? LLIMFloaterContainer::getInstance()->isMinimized() - : !focusFlag; - //Redirect focus to input editor - if (!is_minimized && mChatHistory && mInputEditor) + if (focusFlag) { - //prevent stealing focus when opening a background IM tab (EXT-5387, checking focus for EXT-6781) - if (!isChatMultiTab() || hasFocus()) - { - mInputEditor->setFocus(TRUE); - } + mInputEditor->setFocus(TRUE); } } -- cgit v1.2.3 From f4b10aaebbaf8eb66d41ffa703f6ed7b909ba7e7 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 11 Oct 2012 17:48:39 -0700 Subject: CHUI-380: Fixing a bug that occurred when right clicking nearby chat and then right clicking a participant under a conversation. This would result in both the participant and conversation to be highlighted. Still a work in progress. This change involves introducing an old bug CHUI 289 and finding a different approach to solving it. --- indra/newview/llconversationview.cpp | 2 +- indra/newview/llimconversation.cpp | 4 ++-- indra/newview/llimfloater.cpp | 5 ++++- indra/newview/llnearbychat.cpp | 15 ++++++++------- 4 files changed, 15 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index f9a3a05e59..70f2446752 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -415,7 +415,7 @@ void LLConversationViewParticipant::draw() F32 text_left = (F32)getLabelXPos(); LLColor4 color = mIsSelected ? sHighlightFgColor : sFgColor; - drawHighlight(show_context, true, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); + drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); drawLabel(font, text_left, y, color, right_x); LLView::draw(); diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 9f3c6d0f3d..2027f79eea 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -222,8 +222,8 @@ void LLIMConversation::onFocusReceived() if (! mHadFocus) { - LLIMFloaterContainer* container = LLIMFloaterContainer::getInstance(); - container->setConvItemSelect(mSessionID); + // LLIMFloaterContainer* container = LLIMFloaterContainer::getInstance(); + // container->setConvItemSelect(mSessionID); } } diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index a8add9c6ab..e4032738a7 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -725,6 +725,7 @@ void LLIMFloater::setFocus(BOOL focusFlag) updateMessages(); mInputEditor->setFocus(TRUE); } + } void LLIMFloater::setVisible(BOOL visible) @@ -754,8 +755,10 @@ void LLIMFloater::setVisible(BOOL visible) if (visible && isInVisibleChain()) { sIMFloaterShowedSignal(mSessionID); - setFocus(TRUE); + } + + setFocus(visible); } BOOL LLIMFloater::getVisible() diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a0ddc9b52b..a89ae4a2dc 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -274,23 +274,24 @@ void LLNearbyChat::removeScreenChat() void LLNearbyChat::setFocus(BOOL focusFlag) { LLTransientDockableFloater::setFocus(focusFlag); - + //Redirect focus to input editor if (focusFlag) { mInputEditor->setFocus(TRUE); } + } void LLNearbyChat::setVisible(BOOL visible) { - if(visible) - { - removeScreenChat(); - setFocus(TRUE); - } - LLIMConversation::setVisible(visible); + + if(visible) + { + removeScreenChat(); + } + setFocus(visible); } -- cgit v1.2.3 From 9aa03f0bf284bbfa3f50883351c6e39f7ffa41c5 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Fri, 12 Oct 2012 14:29:44 +0300 Subject: CHUI-402 (Double-click on conversation participant should begin IM session) --- indra/newview/llimfloatercontainer.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 5f111b39d4..0f44d42780 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -142,6 +142,9 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsListPanel = getChild<LLPanel>("conversations_list_panel"); + // Open IM session with selected participant on double click event + mConversationsListPanel->setDoubleClickCallback(boost::bind(&LLIMFloaterContainer::doToSelected, this, LLSD("im"))); + // Create the root model and view for all conversation sessions LLConversationItem* base_item = new LLConversationItem(getRootViewModel()); -- cgit v1.2.3 From 19c5b35a86dbe641fe397baf9a8194d78e440af8 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Fri, 12 Oct 2012 20:10:13 +0300 Subject: CHUI-385 FIXED All user's do not receive ad hoc messages after adding a user to a conversation --- indra/newview/llimfloatercontainer.cpp | 15 ++++++++++----- indra/newview/llimfloatercontainer.h | 4 ++-- indra/newview/llimview.cpp | 9 ++++++--- 3 files changed, 18 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 0f44d42780..2248699e5e 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -109,8 +109,7 @@ void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) { - removeConversationListItem(old_session_id); - addConversationListItem(new_session_id); + addConversationListItem(new_session_id, removeConversationListItem(old_session_id)); } void LLIMFloaterContainer::sessionRemoved(const LLUUID& session_id) @@ -1118,7 +1117,7 @@ void LLIMFloaterContainer::setNearbyDistances() } } -void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) +void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/) { bool is_nearby_chat = uuid.isNull(); @@ -1173,7 +1172,10 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) current_participant_model++; } - setConvItemSelect(uuid); + if (isWidgetSelected) + { + setConvItemSelect(uuid); + } // set the widget to minimized mode if conversations pane is collapsed widget->toggleMinimizedMode(mConversationsPane->isCollapsed()); @@ -1181,17 +1183,19 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) return; } -void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) +bool LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) { // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener + bool isWidgetSelected = false; conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(uuid); if (widget_it != mConversationsWidgets.end()) { LLFolderViewItem* widget = widget_it->second; if (widget) { + isWidgetSelected = widget->isSelected(); widget->destroyView(); } } @@ -1211,6 +1215,7 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c widget->selectItem(); } } + return isWidgetSelected; } LLConversationViewSession* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index ceb054dfa3..5c11577154 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -133,8 +133,8 @@ private: // Conversation list implementation public: - void removeConversationListItem(const LLUUID& uuid, bool change_focus = true); - void addConversationListItem(const LLUUID& uuid); + bool removeConversationListItem(const LLUUID& uuid, bool change_focus = true); + void addConversationListItem(const LLUUID& uuid, bool isWidgetSelected = false); void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); void setNearbyDistances(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index a604c884ca..aa5b9ce006 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -643,6 +643,12 @@ void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, con { session->sessionInitReplyReceived(new_session_id); + if (old_session_id != new_session_id) + { + mId2SessionMap.erase(old_session_id); + mId2SessionMap[new_session_id] = session; + } + LLIMFloater* im_floater = LLIMFloater::findInstance(old_session_id); if (im_floater) { @@ -651,9 +657,6 @@ void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, con if (old_session_id != new_session_id) { - mId2SessionMap.erase(old_session_id); - mId2SessionMap[new_session_id] = session; - gIMMgr->notifyObserverSessionIDUpdated(old_session_id, new_session_id); } -- cgit v1.2.3 From 48c7e2cee70996048b0974c6cdda67cdea11a32c Mon Sep 17 00:00:00 2001 From: "Jeff (Gioffredo Linden)" <gioffredo@lindenlab.com> Date: Fri, 12 Oct 2012 18:14:57 -0400 Subject: Expose Chat history to VITA by adding getValue method to llchathistory object --- indra/newview/llchathistory.cpp | 8 ++++++++ indra/newview/llchathistory.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 3636f9e9d2..deb658c489 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -596,6 +596,14 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this); } +LLSD LLChatHistory::getValue() +{ + LLSD* text=new LLSD(); + text->assign(mEditor->getText()); + return *text; + +} + LLChatHistory::~LLChatHistory() { this->clear(); diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 990c52f31b..fa88483fcd 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -103,7 +103,7 @@ class LLChatHistory : public LLUICtrl public: ~LLChatHistory(); - + LLSD getVlue(); void initFromParams(const Params&); /** -- cgit v1.2.3 From 5f4fbffc82ae755235ead5e1b5883cc909e77e77 Mon Sep 17 00:00:00 2001 From: "Jeff (Gioffredo Linden)" <gioffredo@lindenlab.com> Date: Fri, 12 Oct 2012 20:30:06 -0400 Subject: Fix typo --- indra/newview/llchathistory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index fa88483fcd..effdd75911 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -103,7 +103,7 @@ class LLChatHistory : public LLUICtrl public: ~LLChatHistory(); - LLSD getVlue(); + LLSD getValue(); void initFromParams(const Params&); /** -- cgit v1.2.3 From d7d0416547958792517a9b739b370e51c717fb23 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 12 Oct 2012 20:15:57 -0700 Subject: CHUI-380: (In progress) Refactoring needed to fix focusing issues when selecting an existing conversation item. This commit resolves re-introducing bug CHUI-289. Will code review and cleanup code in next commit. --- indra/llkdu/llimagej2ckdu.cpp | 4 ++-- indra/newview/llchiclet.h | 1 + indra/newview/llchicletbar.h | 1 + indra/newview/llconversationlog.h | 1 + indra/newview/llconversationview.cpp | 6 ++++-- indra/newview/llimconversation.cpp | 11 ----------- indra/newview/llimconversation.h | 3 --- indra/newview/llimfloatercontainer.cpp | 19 +++++++++++++++++++ indra/newview/llimfloatercontainer.h | 3 +++ indra/newview/llimview.cpp | 13 +++++++++++++ indra/newview/llimview.h | 2 ++ indra/newview/llsyswellwindow.h | 1 + 12 files changed, 47 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index cf88de12b4..db75b6e003 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -166,12 +166,12 @@ void LLKDUMessageWarning::put_text(const kdu_uint16 *s) void LLKDUMessageError::put_text(const char *s) { - llinfos << "KDU Error: " << s << llendl; + //llinfos << "KDU Error: " << s << llendl; } void LLKDUMessageError::put_text(const kdu_uint16 *s) { - llinfos << "KDU Error: " << s << llendl; + //llinfos << "KDU Error: " << s << llendl; } void LLKDUMessageError::flush(bool end_of_message) diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index f51d7b622c..3a52b0a67b 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -874,6 +874,7 @@ class LLIMWellChiclet : public LLSysWellChiclet, LLIMSessionObserver friend class LLUICtrlFactory; public: /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} + /*virtual*/ void sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; /*virtual*/ void sessionRemoved(const LLUUID& session_id) { messageCountChanged(LLSD()); } /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {} diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h index 7d0d904810..0589a9fccc 100644 --- a/indra/newview/llchicletbar.h +++ b/indra/newview/llchicletbar.h @@ -51,6 +51,7 @@ public: // LLIMSessionObserver observe triggers /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; /*virtual*/ void sessionRemoved(const LLUUID& session_id); /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 373406aa6f..70f04b21c8 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -124,6 +124,7 @@ public: // LLIMSessionObserver triggers virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + virtual void sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; // Stub virtual void sessionRemoved(const LLUUID& session_id){} // Stub virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){}; // Stub virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){}; // Stub diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 70f2446752..637f30635e 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -424,8 +424,10 @@ void LLConversationViewParticipant::draw() void LLConversationViewParticipant::selectItem() { LLConversationItem* vmi = this->getParentFolder() ? static_cast<LLConversationItem*>(this->getParentFolder()->getViewModelItem()) : NULL; - - if(vmi) + LLIMFloaterContainer* container = LLIMFloaterContainer::getInstance(); + + //Only execute when switching floaters (conversations) + if(vmi && vmi->getUUID() != container->getSelectedSession()) { //When null, show the nearby chat conversation floater if(vmi->getUUID().isNull()) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 2027f79eea..bd2a2419a8 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -54,7 +54,6 @@ LLIMConversation::LLIMConversation(const LLSD& session_id) , mInputEditor(NULL) , mInputEditorTopPad(0) , mRefreshTimer(new LLTimer()) - , mHasFocus(false) { mSession = LLIMModel::getInstance()->findIMSession(mSessionID); @@ -216,21 +215,11 @@ void LLIMConversation::onFocusReceived() } LLTransientDockableFloater::onFocusReceived(); - - mHadFocus = mHasFocus; - mHasFocus = true; - - if (! mHadFocus) - { - // LLIMFloaterContainer* container = LLIMFloaterContainer::getInstance(); - // container->setConvItemSelect(mSessionID); - } } void LLIMConversation::onFocusLost() { setBackgroundOpaque(false); - mHasFocus = false; LLTransientDockableFloater::onFocusLost(); } diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 0960d6db88..603e0d0197 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -141,9 +141,6 @@ private: bool checkIfTornOff(); LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. - - bool mHadFocus; - bool mHasFocus; }; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 5f111b39d4..0250854f36 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -101,6 +101,11 @@ void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::str addConversationListItem(session_id); } +void LLIMFloaterContainer::sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +{ + doSomething(session_id); +} + void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { LLIMFloater::addToHost(session_id, true); @@ -1069,6 +1074,19 @@ void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id) } } +void LLIMFloaterContainer::doSomething(const LLUUID& session_id) +{ + LLConversationItem* vmi = static_cast<LLConversationItem*>(mConversationsRoot->getCurSelectedItem()->getParentFolder()->getViewModelItem()); + + if(session_id != vmi->getUUID()) + { + mSelectedSession = session_id; + LLFolderViewItem* widget = mConversationsWidgets[session_id]; + (widget->getRoot())->setSelection(widget, FALSE, FALSE); + } +} + + void LLIMFloaterContainer::setTimeNow(const LLUUID& session_id, const LLUUID& participant_id) { conversations_items_map::iterator item_it = mConversationsItems.find(session_id); @@ -1204,6 +1222,7 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); if (widget_it != mConversationsWidgets.end()) { + mSelectedSession = widget_it->first; LLFolderViewItem* widget = widget_it->second; widget->selectItem(); } diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index ceb054dfa3..da134c498f 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -64,6 +64,7 @@ public: BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); void setConvItemSelect(const LLUUID& session_id); + void doSomething(const LLUUID& session_id); /*virtual*/ void tabClose(); static LLFloater* getCurrentVoiceFloater(); @@ -81,11 +82,13 @@ public: // LLIMSessionObserver observe triggers /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id); /*virtual*/ void sessionRemoved(const LLUUID& session_id); /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); LLConversationViewModel& getRootViewModel() { return mConversationViewModel; } + LLUUID getSelectedSession() { return mSelectedSession; } private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index a604c884ca..e75db1b7af 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2654,6 +2654,11 @@ LLUUID LLIMMgr::addSession( { LLIMModel::getInstance()->newSession(session_id, name, dialog, other_participant_id, ids, voice); } + else + { + std::string session_name = LLIMModel::getInstance()->getName(session_id); + LLIMMgr::getInstance()->notifyObserverSessionAlreadyAdded(session_id, session_name, other_participant_id); + } //we don't need to show notes about online/offline, mute/unmute users' statuses for existing sessions if (!new_session) return session_id; @@ -2956,6 +2961,14 @@ void LLIMMgr::notifyObserverSessionAdded(const LLUUID& session_id, const std::st } } +void LLIMMgr::notifyObserverSessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +{ + for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++) + { + (*it)->sessionAlreadyAdded(session_id, name, other_participant_id); + } +} + void LLIMMgr::notifyObserverSessionVoiceOrIMStarted(const LLUUID& session_id) { for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++) diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 82cfa394a6..a34359eb00 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -303,6 +303,7 @@ class LLIMSessionObserver public: virtual ~LLIMSessionObserver() {} virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0; + virtual void sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0; virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) = 0; virtual void sessionRemoved(const LLUUID& session_id) = 0; virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) = 0; @@ -469,6 +470,7 @@ private: static void onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& name, bool is_group); void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + void notifyObserverSessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); void notifyObserverSessionVoiceOrIMStarted(const LLUUID& session_id); void notifyObserverSessionRemoved(const LLUUID& session_id); void notifyObserverSessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 6be12711ac..302007c9aa 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -171,6 +171,7 @@ public: // LLIMSessionObserver observe triggers /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; /*virtual*/ void sessionRemoved(const LLUUID& session_id); /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); -- cgit v1.2.3 From f609f4cca3a91c8d6ea7c55b61d0b2cfd29be6b7 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Mon, 15 Oct 2012 13:55:12 +0300 Subject: CHUI-400 FIXED Disable "Activate Group" menu item if selected group is the active group --- indra/newview/llimfloatercontainer.cpp | 6 ++++++ indra/newview/skins/default/xui/en/menu_conversation.xml | 1 + 2 files changed, 7 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 2248699e5e..16751a6ea1 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -961,6 +961,12 @@ bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) uuid_vec_t mUUIDs; getParticipantUUIDs(mUUIDs); + if(item == std::string("can_activate_group")) + { + LLUUID selected_group_id = getCurSelectedViewModelItem()->getUUID(); + return gAgent.getGroupID() != selected_group_id; + } + if(mUUIDs.size() <= 0) { return false; diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index 912ff811d9..682d70e4f0 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -117,6 +117,7 @@ layout="topleft" name="activate_group"> <on_click function="Group.DoToSelected" parameter="activate_group"/> + <on_enable function="Avatar.EnableItem" parameter="can_activate_group" /> </menu_item_call> <menu_item_call label="Leave Group" -- cgit v1.2.3 From 5a5df259ffc23a6289d25deac906047a7356fb42 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 15 Oct 2012 13:58:21 -0700 Subject: CHUI-380: Final commit for this issue. After code review changed some method names to be more accurate. Also using dynamic_cast instead of static_cast for safety. --- indra/llkdu/llimagej2ckdu.cpp | 4 ++-- indra/newview/llchiclet.h | 2 +- indra/newview/llchicletbar.h | 2 +- indra/newview/llconversationlog.h | 2 +- indra/newview/llimfloatercontainer.cpp | 24 ++++++++++++++++-------- indra/newview/llimfloatercontainer.h | 4 ++-- indra/newview/llimview.cpp | 8 +++++--- indra/newview/llimview.h | 5 +++-- indra/newview/llsyswellwindow.h | 2 +- 9 files changed, 32 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index db75b6e003..cf88de12b4 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -166,12 +166,12 @@ void LLKDUMessageWarning::put_text(const kdu_uint16 *s) void LLKDUMessageError::put_text(const char *s) { - //llinfos << "KDU Error: " << s << llendl; + llinfos << "KDU Error: " << s << llendl; } void LLKDUMessageError::put_text(const kdu_uint16 *s) { - //llinfos << "KDU Error: " << s << llendl; + llinfos << "KDU Error: " << s << llendl; } void LLKDUMessageError::flush(bool end_of_message) diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 3a52b0a67b..6395f5b694 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -874,7 +874,7 @@ class LLIMWellChiclet : public LLSysWellChiclet, LLIMSessionObserver friend class LLUICtrlFactory; public: /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} - /*virtual*/ void sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} + /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; /*virtual*/ void sessionRemoved(const LLUUID& session_id) { messageCountChanged(LLSD()); } /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {} diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h index 0589a9fccc..a9a5b61ae7 100644 --- a/indra/newview/llchicletbar.h +++ b/indra/newview/llchicletbar.h @@ -51,7 +51,7 @@ public: // LLIMSessionObserver observe triggers /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); - /*virtual*/ void sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; + /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; /*virtual*/ void sessionRemoved(const LLUUID& session_id); /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 70f04b21c8..b92cf0f5e2 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -124,7 +124,7 @@ public: // LLIMSessionObserver triggers virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); - virtual void sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; // Stub + virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; // Stub virtual void sessionRemoved(const LLUUID& session_id){} // Stub virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){}; // Stub virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){}; // Stub diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 0250854f36..c8897c1f92 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -101,9 +101,9 @@ void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::str addConversationListItem(session_id); } -void LLIMFloaterContainer::sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - doSomething(session_id); + setItemSelect(session_id); } void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) @@ -1064,6 +1064,7 @@ bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata) return false; } +//Will select only the conversation item void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id) { LLFolderViewItem* widget = mConversationsWidgets[session_id]; @@ -1074,15 +1075,22 @@ void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id) } } -void LLIMFloaterContainer::doSomething(const LLUUID& session_id) +//Will select the conversation/participant item +void LLIMFloaterContainer::setItemSelect(const LLUUID& session_id) { - LLConversationItem* vmi = static_cast<LLConversationItem*>(mConversationsRoot->getCurSelectedItem()->getParentFolder()->getViewModelItem()); - if(session_id != vmi->getUUID()) + if(mConversationsRoot->getCurSelectedItem() && mConversationsRoot->getCurSelectedItem()->getParentFolder()) { - mSelectedSession = session_id; - LLFolderViewItem* widget = mConversationsWidgets[session_id]; - (widget->getRoot())->setSelection(widget, FALSE, FALSE); + //Retreive the conversation id. When a participant is selected, then have to to get the converation id from the parent. + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(mConversationsRoot->getCurSelectedItem()->getParentFolder()->getViewModelItem()); + + //Will allow selection/highlighting of the conversation/participant + if(session_id != vmi->getUUID()) + { + mSelectedSession = session_id; + LLFolderViewItem* widget = mConversationsWidgets[session_id]; + (widget->getRoot())->setSelection(widget, FALSE, FALSE); + } } } diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index da134c498f..c9da213f8c 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -64,7 +64,7 @@ public: BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); void setConvItemSelect(const LLUUID& session_id); - void doSomething(const LLUUID& session_id); + void setItemSelect(const LLUUID& session_id); /*virtual*/ void tabClose(); static LLFloater* getCurrentVoiceFloater(); @@ -82,7 +82,7 @@ public: // LLIMSessionObserver observe triggers /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); - /*virtual*/ void sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id); /*virtual*/ void sessionRemoved(const LLUUID& session_id); /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index e75db1b7af..eea59c223a 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2650,14 +2650,16 @@ LLUUID LLIMMgr::addSession( } } + //Notify observers that a session was added if (new_session) { LLIMModel::getInstance()->newSession(session_id, name, dialog, other_participant_id, ids, voice); } + //Notifies observers that the session was already added else { std::string session_name = LLIMModel::getInstance()->getName(session_id); - LLIMMgr::getInstance()->notifyObserverSessionAlreadyAdded(session_id, session_name, other_participant_id); + LLIMMgr::getInstance()->notifyObserverSessionActivated(session_id, session_name, other_participant_id); } //we don't need to show notes about online/offline, mute/unmute users' statuses for existing sessions @@ -2961,11 +2963,11 @@ void LLIMMgr::notifyObserverSessionAdded(const LLUUID& session_id, const std::st } } -void LLIMMgr::notifyObserverSessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +void LLIMMgr::notifyObserverSessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++) { - (*it)->sessionAlreadyAdded(session_id, name, other_participant_id); + (*it)->sessionActivated(session_id, name, other_participant_id); } } diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index a34359eb00..00b67f520c 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -303,7 +303,7 @@ class LLIMSessionObserver public: virtual ~LLIMSessionObserver() {} virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0; - virtual void sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0; + virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0; virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) = 0; virtual void sessionRemoved(const LLUUID& session_id) = 0; virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) = 0; @@ -470,7 +470,8 @@ private: static void onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& name, bool is_group); void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); - void notifyObserverSessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + //Triggers when a session has already been added + void notifyObserverSessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); void notifyObserverSessionVoiceOrIMStarted(const LLUUID& session_id); void notifyObserverSessionRemoved(const LLUUID& session_id); void notifyObserverSessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 302007c9aa..378d5e0aa2 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -171,7 +171,7 @@ public: // LLIMSessionObserver observe triggers /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); - /*virtual*/ void sessionAlreadyAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} + /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; /*virtual*/ void sessionRemoved(const LLUUID& session_id); /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); -- cgit v1.2.3 From 815884e0d49620db8f9f60fc629a26ad2c666749 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 15 Oct 2012 14:27:47 -0700 Subject: MAINT-1551 : WIP : Trace IM messaging in and out. --- indra/newview/lleventpoll.cpp | 38 +++++++++++++++++++++++--------------- indra/newview/llimfloater.cpp | 4 +++- indra/newview/llimview.cpp | 7 +++++++ indra/newview/llspeakers.cpp | 4 ++++ indra/newview/llvoicechannel.cpp | 2 ++ 5 files changed, 39 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 4f4d9a40b4..1cf3de8ef0 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -37,6 +37,7 @@ #include "llviewerregion.h" #include "message.h" #include "lltrans.h" +#include "llsdserialize.h" namespace { @@ -109,14 +110,14 @@ namespace const std::string& pollURL, const LLHost& sender) { LLHTTPClient::ResponderPtr result = new LLEventPollResponder(pollURL, sender); - llinfos << "LLEventPollResponder::start <" << sCount << "> " + llinfos << "Merov debug : LLEventPollResponder::start <" << sCount << "> " << pollURL << llendl; return result; } void LLEventPollResponder::stop() { - llinfos << "LLEventPollResponder::stop <" << mCount << "> " + llinfos << "Merov debug : LLEventPollResponder::stop <" << mCount << "> " << mPollURL << llendl; // there should be a way to stop a LLHTTPClient request in progress mDone = true; @@ -134,17 +135,17 @@ namespace LLViewerRegion *regionp = gAgent.getRegion(); if (!regionp) { - llerrs << "LLEventPoll initialized before region is added." << llendl; + llinfos << "Merov debug : LLEventPoll initialized before region is added." << llendl; } mSender = sender.getIPandPort(); - llinfos << "LLEventPoll initialized with sender " << mSender << llendl; + llinfos << "Merov debug : LLEventPoll initialized with sender " << mSender << llendl; makeRequest(); } LLEventPollResponder::~LLEventPollResponder() { stop(); - lldebugs << "LLEventPollResponder::~Impl <" << mCount << "> " + llinfos << "Merov debug : LLEventPollResponder::~Impl <" << mCount << "> " << mPollURL << llendl; } @@ -154,6 +155,7 @@ namespace const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { + llinfos << "Merov debug : LLEventPollResponder::completedRaw, status = " << status << ", reason = " << reason << llendl; if (status == HTTP_BAD_GATEWAY) { // These errors are not parsable as LLSD, @@ -172,8 +174,12 @@ namespace request["ack"] = mAcknowledge; request["done"] = mDone; - lldebugs << "LLEventPollResponder::makeRequest <" << mCount << "> ack = " - << LLSDXMLStreamer(mAcknowledge) << llendl; + llinfos << "Merov debug : viewer->sim : LLEventPollResponder::makeRequest <" << mCount + << "> ack = " << LLSDXMLStreamer(mAcknowledge) + << ", error = " << mErrorCount + << ", sender = " << mSender + << ", url = " << mPollURL + << ", done = " << mDone << llendl; LLHTTPClient::post(mPollURL, request, this); } @@ -183,12 +189,14 @@ namespace LLSD message; message["sender"] = mSender; message["body"] = content["body"]; + llinfos << "Merov debug : sim->viewer : LLEventPollResponder::handleMessage, msg_name = " << msg_name << ", message = " << LLSDOStreamer<LLSDNotationFormatter>(message) << llendl; LLMessageSystem::dispatch(msg_name, message); } //virtual void LLEventPollResponder::error(U32 status, const std::string& reason) { + llinfos << "Merov debug : LLEventPollResponder::error, status = " << status << ", reason = " << reason << llendl; if (mDone) return; // A HTTP_BAD_GATEWAY (502) error is our standard timeout response @@ -207,11 +215,11 @@ namespace + mErrorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC , this); - llwarns << "Unexpected HTTP error. status: " << status << ", reason: " << reason << llendl; + llinfos << "Merov debug : Unexpected HTTP error. status: " << status << ", reason: " << reason << llendl; } else { - llwarns << "LLEventPollResponder::error: <" << mCount << "> got " + llinfos << "Merov debug : LLEventPollResponder::error: <" << mCount << "> got " << status << ": " << reason << (mDone ? " -- done" : "") << llendl; stop(); @@ -227,7 +235,7 @@ namespace // continue running. if(gAgent.getRegion() && gAgent.getRegion()->getHost().getIPandPort() == mSender) { - llwarns << "Forcing disconnect due to stalled main region event poll." << llendl; + llinfos << "Merov debug : Forcing disconnect due to stalled main region event poll." << llendl; LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection")); } } @@ -236,8 +244,8 @@ namespace //virtual void LLEventPollResponder::result(const LLSD& content) { - lldebugs << "LLEventPollResponder::result <" << mCount << ">" - << (mDone ? " -- done" : "") << llendl; + llinfos << "Merov debug : LLEventPollResponder::result <" << mCount << "> " + << (mDone ? " -- done" : "") << ", content = " << LLSDOStreamer<LLSDNotationFormatter>(content) << llendl; if (mDone) return; @@ -246,7 +254,7 @@ namespace if (!content.get("events") || !content.get("id")) { - llwarns << "received event poll with no events or id key" << llendl; + llinfos << "Merov debug : received event poll with no events or id key" << llendl; makeRequest(); return; } @@ -256,11 +264,11 @@ namespace if(mAcknowledge.isUndefined()) { - llwarns << "LLEventPollResponder: id undefined" << llendl; + llinfos << "Merov debug : LLEventPollResponder: id undefined" << llendl; } // was llinfos but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG - lldebugs << "LLEventPollResponder::completed <" << mCount << "> " << events.size() << "events (id " + llinfos << "Merov debug : LLEventPollResponder::completed <" << mCount << "> " << events.size() << "events (id " << LLSDXMLStreamer(mAcknowledge) << ")" << llendl; LLSD::array_const_iterator i = events.beginArray(); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 467f48600a..47e091a57c 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -59,6 +59,7 @@ #include "llviewerchat.h" #include "llnotificationmanager.h" #include "llautoreplace.h" +#include "llsdserialize.h" floater_showed_signal_t LLIMFloater::sIMFloaterShowedSignal; @@ -1208,11 +1209,12 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) } data["method"] = "invite"; data["session-id"] = mSessionID; + llinfos << "Merov debug : viewer->sim : LLIMFloater::inviteToSession, session id = " << mSessionID << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post(url, data,new LLSessionInviteResponder(mSessionID)); } else { - llinfos << "LLIMFloater::inviteToSession -" + llinfos << "Merov debug : LLIMFloater::inviteToSession -" << " no need to invite agents for " << mDialog << llendl; // successful add, because everyone that needed to get added diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index b45903835a..398584e005 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -63,6 +63,7 @@ #include "lltoolbarview.h" #include "llviewercontrol.h" #include "llviewerparcelmgr.h" +#include "llsdserialize.h" const static std::string ADHOC_NAME_SUFFIX(" Conference"); @@ -1316,6 +1317,7 @@ bool LLIMModel::sendStartSession( data["params"] = agents; + llinfos << "Merov debug : viewer-> sim : LLIMModel::sendStartSession, session id = " << temp_session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post( url, data, @@ -2253,6 +2255,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload LLSD data; data["method"] = "accept invitation"; data["session-id"] = session_id; + llinfos << "Merov debug : viewer-> sim : LLIncomingCallDialog::processCallResponse, accept, session id = " << session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post( url, data, @@ -2293,6 +2296,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload LLSD data; data["method"] = "decline invitation"; data["session-id"] = session_id; + llinfos << "Merov debug : viewer-> sim : LLIncomingCallDialog::processCallResponse, decline, session id = " << session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post( url, data, @@ -2346,6 +2350,7 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response) LLSD data; data["method"] = "accept invitation"; data["session-id"] = session_id; + llinfos << "Merov debug : viewer-> sim : inviteUserResponse, accept, session id = " << session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post( url, data, @@ -2381,6 +2386,7 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response) LLSD data; data["method"] = "decline invitation"; data["session-id"] = session_id; + llinfos << "Merov debug : viewer-> sim : inviteUserResponse, decline, session id = " << session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post( url, data, @@ -3345,6 +3351,7 @@ public: LLSD data; data["method"] = "accept invitation"; data["session-id"] = session_id; + llinfos << "Merov debug : viewer-> sim : LLViewerChatterBoxInvitation, session id = " << session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post( url, data, diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 2d2b5202e0..19b99fef11 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -36,6 +36,7 @@ #include "llviewerobjectlist.h" #include "llvoavatar.h" #include "llworld.h" +#include "llsdserialize.h" const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f); const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f); @@ -785,6 +786,7 @@ void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) //current value represents ability to type, so invert data["params"]["mute_info"]["text"] = !speakerp->mModeratorMutedText; + llinfos << "Merov debug : viewer->sim : LLIMSpeakerMgr::toggleAllowTextChat, session id = " << getSessionID() << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post(url, data, new ModerationResponder(getSessionID())); } @@ -809,6 +811,7 @@ void LLIMSpeakerMgr::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmu data["params"]["mute_info"] = LLSD::emptyMap(); data["params"]["mute_info"]["voice"] = !unmute; + llinfos << "Merov debug : viewer->sim : LLIMSpeakerMgr::moderateVoiceParticipant, session id = " << getSessionID() << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post( url, data, @@ -851,6 +854,7 @@ void LLIMSpeakerMgr::moderateVoiceSession(const LLUUID& session_id, bool disallo data["params"]["update_info"]["moderated_mode"] = LLSD::emptyMap(); data["params"]["update_info"]["moderated_mode"]["voice"] = disallow_voice; + llinfos << "Merov debug : viewer->sim : LLIMSpeakerMgr::moderateVoiceSession, session id = " << session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post(url, data, new ModerationResponder(session_id)); } diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index ceff75a0cc..62a43333dd 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -35,6 +35,7 @@ #include "llrecentpeople.h" #include "llviewercontrol.h" #include "llvoicechannel.h" +#include "llsdserialize.h" LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap; @@ -539,6 +540,7 @@ void LLVoiceChannelGroup::getChannelInfo() LLSD data; data["method"] = "call"; data["session-id"] = mSessionID; + llinfos << "Merov debug : viewer-> sim : LLVoiceChannelGroup::getChannelInfo, session id = " << mSessionID << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post(url, data, new LLVoiceCallCapResponder(mSessionID)); -- cgit v1.2.3 From 699e0a1e0b89e4d3c2d1342c821496c5699b8c52 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 15 Oct 2012 14:28:07 -0700 Subject: CHUI-380: Merge fix, the addConverationListItem API was changedso that it does not by default select the new conversation item. Adjusted sessionAdded and sessionVoiceOrImStarted functions to specify that the first item should be selected when calling addConversationListItem(). --- indra/newview/llimfloatercontainer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 8a30b5cd68..5c1105531e 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -98,7 +98,7 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { LLIMFloater::addToHost(session_id, true); - addConversationListItem(session_id); + addConversationListItem(session_id, true); } void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) @@ -109,7 +109,7 @@ void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std: void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { LLIMFloater::addToHost(session_id, true); - addConversationListItem(session_id); + addConversationListItem(session_id, true); } void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) -- cgit v1.2.3 From a8c443feb21d5fe486e9a30649089633ae3f6e22 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 15 Oct 2012 14:29:57 -0700 Subject: MAINT-1551 : WIP : More IM comm tracing and attempt to fix --- indra/newview/llavataractions.cpp | 11 +++++++++-- indra/newview/lleventpoll.cpp | 31 +++++++++++++++++-------------- indra/newview/llspeakers.cpp | 2 ++ 3 files changed, 28 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 3326103d03..f7f5c04ef9 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -296,10 +296,17 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids, const LLUUID& float } const std::string title = LLTrans::getString("conference-title"); LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array, false, floater_id); - if (session_id != LLUUID::null) + + if (session_id == LLUUID::null) { - LLIMFloater::show(session_id); + return; } + + LLIMFloater::show(session_id); +// gIMMgr->processAgentListUpdates(session_id, LLSD()); + gIMMgr->startCall(session_id,LLVoiceChannel::OUTGOING_CALL); + gIMMgr->endCall(session_id); + make_ui_sound("UISndStartIM"); } diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 4f4d9a40b4..a5aa014a74 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -109,14 +109,14 @@ namespace const std::string& pollURL, const LLHost& sender) { LLHTTPClient::ResponderPtr result = new LLEventPollResponder(pollURL, sender); - llinfos << "LLEventPollResponder::start <" << sCount << "> " + llinfos << "Merov debug : LLEventPollResponder::start <" << sCount << "> " << pollURL << llendl; return result; } void LLEventPollResponder::stop() { - llinfos << "LLEventPollResponder::stop <" << mCount << "> " + llinfos << "Merov debug : LLEventPollResponder::stop <" << mCount << "> " << mPollURL << llendl; // there should be a way to stop a LLHTTPClient request in progress mDone = true; @@ -137,14 +137,14 @@ namespace llerrs << "LLEventPoll initialized before region is added." << llendl; } mSender = sender.getIPandPort(); - llinfos << "LLEventPoll initialized with sender " << mSender << llendl; + llinfos << "Merov debug : LLEventPoll initialized with sender " << mSender << llendl; makeRequest(); } LLEventPollResponder::~LLEventPollResponder() { stop(); - lldebugs << "LLEventPollResponder::~Impl <" << mCount << "> " + llinfos << "Merov debug : LLEventPollResponder::~Impl <" << mCount << "> " << mPollURL << llendl; } @@ -154,11 +154,13 @@ namespace const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { + llinfos << "Merov debug : LLEventPollResponder::completedRaw url <" << mPollURL << ">, status = " << status << ", reason = " << reason << llendl; if (status == HTTP_BAD_GATEWAY) { // These errors are not parsable as LLSD, // which LLHTTPClient::Responder::completedRaw will try to do. - completed(status, reason, LLSD()); + //completed(status, reason, LLSD()); + error(status, reason); } else { @@ -172,8 +174,7 @@ namespace request["ack"] = mAcknowledge; request["done"] = mDone; - lldebugs << "LLEventPollResponder::makeRequest <" << mCount << "> ack = " - << LLSDXMLStreamer(mAcknowledge) << llendl; + llinfos << "Merov debug : LLEventPollResponder::makeRequest <" << mCount << "> ack = " << LLSDXMLStreamer(mAcknowledge) << llendl; LLHTTPClient::post(mPollURL, request, this); } @@ -183,6 +184,7 @@ namespace LLSD message; message["sender"] = mSender; message["body"] = content["body"]; + llinfos << "Merov debug : LLEventPollResponder::handleMessage, msg_name = " << msg_name << ", message = " << LLSDOStreamer<LLSDNotationFormatter>(message) << llendl; LLMessageSystem::dispatch(msg_name, message); } @@ -190,6 +192,7 @@ namespace void LLEventPollResponder::error(U32 status, const std::string& reason) { if (mDone) return; + llinfos << "Merov debug : LLEventPollResponder::error, status = " << status << ", reason = " << reason << llendl; // A HTTP_BAD_GATEWAY (502) error is our standard timeout response // we get this when there are no events. @@ -207,11 +210,11 @@ namespace + mErrorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC , this); - llwarns << "Unexpected HTTP error. status: " << status << ", reason: " << reason << llendl; + llinfos << "Merov debug : Unexpected HTTP error. status: " << status << ", reason: " << reason << llendl; } else { - llwarns << "LLEventPollResponder::error: <" << mCount << "> got " + llinfos << "Merov debug : LLEventPollResponder::error: <" << mCount << "> got " << status << ": " << reason << (mDone ? " -- done" : "") << llendl; stop(); @@ -227,7 +230,7 @@ namespace // continue running. if(gAgent.getRegion() && gAgent.getRegion()->getHost().getIPandPort() == mSender) { - llwarns << "Forcing disconnect due to stalled main region event poll." << llendl; + llinfos << "Merov debug : Forcing disconnect due to stalled main region event poll." << llendl; LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection")); } } @@ -236,7 +239,7 @@ namespace //virtual void LLEventPollResponder::result(const LLSD& content) { - lldebugs << "LLEventPollResponder::result <" << mCount << ">" + llinfos << "Merov debug : LLEventPollResponder::result <" << mCount << ">" << (mDone ? " -- done" : "") << llendl; if (mDone) return; @@ -246,7 +249,7 @@ namespace if (!content.get("events") || !content.get("id")) { - llwarns << "received event poll with no events or id key" << llendl; + llinfos << "Merov debug : received event poll with no events or id key" << llendl; makeRequest(); return; } @@ -256,11 +259,11 @@ namespace if(mAcknowledge.isUndefined()) { - llwarns << "LLEventPollResponder: id undefined" << llendl; + llinfos << "Merov debug : LLEventPollResponder: id undefined" << llendl; } // was llinfos but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG - lldebugs << "LLEventPollResponder::completed <" << mCount << "> " << events.size() << "events (id " + llinfos << "Merov debug : LLEventPollResponder::completed <" << mCount << "> " << events.size() << "events (id " << LLSDXMLStreamer(mAcknowledge) << ")" << llendl; LLSD::array_const_iterator i = events.beginArray(); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 2d2b5202e0..92149ee50a 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -286,6 +286,7 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin mSpeakers.insert(std::make_pair(speakerp->mID, speakerp)); mSpeakersSorted.push_back(speakerp); LL_DEBUGS("Speakers") << "Added speaker " << id << llendl; + //llinfos << "Merov debug : setSpeaker, add, id = " << id << ", name = " << name << llendl; fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add"); } else @@ -306,6 +307,7 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin } else { + llinfos << "Merov debug : setSpeaker, speaker not found? id = " << id << ", name = " << name << llendl; LL_WARNS("Speakers") << "Speaker " << id << " not found" << llendl; } } -- cgit v1.2.3 From d0f9600f37a87b2d6c7a2c3cfbbc5d793e505872 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 15 Oct 2012 16:06:02 -0700 Subject: CHUI-380: Bug fix after merge. When selecting the participant of a conversation focus would be lost on the converstation floater. This was because focus would be set to the participant folder item. Resolution: Now delegate focus from the particiapnt folder item to the conversation floater. --- indra/newview/llconversationview.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 637f30635e..b7ebb70e86 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -425,6 +425,7 @@ void LLConversationViewParticipant::selectItem() { LLConversationItem* vmi = this->getParentFolder() ? static_cast<LLConversationItem*>(this->getParentFolder()->getViewModelItem()) : NULL; LLIMFloaterContainer* container = LLIMFloaterContainer::getInstance(); + LLFloater* session_floater; //Only execute when switching floaters (conversations) if(vmi && vmi->getUUID() != container->getSelectedSession()) @@ -441,6 +442,12 @@ void LLConversationViewParticipant::selectItem() LLIMFloater::show(vmi->getUUID()); } } + //Focus the current conversation floater (it is already visible so just focus it) + else + { + session_floater = LLIMConversation::getConversation(vmi->getUUID()); + session_floater->setFocus(TRUE); + } LLFolderViewItem::selectItem(); } -- cgit v1.2.3 From 1557bffb5630158430946abd600218be89e3590e Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 15 Oct 2012 19:44:14 -0700 Subject: MAINT-1551 : WIP : Added a hack : send an accept invitation message so to trigger the sending of the agent list. --- indra/newview/llavataractions.cpp | 4 +- indra/newview/llspeakers.cpp | 126 +++++++++++++++++++++++++++----------- indra/newview/llspeakers.h | 2 + 3 files changed, 93 insertions(+), 39 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index f7f5c04ef9..600df31c8b 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -304,8 +304,8 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids, const LLUUID& float LLIMFloater::show(session_id); // gIMMgr->processAgentListUpdates(session_id, LLSD()); - gIMMgr->startCall(session_id,LLVoiceChannel::OUTGOING_CALL); - gIMMgr->endCall(session_id); +// gIMMgr->startCall(session_id,LLVoiceChannel::OUTGOING_CALL); +// gIMMgr->endCall(session_id); make_ui_sound("UISndStartIM"); } diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 2e26eabb71..11d1b563ac 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -256,6 +256,64 @@ bool LLSpeakersDelayActionsStorage::onTimerActionCallback(const LLUUID& speaker_ } +// +// ModerationResponder +// + +class ModerationResponder : public LLHTTPClient::Responder +{ +public: + ModerationResponder(const LLUUID& session_id) + { + mSessionID = session_id; + } + + virtual void error(U32 status, const std::string& reason) + { + llwarns << status << ": " << reason << llendl; + + if ( gIMMgr ) + { + //403 == you're not a mod + //should be disabled if you're not a moderator + if ( 403 == status ) + { + gIMMgr->showSessionEventError( + "mute", + "not_a_mod_error", + mSessionID); + } + else + { + gIMMgr->showSessionEventError( + "mute", + "generic_request_error", + mSessionID); + } + } + } + +private: + LLUUID mSessionID; +}; + +class UpdateResponder : public LLHTTPClient::Responder +{ +public: + UpdateResponder(const LLUUID& session_id) + { + mSessionID = session_id; + } + + virtual void error(U32 status, const std::string& reason) + { + llinfos << "Merov debug : UpdateResponder error, status = " << status << ": " << reason << llendl; + } + +private: + LLUUID mSessionID; +}; + // // LLSpeakerMgr // @@ -483,6 +541,37 @@ void LLSpeakerMgr::updateSpeakerList() } } + else + { + // Check if the list is empty, except if it's Nearby Chat (session_id NULL). + LLUUID session_id = getSessionID(); + if ((mSpeakers.size() == 0) && (!session_id.isNull())) + { + llinfos << "Merov debug : LLSpeakerMgr::updateSpeakerList: No speakers in " << session_id << llendl; + // MAINT-1551 : If the list is empty for too long, we should send a message to the sim so that + // it sends the participant list again. + updateSession(); + } + } +} + +void LLSpeakerMgr::updateSession() +{ + std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); + LLSD data; + data["method"] = "accept invitation"; +// data["method"] = "session update"; + data["session-id"] = getSessionID(); +// data["params"] = LLSD::emptyMap(); + +// data["params"]["update_info"] = LLSD::emptyMap(); + +// data["params"]["update_info"]["moderated_mode"] = LLSD::emptyMap(); +// data["params"]["update_info"]["moderated_mode"]["voice"] = false; + + llinfos << "Merov debug : viewer->sim : LLSpeakerMgr::updateSession, session id = " << getSessionID() << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; + + LLHTTPClient::post(url, data, new UpdateResponder(getSessionID())); } void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp) @@ -736,43 +825,6 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) } } -class ModerationResponder : public LLHTTPClient::Responder -{ -public: - ModerationResponder(const LLUUID& session_id) - { - mSessionID = session_id; - } - - virtual void error(U32 status, const std::string& reason) - { - llwarns << status << ": " << reason << llendl; - - if ( gIMMgr ) - { - //403 == you're not a mod - //should be disabled if you're not a moderator - if ( 403 == status ) - { - gIMMgr->showSessionEventError( - "mute", - "not_a_mod_error", - mSessionID); - } - else - { - gIMMgr->showSessionEventError( - "mute", - "generic_request_error", - mSessionID); - } - } - } - -private: - LLUUID mSessionID; -}; - void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) { LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id); diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 8ab08661d3..671b3fb341 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -258,6 +258,8 @@ protected: void setSpeakerNotInChannel(LLSpeaker* speackerp); bool removeSpeaker(const LLUUID& speaker_id); + void updateSession(); + typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t; speaker_map_t mSpeakers; -- cgit v1.2.3 From 5a22949cf509ebd1a3c7dfbd029b4bc188fee4a3 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Tue, 16 Oct 2012 15:33:12 +0300 Subject: CHUI-388 FIXED Do not add menu items to Participant Menu if own avatar is selected in participant list. Do not show Menu if all menu items are disabled. --- indra/llui/llmenugl.cpp | 12 +++++++++++- indra/newview/llconversationmodel.cpp | 6 +++++- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 5182a8cea1..ae4aa1e1dd 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3037,7 +3037,17 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y) const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size const S32 CURSOR_WIDTH = 12; - if(menu->getChildList()->empty()) + //Do not show menu if all menu items are disabled + BOOL item_enabled = false; + for (LLView::child_list_t::const_iterator itor = menu->getChildList()->begin(); + itor != menu->getChildList()->end(); + ++itor) + { + LLView *menu_item = (*itor); + item_enabled = item_enabled || menu_item->getEnabled(); + } + + if(menu->getChildList()->empty() || !item_enabled) { return; } diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 29e7ac4e12..e5232d730c 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" +#include "llagent.h" #include "llavatarnamecache.h" #include "llavataractions.h" #include "llevents.h" @@ -374,7 +375,10 @@ void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t items; menuentry_vec_t disabled_items; - buildParticipantMenuOptions(items); + if(gAgent.getID() != mUUID) + { + buildParticipantMenuOptions(items); + } hide_context_entries(menu, items, disabled_items); } -- cgit v1.2.3 From ae093e02a126666c9137d9eb6d9aeea0c1c73a8a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 16 Oct 2012 11:38:36 -0700 Subject: CHUI-380: Realized that the when clicking the participant/conversation item that the active session wasn't being stored. This caused the right side conversation floater to not change when selecting a participant under a conersation. Resolution: now when clicking on a conversation or participant the active session is stored using setActiveSession(). --- indra/newview/llconversationview.cpp | 6 ++++++ indra/newview/llimfloatercontainer.h | 1 + 2 files changed, 7 insertions(+) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index b7ebb70e86..1b450665b3 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -242,6 +242,9 @@ void LLConversationViewSession::selectItem() // Set the focus on the selected floater session_floater->setFocus(TRUE); + // Store the active session + LLIMFloaterContainer::getInstance()->setSelectedSession(item->getUUID()); + LLFolderViewItem::selectItem(); } @@ -441,6 +444,9 @@ void LLConversationViewParticipant::selectItem() { LLIMFloater::show(vmi->getUUID()); } + + // Store the active session + container->setSelectedSession(vmi->getUUID()); } //Focus the current conversation floater (it is already visible so just focus it) else diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 6643471d97..579f62c688 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -89,6 +89,7 @@ public: LLConversationViewModel& getRootViewModel() { return mConversationViewModel; } LLUUID getSelectedSession() { return mSelectedSession; } + void setSelectedSession(LLUUID sessionID) { mSelectedSession = sessionID; } private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; -- cgit v1.2.3 From 337cd3aa9d8a8beaebd35ec6b53f09709e35a4d4 Mon Sep 17 00:00:00 2001 From: "Jeff (Gioffredo Linden)" <gioffredo@lindenlab.com> Date: Tue, 16 Oct 2012 15:22:42 -0400 Subject: Make getValue const to fix Windows builds - and be more robust --- indra/newview/llchathistory.cpp | 2 +- indra/newview/llchathistory.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index deb658c489..821d1f4685 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -596,7 +596,7 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this); } -LLSD LLChatHistory::getValue() +const LLSD LLChatHistory::getValue() { LLSD* text=new LLSD(); text->assign(mEditor->getText()); diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index effdd75911..b65d222b53 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -103,7 +103,7 @@ class LLChatHistory : public LLUICtrl public: ~LLChatHistory(); - LLSD getValue(); + const LLSD getValue(); void initFromParams(const Params&); /** -- cgit v1.2.3 From 86c3a45b6749387991064df6a42b1d046bd9d4d8 Mon Sep 17 00:00:00 2001 From: "Jeff (Gioffredo Linden)" <gioffredo@lindenlab.com> Date: Tue, 16 Oct 2012 16:08:25 -0400 Subject: Move const kw location --- indra/newview/llchathistory.cpp | 2 +- indra/newview/llchathistory.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 821d1f4685..c61a8c8562 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -596,7 +596,7 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this); } -const LLSD LLChatHistory::getValue() +LLSD LLChatHistory::getValue() const { LLSD* text=new LLSD(); text->assign(mEditor->getText()); diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index b65d222b53..bb6d4fb59c 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -103,7 +103,7 @@ class LLChatHistory : public LLUICtrl public: ~LLChatHistory(); - const LLSD getValue(); + LLSD getValue() const; void initFromParams(const Params&); /** -- cgit v1.2.3 From 1251f45e6246d81658cf4fe6f2654472c772e94b Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 17 Oct 2012 00:16:18 +0300 Subject: CHUI-394 FIXED Group moderation tools missing in right click menus --- indra/llui/llmenugl.cpp | 117 +++---- indra/llui/llmenugl.h | 35 +- indra/llui/lltoggleablemenu.cpp | 5 + indra/llui/lltoggleablemenu.h | 2 + indra/newview/llconversationmodel.cpp | 13 + indra/newview/llimfloatercontainer.cpp | 344 ++++++++++++++++---- indra/newview/llimfloatercontainer.h | 13 + indra/newview/llinventorybridge.cpp | 2 +- indra/newview/llparticipantlist.cpp | 361 --------------------- indra/newview/llparticipantlist.h | 75 ----- .../skins/default/xui/en/menu_conversation.xml | 45 +++ 11 files changed, 435 insertions(+), 577 deletions(-) (limited to 'indra') diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index ae4aa1e1dd..93dc13475b 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1764,6 +1764,26 @@ bool LLMenuGL::addChild(LLView* view, S32 tab_group) return false; } +// Used in LLContextMenu and in LLTogleableMenu + +// Add an item to the context menu branch +bool LLMenuGL::addContextChild(LLView* view, S32 tab_group) +{ + LLContextMenu* context = dynamic_cast<LLContextMenu*>(view); + if (context) + return appendContextSubMenu(context); + + LLMenuItemSeparatorGL* separator = dynamic_cast<LLMenuItemSeparatorGL*>(view); + if (separator) + return append(separator); + + LLMenuItemGL* item = dynamic_cast<LLMenuItemGL*>(view); + if (item) + return append(item); + + return false; +} + void LLMenuGL::removeChild( LLView* ctrl) { // previously a dynamic_cast with if statement to check validity @@ -2501,6 +2521,32 @@ BOOL LLMenuGL::appendMenu( LLMenuGL* menu ) return success; } +// add a context menu branch + +BOOL LLMenuGL::appendContextSubMenu(LLMenuGL *menu) + +{ + if (menu == this) + { + llerrs << "Can't attach a context menu to itself" << llendl; + } + + LLContextMenuBranch *item; + LLContextMenuBranch::Params p; + + p.name = menu->getName(); + p.label = menu->getLabel(); + p.branch = (LLContextMenu *)menu; + p.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor"); + p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor"); + p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor"); + p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor"); + item = LLUICtrlFactory::create<LLContextMenuBranch>(p); + LLMenuGL::sMenuContainer->addChild(item->getBranch()); + + return append( item ); +} + void LLMenuGL::setEnabledSubMenus(BOOL enable) { setEnabled(enable); @@ -3735,39 +3781,6 @@ void LLTearOffMenu::closeTearOff() mMenu->setDropShadowed(TRUE); } - -//----------------------------------------------------------------------------- -// class LLContextMenuBranch -// A branch to another context menu -//----------------------------------------------------------------------------- -class LLContextMenuBranch : public LLMenuItemGL -{ -public: - struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params> - { - Mandatory<LLContextMenu*> branch; - }; - - LLContextMenuBranch(const Params&); - - virtual ~LLContextMenuBranch() - {} - - // called to rebuild the draw label - virtual void buildDrawLabel( void ); - - // onCommit() - do the primary funcationality of the menu item. - virtual void onCommit( void ); - - LLContextMenu* getBranch() { return mBranch.get(); } - void setHighlight( BOOL highlight ); - -protected: - void showSubMenu(); - - LLHandle<LLContextMenu> mBranch; -}; - LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p) : LLMenuItemGL(p), mBranch( p.branch()->getHandle() ) @@ -4039,44 +4052,8 @@ BOOL LLContextMenu::handleRightMouseUp( S32 x, S32 y, MASK mask ) return result; } -BOOL LLContextMenu::appendContextSubMenu(LLContextMenu *menu) -{ - - if (menu == this) - { - llerrs << "Can't attach a context menu to itself" << llendl; - } - - LLContextMenuBranch *item; - LLContextMenuBranch::Params p; - p.name = menu->getName(); - p.label = menu->getLabel(); - p.branch = menu; - p.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor"); - p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor"); - p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor"); - p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor"); - - item = LLUICtrlFactory::create<LLContextMenuBranch>(p); - LLMenuGL::sMenuContainer->addChild(item->getBranch()); - - return append( item ); -} - bool LLContextMenu::addChild(LLView* view, S32 tab_group) { - LLContextMenu* context = dynamic_cast<LLContextMenu*>(view); - if (context) - return appendContextSubMenu(context); - - LLMenuItemSeparatorGL* separator = dynamic_cast<LLMenuItemSeparatorGL*>(view); - if (separator) - return append(separator); - - LLMenuItemGL* item = dynamic_cast<LLMenuItemGL*>(view); - if (item) - return append(item); - - return false; + return addContextChild(view, tab_group); } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index a9de3ef937..3e03232e92 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -519,6 +519,9 @@ public: void resetScrollPositionOnShow(bool reset_scroll_pos) { mResetScrollPositionOnShow = reset_scroll_pos; } bool isScrollPositionOnShowReset() { return mResetScrollPositionOnShow; } + // add a context menu branch + BOOL appendContextSubMenu(LLMenuGL *menu); + protected: void createSpilloverBranch(); void cleanupSpilloverBranch(); @@ -528,6 +531,10 @@ protected: // add a menu - this will create a cascading menu virtual BOOL appendMenu( LLMenuGL* menu ); + // Used in LLContextMenu and in LLTogleableMenu + // to add an item of context menu branch + bool addContextChild(LLView* view, S32 tab_group); + // TODO: create accessor methods for these? typedef std::list< LLMenuItemGL* > item_list_t; item_list_t mItems; @@ -677,8 +684,6 @@ public: virtual bool addChild (LLView* view, S32 tab_group = 0); - BOOL appendContextSubMenu(LLContextMenu *menu); - LLHandle<LLContextMenu> getHandle() { return getDerivedHandle<LLContextMenu>(); } LLView* getSpawningView() const { return mSpawningViewHandle.get(); } @@ -691,7 +696,33 @@ protected: LLHandle<LLView> mSpawningViewHandle; }; +//----------------------------------------------------------------------------- +// class LLContextMenuBranch +// A branch to another context menu +//----------------------------------------------------------------------------- +class LLContextMenuBranch : public LLMenuItemGL +{ +public: + struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params> + { + Mandatory<LLContextMenu*> branch; + }; + + LLContextMenuBranch(const Params&); + + // Called to rebuild strings for this item + virtual void buildDrawLabel( void ); + // Performed when menu item clicked + virtual void onCommit( void ); + + LLContextMenu* getBranch() { return mBranch.get(); } + void setHighlight( BOOL highlight ); + +protected: + void showSubMenu(); + LLHandle<LLContextMenu> mBranch; +}; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLMenuBarGL diff --git a/indra/llui/lltoggleablemenu.cpp b/indra/llui/lltoggleablemenu.cpp index d29260750f..b4c6c6162b 100644 --- a/indra/llui/lltoggleablemenu.cpp +++ b/indra/llui/lltoggleablemenu.cpp @@ -99,3 +99,8 @@ bool LLToggleableMenu::toggleVisibility() return true; } + +bool LLToggleableMenu::addChild(LLView* view, S32 tab_group) +{ + return addContextChild(view, tab_group); +} diff --git a/indra/llui/lltoggleablemenu.h b/indra/llui/lltoggleablemenu.h index dd9ac5b8c1..57b8f62eb6 100644 --- a/indra/llui/lltoggleablemenu.h +++ b/indra/llui/lltoggleablemenu.h @@ -47,6 +47,8 @@ public: virtual void handleVisibilityChange (BOOL curVisibilityIn); + virtual bool addChild (LLView* view, S32 tab_group = 0); + const LLRect& getButtonRect() const { return mButtonRect; } // Converts the given local button rect to a screen rect diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index e5232d730c..f0c8658cfe 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -114,6 +114,19 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items) items.push_back(std::string("share")); items.push_back(std::string("pay")); items.push_back(std::string("block_unblock")); + + if(this->getType() != CONV_SESSION_1_ON_1) + { + items.push_back(std::string("Moderator Options Separator")); + items.push_back(std::string("Moderator Options")); + items.push_back(std::string("AllowTextChat")); + items.push_back(std::string("moderate_voice_separator")); + items.push_back(std::string("ModerateVoiceMuteSelected")); + items.push_back(std::string("ModerateVoiceUnMuteSelected")); + items.push_back(std::string("ModerateVoiceMute")); + items.push_back(std::string("ModerateVoiceUnmute")); + } + } // diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 5c1105531e..c9c7e94af9 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -44,6 +44,7 @@ #include "llfloateravatarpicker.h" #include "llfloaterpreference.h" #include "llimview.h" +#include "llnotificationsutil.h" #include "lltransientfloatermgr.h" #include "llviewercontrol.h" #include "llconversationview.h" @@ -830,59 +831,67 @@ void LLIMFloaterContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) void LLIMFloaterContainer::doToParticipants(const std::string& command, uuid_vec_t& selectedIDS) { - if(selectedIDS.size() > 0) -{ - const LLUUID userID = selectedIDS.front(); + if(selectedIDS.size() > 0) + { + const LLUUID& userID = selectedIDS.front(); - if ("view_profile" == command) - { - LLAvatarActions::showProfile(userID); - } - else if("im" == command) - { - LLAvatarActions::startIM(userID); - } - else if("offer_teleport" == command) - { - LLAvatarActions::offerTeleport(selectedIDS); - } - else if("voice_call" == command) - { - LLAvatarActions::startCall(userID); - } - else if("chat_history" == command) - { - LLAvatarActions::viewChatHistory(userID); - } - else if("add_friend" == command) - { - LLAvatarActions::requestFriendshipDialog(userID); - } - else if("remove_friend" == command) - { - LLAvatarActions::removeFriendDialog(userID); - } - else if("invite_to_group" == command) - { - LLAvatarActions::inviteToGroup(userID); - } - else if("map" == command) - { - LLAvatarActions::showOnMap(userID); - } - else if("share" == command) - { - LLAvatarActions::share(userID); - } - else if("pay" == command) - { - LLAvatarActions::pay(userID); - } - else if("block_unblock" == command) - { - LLAvatarActions::toggleBlock(userID); - } -} + if ("view_profile" == command) + { + LLAvatarActions::showProfile(userID); + } + else if("im" == command) + { + LLAvatarActions::startIM(userID); + } + else if("offer_teleport" == command) + { + LLAvatarActions::offerTeleport(selectedIDS); + } + else if("voice_call" == command) + { + LLAvatarActions::startCall(userID); + } + else if("chat_history" == command) + { + LLAvatarActions::viewChatHistory(userID); + } + else if("add_friend" == command) + { + LLAvatarActions::requestFriendshipDialog(userID); + } + else if("remove_friend" == command) + { + LLAvatarActions::removeFriendDialog(userID); + } + else if("invite_to_group" == command) + { + LLAvatarActions::inviteToGroup(userID); + } + else if("map" == command) + { + LLAvatarActions::showOnMap(userID); + } + else if("share" == command) + { + LLAvatarActions::share(userID); + } + else if("pay" == command) + { + LLAvatarActions::pay(userID); + } + else if("block_unblock" == command) + { + LLAvatarActions::toggleBlock(userID); + } + else if("selected" == command || "mute_all" == command || "unmute_all" == command) + { + moderateVoice(command, userID); + } + else if ("toggle_allow_text_chat" == command) + { + toggleAllowTextChat(userID); + } + } } void LLIMFloaterContainer::doToSelectedConversation(const std::string& command, uuid_vec_t& selectedIDS) @@ -963,8 +972,8 @@ void LLIMFloaterContainer::doToSelectedGroup(const LLSD& userdata) bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) { std::string item = userdata.asString(); - uuid_vec_t mUUIDs; - getParticipantUUIDs(mUUIDs); + uuid_vec_t uuids; + getParticipantUUIDs(uuids); if(item == std::string("can_activate_group")) { @@ -972,7 +981,7 @@ bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) return gAgent.getGroupID() != selected_group_id; } - if(mUUIDs.size() <= 0) + if(uuids.size() <= 0) { return false; } @@ -982,7 +991,7 @@ bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) if (item == std::string("can_block")) { - const LLUUID& id = mUUIDs.front(); + const LLUUID& id = uuids.front(); return LLAvatarActions::canBlock(id); } else if (item == std::string("can_add")) @@ -992,7 +1001,7 @@ bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) // - and there are no friends among selection yet. //EXT-7389 - disable for more than 1 - if(mUUIDs.size() > 1) + if(uuids.size() > 1) { return false; } @@ -1000,8 +1009,8 @@ bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) bool result = true; uuid_vec_t::const_iterator - id = mUUIDs.begin(), - uuids_end = mUUIDs.end(); + id = uuids.begin(), + uuids_end = uuids.end(); for (;id != uuids_end; ++id) { @@ -1020,11 +1029,11 @@ bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) // - there are selected people // - and there are only friends among selection. - bool result = (mUUIDs.size() > 0); + bool result = (uuids.size() > 0); uuid_vec_t::const_iterator - id = mUUIDs.begin(), - uuids_end = mUUIDs.end(); + id = uuids.begin(), + uuids_end = uuids.end(); for (;id != uuids_end; ++id) { @@ -1043,15 +1052,20 @@ bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) } else if (item == std::string("can_show_on_map")) { - const LLUUID& id = mUUIDs.front(); + const LLUUID& id = uuids.front(); return (LLAvatarTracker::instance().isBuddyOnline(id) && is_agent_mappable(id)) || gAgent.isGodlike(); } else if(item == std::string("can_offer_teleport")) { - return LLAvatarActions::canOfferTeleport(mUUIDs); + return LLAvatarActions::canOfferTeleport(uuids); } + else if("can_moderate_voice" == item || "can_allow_text_chat" == item || "can_mute" == item || "can_unmute" == item) + { + return enableModerateContextMenuItem(item); + } + return false; } @@ -1063,10 +1077,19 @@ bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata) if(mUUIDs.size() > 0 ) { - if (item == std::string("is_blocked")) - { - return LLAvatarActions::isBlocked(mUUIDs.front()); - } + if ("is_blocked" == item) + { + return LLAvatarActions::isBlocked(mUUIDs.front()); + } + else if ("is_allowed_text_chat" == item) + { + const LLSpeaker * speakerp = getSpeakerOfSelectedParticipant(getSpeakerMgrForSelectedParticipant()); + + if (NULL != speakerp) + { + return !speakerp->mModeratorMutedText; + } + } } return false; @@ -1284,4 +1307,189 @@ LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParti return LLUICtrlFactory::create<LLConversationViewParticipant>(params); } +bool LLIMFloaterContainer::enableModerateContextMenuItem(const std::string& userdata) +{ + // only group moderators can perform actions related to this "enable callback" + if (!isGroupModerator()) + { + return false; + } + + LLSpeaker * speakerp = getSpeakerOfSelectedParticipant(getSpeakerMgrForSelectedParticipant()); + if (NULL == speakerp) + { + return false; + } + + bool voice_channel = speakerp->isInVoiceChannel(); + + if ("can_moderate_voice" == userdata) + { + return voice_channel; + } + else if ("can_mute" == userdata) + { + return voice_channel && !isMuted(getCurSelectedViewModelItem()->getUUID()); + } + else if ("can_unmute" == userdata) + { + return voice_channel && isMuted(getCurSelectedViewModelItem()->getUUID()); + } + + // The last invoke is used to check whether the "can_allow_text_chat" will enabled + return LLVoiceClient::getInstance()->isParticipantAvatar(getCurSelectedViewModelItem()->getUUID()); +} + +bool LLIMFloaterContainer::isGroupModerator() +{ + LLSpeakerMgr * speaker_manager = getSpeakerMgrForSelectedParticipant(); + if (NULL == speaker_manager) + { + llwarns << "Speaker manager is missing" << llendl; + return false; + } + + // Is session a group call/chat? + if(gAgent.isInGroup(speaker_manager->getSessionID())) + { + LLSpeaker * speaker = speaker_manager->findSpeaker(gAgentID).get(); + + // Is agent a moderator? + return speaker && speaker->mIsModerator; + } + + return false; +} + +void LLIMFloaterContainer::moderateVoice(const std::string& command, const LLUUID& userID) +{ + if (!gAgent.getRegion()) return; + + if (command.compare("selected")) + { + moderateVoiceAllParticipants(command.compare("mute_all")); + } + else + { + moderateVoiceParticipant(userID, isMuted(userID)); + } +} + +bool LLIMFloaterContainer::isMuted(const LLUUID& avatar_id) +{ + const LLSpeaker * speakerp = getSpeakerOfSelectedParticipant(getSpeakerMgrForSelectedParticipant()); + return NULL == speakerp ? true : speakerp->mStatus == LLSpeaker::STATUS_MUTED; +} + +void LLIMFloaterContainer::moderateVoiceAllParticipants(bool unmute) +{ + LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr*>(getSpeakerMgrForSelectedParticipant()); + + if (NULL != speaker_managerp) + { + if (!unmute) + { + LLSD payload; + payload["session_id"] = speaker_managerp->getSessionID(); + LLNotificationsUtil::add("ConfirmMuteAll", LLSD(), payload, confirmMuteAllCallback); + return; + } + + speaker_managerp->moderateVoiceAllParticipants(unmute); + } +} + +// static +void LLIMFloaterContainer::confirmMuteAllCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + // if Cancel pressed + if (option == 1) + { + return; + } + + const LLSD& payload = notification["payload"]; + const LLUUID& session_id = payload["session_id"]; + + LLIMSpeakerMgr * speaker_manager = dynamic_cast<LLIMSpeakerMgr*> ( + LLIMModel::getInstance()->getSpeakerManager(session_id)); + if (speaker_manager) + { + speaker_manager->moderateVoiceAllParticipants(false); + } + + return; +} + +void LLIMFloaterContainer::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute) +{ + LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr *>(getSpeakerMgrForSelectedParticipant()); + + if (NULL != speaker_managerp) + { + speaker_managerp->moderateVoiceParticipant(avatar_id, unmute); + } +} + +LLSpeakerMgr * LLIMFloaterContainer::getSpeakerMgrForSelectedParticipant() +{ + LLFolderViewItem * selected_folder_itemp = mConversationsRoot->getCurSelectedItem(); + if (NULL == selected_folder_itemp) + { + llwarns << "Current selected item is null" << llendl; + return NULL; + } + + LLFolderViewFolder * conversation_itemp = selected_folder_itemp->getParentFolder(); + + conversations_widgets_map::const_iterator iter = mConversationsWidgets.begin(); + conversations_widgets_map::const_iterator end = mConversationsWidgets.end(); + const LLUUID * conversation_uuidp = NULL; + while(iter != end) + { + if (iter->second == conversation_itemp) + { + conversation_uuidp = &iter->first; + break; + } + ++iter; + } + if (NULL == conversation_uuidp) + { + llwarns << "Cannot find conversation item widget" << llendl; + return NULL; + } + + return conversation_uuidp->isNull() ? (LLSpeakerMgr *)LLLocalSpeakerMgr::getInstance() + : LLIMModel::getInstance()->getSpeakerManager(*conversation_uuidp); +} + +LLSpeaker * LLIMFloaterContainer::getSpeakerOfSelectedParticipant(LLSpeakerMgr * speaker_managerp) +{ + if (NULL == speaker_managerp) + { + llwarns << "Speaker manager is missing" << llendl; + return NULL; + } + + const LLConversationItem * participant_itemp = getCurSelectedViewModelItem(); + if (NULL == participant_itemp) + { + llwarns << "Cannot evaluate current selected view model item" << llendl; + return NULL; + } + + return speaker_managerp->findSpeaker(participant_itemp->getUUID()); +} + +void LLIMFloaterContainer::toggleAllowTextChat(const LLUUID& participant_uuid) +{ + LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr*>(getSpeakerMgrForSelectedParticipant()); + if (NULL != speaker_managerp) + { + speaker_managerp->toggleAllowTextChat(participant_uuid); + } +} + // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 579f62c688..ba2d085858 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -45,6 +45,8 @@ class LLLayoutPanel; class LLLayoutStack; class LLTabContainer; class LLIMFloaterContainer; +class LLSpeaker; +class LLSpeakerMgr; class LLIMFloaterContainer : public LLMultiFloater @@ -126,6 +128,17 @@ private: bool checkContextMenuItem(const LLSD& userdata); bool enableContextMenuItem(const LLSD& userdata); + static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response); + bool enableModerateContextMenuItem(const std::string& userdata); + LLSpeaker * getSpeakerOfSelectedParticipant(LLSpeakerMgr * speaker_managerp); + LLSpeakerMgr * getSpeakerMgrForSelectedParticipant(); + bool isGroupModerator(); + bool isMuted(const LLUUID& avatar_id); + void moderateVoice(const std::string& command, const LLUUID& userID); + void moderateVoiceAllParticipants(bool unmute); + void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); + void toggleAllowTextChat(const LLUUID& participant_uuid); + LLButton* mExpandCollapseBtn; LLLayoutPanel* mMessagesPane; LLLayoutPanel* mConversationsPane; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 139713b96e..28c2edbe84 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -577,7 +577,7 @@ void hide_context_entries(LLMenuGL& menu, // descend into split menus: LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(menu_item); - if ((name == "More") && branchp) + if (NULL != branchp) { hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries); } diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 90226e7fba..b263143bd1 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -213,7 +213,6 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLConversationItemSession(data_source->getSessionID(), root_view_model), mSpeakerMgr(data_source), mAvatarList(avatar_list), - mParticipantListMenu(NULL), mExcludeAgent(exclude_agent), mValidateSpeakerCallback(NULL) { @@ -248,8 +247,6 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, if (use_context_menu) { - //mParticipantListMenu = new LLParticipantListMenu(*this); - //mAvatarList->setContextMenu(mParticipantListMenu); mAvatarList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); } else @@ -316,20 +313,6 @@ LLParticipantList::~LLParticipantList() mAvatarListToggleIconsConnection.disconnect(); } - // It is possible Participant List will be re-created from LLCallFloater::onCurrentChannelChanged() - // See ticket EXT-3427 - // hide menu before deleting it to stop enable and check handlers from triggering. - if(mParticipantListMenu && !LLApp::isExiting()) - { - mParticipantListMenu->hide(); - } - - if (mParticipantListMenu) - { - delete mParticipantListMenu; - mParticipantListMenu = NULL; - } - if (mAvatarList) { mAvatarList->setContextMenu(NULL); @@ -786,350 +769,6 @@ bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents:: return mParent.onSpeakerMuteEvent(event, userdata); } -/*LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() -{ - // set up the callbacks for all of the avatar menu items - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - - registrar.add("ParticipantList.Sort", boost::bind(&LLParticipantList::LLParticipantListMenu::sortParticipantList, this, _2)); - registrar.add("ParticipantList.ToggleAllowTextChat", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleAllowTextChat, this, _2)); - registrar.add("ParticipantList.ToggleMuteText", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteText, this, _2)); - - registrar.add("Avatar.Profile", boost::bind(&LLAvatarActions::showProfile, mUUIDs.front())); - registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, mUUIDs.front())); - registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs.front())); - registrar.add("Avatar.BlockUnblock", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteVoice, this, _2)); - registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, mUUIDs.front())); - registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs.front())); - registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, mUUIDs.front())); - - registrar.add("ParticipantList.ModerateVoice", boost::bind(&LLParticipantList::LLParticipantListMenu::moderateVoice, this, _2)); - - enable_registrar.add("ParticipantList.EnableItem", boost::bind(&LLParticipantList::LLParticipantListMenu::enableContextMenuItem, this, _2)); - enable_registrar.add("ParticipantList.EnableItem.Moderate", boost::bind(&LLParticipantList::LLParticipantListMenu::enableModerateContextMenuItem, this, _2)); - enable_registrar.add("ParticipantList.CheckItem", boost::bind(&LLParticipantList::LLParticipantListMenu::checkContextMenuItem, this, _2)); - - // create the context menu from the XUI - LLContextMenu* main_menu = createFromFile("menu_participant_list.xml"); - - // Don't show sort options for P2P chat - bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1); - main_menu->setItemVisible("SortByName", is_sort_visible); - main_menu->setItemVisible("SortByRecentSpeakers", is_sort_visible); - main_menu->setItemVisible("Moderator Options Separator", isGroupModerator()); - main_menu->setItemVisible("Moderator Options", isGroupModerator()); - main_menu->setItemVisible("View Icons Separator", mParent.mAvatarListToggleIconsConnection.connected()); - main_menu->setItemVisible("View Icons", mParent.mAvatarListToggleIconsConnection.connected()); - main_menu->arrangeAndClear(); - - return main_menu; -}*/ - -void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y) -{ - if (uuids.size() == 0) return; - - LLListContextMenu::show(spawning_view, uuids, x, y); - - const LLUUID& speaker_id = mUUIDs.front(); - BOOL is_muted = isMuted(speaker_id); - - if (is_muted) - { - LLMenuGL::sMenuContainer->getChildView("ModerateVoiceMuteSelected")->setVisible( false); - } - else - { - LLMenuGL::sMenuContainer->getChildView("ModerateVoiceUnMuteSelected")->setVisible( false); - } -} - -void LLParticipantList::LLParticipantListMenu::sortParticipantList(const LLSD& userdata) -{ - std::string param = userdata.asString(); - if ("sort_by_name" == param) - { - mParent.setSortOrder(E_SORT_BY_NAME); - } - else if ("sort_by_recent_speakers" == param) - { - mParent.setSortOrder(E_SORT_BY_RECENT_SPEAKERS); - } -} - -void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& userdata) -{ - - LLIMSpeakerMgr* mgr = dynamic_cast<LLIMSpeakerMgr*>(mParent.mSpeakerMgr); - if (mgr) - { - const LLUUID speaker_id = mUUIDs.front(); - mgr->toggleAllowTextChat(speaker_id); - } -} - -void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata, U32 flags) -{ - const LLUUID speaker_id = mUUIDs.front(); - BOOL is_muted = LLMuteList::getInstance()->isMuted(speaker_id, flags); - std::string name; - - //fill in name using voice client's copy of name cache - LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(speaker_id); - if (speakerp.isNull()) - { - LL_WARNS("Speakers") << "Speaker " << speaker_id << " not found" << llendl; - return; - } - LLAvatarListItem* item = (mParent.mAvatarList ? dynamic_cast<LLAvatarListItem*>(mParent.mAvatarList->getItemByValue(speaker_id)) : NULL); - if (NULL == item) return; - - name = item->getAvatarName(); - - LLMute::EType mute_type; - switch (speakerp->mType) - { - case LLSpeaker::SPEAKER_AGENT: - mute_type = LLMute::AGENT; - break; - case LLSpeaker::SPEAKER_OBJECT: - mute_type = LLMute::OBJECT; - break; - case LLSpeaker::SPEAKER_EXTERNAL: - default: - mute_type = LLMute::EXTERNAL; - break; - } - LLMute mute(speaker_id, name, mute_type); - - if (!is_muted) - { - LLMuteList::getInstance()->add(mute, flags); - } - else - { - LLMuteList::getInstance()->remove(mute, flags); - } -} - -void LLParticipantList::LLParticipantListMenu::toggleMuteText(const LLSD& userdata) -{ - toggleMute(userdata, LLMute::flagTextChat); -} - -void LLParticipantList::LLParticipantListMenu::toggleMuteVoice(const LLSD& userdata) -{ - toggleMute(userdata, LLMute::flagVoiceChat); -} - -bool LLParticipantList::LLParticipantListMenu::isGroupModerator() -{ - if (!mParent.mSpeakerMgr) - { - llwarns << "Speaker manager is missing" << llendl; - return false; - } - - // Is session a group call/chat? - if(gAgent.isInGroup(mParent.mSpeakerMgr->getSessionID())) - { - LLSpeaker* speaker = mParent.mSpeakerMgr->findSpeaker(gAgentID).get(); - - // Is agent a moderator? - return speaker && speaker->mIsModerator; - } - return false; -} - -bool LLParticipantList::LLParticipantListMenu::isMuted(const LLUUID& avatar_id) -{ - LLPointer<LLSpeaker> selected_speakerp = mParent.mSpeakerMgr->findSpeaker(avatar_id); - if (!selected_speakerp) return true; - - return selected_speakerp->mStatus == LLSpeaker::STATUS_MUTED; -} - -void LLParticipantList::LLParticipantListMenu::moderateVoice(const LLSD& userdata) -{ - if (!gAgent.getRegion()) return; - - bool moderate_selected = userdata.asString() == "selected"; - - if (moderate_selected) - { - const LLUUID& selected_avatar_id = mUUIDs.front(); - bool is_muted = isMuted(selected_avatar_id); - moderateVoiceParticipant(selected_avatar_id, is_muted); - } - else - { - bool unmute_all = userdata.asString() == "unmute_all"; - moderateVoiceAllParticipants(unmute_all); - } -} - -void LLParticipantList::LLParticipantListMenu::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute) -{ - LLIMSpeakerMgr* mgr = dynamic_cast<LLIMSpeakerMgr*>(mParent.mSpeakerMgr); - if (mgr) - { - mgr->moderateVoiceParticipant(avatar_id, unmute); - } -} - -void LLParticipantList::LLParticipantListMenu::moderateVoiceAllParticipants(bool unmute) -{ - LLIMSpeakerMgr* mgr = dynamic_cast<LLIMSpeakerMgr*>(mParent.mSpeakerMgr); - if (mgr) - { - if (!unmute) - { - LLSD payload; - payload["session_id"] = mgr->getSessionID(); - LLNotificationsUtil::add("ConfirmMuteAll", LLSD(), payload, confirmMuteAllCallback); - return; - } - - mgr->moderateVoiceAllParticipants(unmute); - } -} - -// static -void LLParticipantList::LLParticipantListMenu::confirmMuteAllCallback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - // if Cancel pressed - if (option == 1) - { - return; - } - - const LLSD& payload = notification["payload"]; - const LLUUID& session_id = payload["session_id"]; - - LLIMSpeakerMgr * speaker_manager = dynamic_cast<LLIMSpeakerMgr*> ( - LLIMModel::getInstance()->getSpeakerManager(session_id)); - if (speaker_manager) - { - speaker_manager->moderateVoiceAllParticipants(false); - } - - return; -} - - -bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& userdata) -{ - std::string item = userdata.asString(); - const LLUUID& participant_id = mUUIDs.front(); - - // For now non of "can_view_profile" action and menu actions listed below except "can_block" - // can be performed for Avaline callers. - bool is_participant_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(participant_id); - if (!is_participant_avatar && "can_block" != item) return false; - - if (item == "can_mute_text" || "can_block" == item || "can_share" == item || "can_im" == item - || "can_pay" == item) - { - return mUUIDs.front() != gAgentID; - } - else if (item == std::string("can_add")) - { - // We can add friends if: - // - there are selected people - // - and there are no friends among selection yet. - - bool result = (mUUIDs.size() > 0); - - uuid_vec_t::const_iterator - id = mUUIDs.begin(), - uuids_end = mUUIDs.end(); - - for (;id != uuids_end; ++id) - { - if ( *id == gAgentID || LLAvatarActions::isFriend(*id) ) - { - result = false; - break; - } - } - return result; - } - else if (item == "can_call") - { - bool not_agent = mUUIDs.front() != gAgentID; - bool can_call = not_agent && LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); - return can_call; - } - - return true; -} - -/* - Processed menu items with such parameters: - can_allow_text_chat - can_moderate_voice -*/ -bool LLParticipantList::LLParticipantListMenu::enableModerateContextMenuItem(const LLSD& userdata) -{ - // only group moderators can perform actions related to this "enable callback" - if (!isGroupModerator()) return false; - - const LLUUID& participant_id = mUUIDs.front(); - LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(participant_id); - - // not in voice participants can not be moderated - bool speaker_in_voice = speakerp.notNull() && speakerp->isInVoiceChannel(); - - const std::string& item = userdata.asString(); - - if ("can_moderate_voice" == item) - { - return speaker_in_voice; - } - - // For now non of menu actions except "can_moderate_voice" can be performed for Avaline callers. - bool is_participant_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(participant_id); - if (!is_participant_avatar) return false; - - return true; -} - -bool LLParticipantList::LLParticipantListMenu::checkContextMenuItem(const LLSD& userdata) -{ - std::string item = userdata.asString(); - const LLUUID& id = mUUIDs.front(); - - if (item == "is_muted") - { - return LLMuteList::getInstance()->isMuted(id, LLMute::flagTextChat); - } - else if (item == "is_allowed_text_chat") - { - LLPointer<LLSpeaker> selected_speakerp = mParent.mSpeakerMgr->findSpeaker(id); - - if (selected_speakerp.notNull()) - { - return !selected_speakerp->mModeratorMutedText; - } - } - else if(item == "is_blocked") - { - return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat); - } - else if(item == "is_sorted_by_name") - { - return E_SORT_BY_NAME == mParent.getSortOrder(); - } - else if(item == "is_sorted_by_recent_speakers") - { - return E_SORT_BY_RECENT_SPEAKERS == mParent.getSortOrder(); - } - - return false; -} - bool LLParticipantList::LLAvatarItemRecentSpeakerComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const { if (mParent.mSpeakerMgr) diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index acee68873c..aaf1e070a5 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -159,79 +159,6 @@ protected: /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); }; - /** - * Menu used in the participant list. - */ - class LLParticipantListMenu : public LLListContextMenu - { - public: - LLParticipantListMenu(LLParticipantList& parent):mParent(parent){}; - /*virtual*/ LLContextMenu* createMenu(); - /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); - protected: - LLParticipantList& mParent; - private: - bool enableContextMenuItem(const LLSD& userdata); - bool enableModerateContextMenuItem(const LLSD& userdata); - bool checkContextMenuItem(const LLSD& userdata); - - void sortParticipantList(const LLSD& userdata); - void toggleAllowTextChat(const LLSD& userdata); - void toggleMute(const LLSD& userdata, U32 flags); - void toggleMuteText(const LLSD& userdata); - void toggleMuteVoice(const LLSD& userdata); - - /** - * Return true if Agent is group moderator(and moderator of group call). - */ - bool isGroupModerator(); - - // Voice moderation support - /** - * Check whether specified by argument avatar is muted for group chat or not. - */ - bool isMuted(const LLUUID& avatar_id); - - /** - * Processes Voice moderation menu items. - * - * It calls either moderateVoiceParticipant() or moderateVoiceParticipant() depend on - * passed parameter. - * - * @param userdata can be "selected" or "others". - * - * @see moderateVoiceParticipant() - * @see moderateVoiceAllParticipants() - */ - void moderateVoice(const LLSD& userdata); - - /** - * Mutes/Unmutes avatar for current group voice chat. - * - * It only marks avatar as muted for session and does not use local Agent's Block list. - * It does not mute Agent itself. - * - * @param[in] avatar_id UUID of avatar to be processed - * @param[in] unmute if true - specified avatar will be muted, otherwise - unmuted. - * - * @see moderateVoiceAllParticipants() - */ - void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); - - /** - * Mutes/Unmutes all avatars for current group voice chat. - * - * It only marks avatars as muted for session and does not use local Agent's Block list. - * - * @param[in] unmute if true - avatars will be muted, otherwise - unmuted. - * - * @see moderateVoiceParticipant() - */ - void moderateVoiceAllParticipants(bool unmute); - - static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response); - }; - /** * Comparator for comparing avatar items by last spoken time */ @@ -276,8 +203,6 @@ private: LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener; LLPointer<SpeakerMuteListener> mSpeakerMuteListener; - LLParticipantListMenu* mParticipantListMenu; - /** * This field manages an adding a new avatar_id in the mAvatarList * If true, then agent_id wont be added into mAvatarList diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index 682d70e4f0..2e9bda5804 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -125,4 +125,49 @@ name="leave_group"> <on_click function="Group.DoToSelected" parameter="leave_group"/> </menu_item_call> + <menu_item_separator + layout="topleft" + name="Moderator Options Separator"/> + <context_menu + label="Moderator Options" + layout="topleft" + name="Moderator Options"> + <menu_item_check + label="Allow text chat" + layout="topleft" + name="AllowTextChat"> + <on_check function="Avatar.CheckItem" parameter="is_allowed_text_chat" /> + <on_click function="Avatar.DoToSelected" parameter="toggle_allow_text_chat" /> + <on_enable function="Avatar.EnableItem" parameter="can_allow_text_chat" /> + </menu_item_check> + <menu_item_separator layout="topleft" name="moderate_voice_separator" /> + <menu_item_call + label="Mute this participant" + layout="topleft" + name="ModerateVoiceMuteSelected"> + <on_click function="Avatar.DoToSelected" parameter="selected" /> + <on_enable function="Avatar.EnableItem" parameter="can_mute" /> + </menu_item_call> + <menu_item_call + label="Unmute this participant" + layout="topleft" + name="ModerateVoiceUnMuteSelected"> + <on_click function="Avatar.DoToSelected" parameter="selected" /> + <on_enable function="Avatar.EnableItem" parameter="can_unmute" /> + </menu_item_call> + <menu_item_call + label="Mute everyone" + layout="topleft" + name="ModerateVoiceMute"> + <on_click function="Avatar.DoToSelected" parameter="mute_all" /> + <on_enable function="Avatar.EnableItem" parameter="can_moderate_voice" /> + </menu_item_call> + <menu_item_call + label="Unmute everyone" + layout="topleft" + name="ModerateVoiceUnmute"> + <on_click function="Avatar.DoToSelected" parameter="unmute_all" /> + <on_enable function="Avatar.EnableItem" parameter="can_moderate_voice" /> + </menu_item_call> + </context_menu> </toggleable_menu> -- cgit v1.2.3 From 30a04430df02c6f3e949af0e457fe4ed49474ee3 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 17 Oct 2012 19:16:13 +0300 Subject: CHUI-419 FIXED Selecting the drop down arrow to list participants for a conversation does not select that conversation --- indra/newview/llconversationview.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 1b450665b3..9144f402b4 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -222,6 +222,13 @@ void LLConversationViewSession::toggleOpen() if (!mMinimizedMode) { LLFolderViewFolder::toggleOpen(); + + // do item's selection when opened + if (LLFolderViewFolder::isOpen()) + { + getParentFolder()->setSelection(this, true); + } + } } -- cgit v1.2.3 From d60609e0096bc7ede9edde1ba6d103f5f860af0d Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 17 Oct 2012 12:26:40 -0700 Subject: MAINT-1551 : WIP : More tests to elicit a correct answer from the backbone server --- indra/newview/llimview.cpp | 1 + indra/newview/llspeakers.cpp | 52 +++++++++++++++++++++++++++++++++++--------- indra/newview/llspeakers.h | 2 ++ 3 files changed, 45 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 398584e005..e6f93aa9be 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -238,6 +238,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& //we need to wait for session initialization for outgoing ad-hoc and group chat session //correct session id for initiated ad-hoc chat will be received from the server + // Merov : MAINT-1551 : We need to read that mInitialTargetIDs when initializing the conversation if (!LLIMModel::getInstance()->sendStartSession(mSessionID, mOtherParticipantID, mInitialTargetIDs, mType)) { diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 11d1b563ac..217efdf4af 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -307,7 +307,7 @@ public: virtual void error(U32 status, const std::string& reason) { - llinfos << "Merov debug : UpdateResponder error, status = " << status << ": " << reason << llendl; + llinfos << "Merov debug : UpdateResponder error, on " << mSessionID << ", status = " << status << ": " << reason << llendl; } private: @@ -322,8 +322,11 @@ LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) : mVoiceChannel(channelp) , mVoiceModerated(false) , mModerateModeHandledFirstTime(false) +, mSessionUpdated(false) +, mSessionID() { static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0); +// mSessionID = getSessionID(); mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay); } @@ -547,7 +550,7 @@ void LLSpeakerMgr::updateSpeakerList() LLUUID session_id = getSessionID(); if ((mSpeakers.size() == 0) && (!session_id.isNull())) { - llinfos << "Merov debug : LLSpeakerMgr::updateSpeakerList: No speakers in " << session_id << llendl; + //llinfos << "Merov debug : LLSpeakerMgr::updateSpeakerList: No speakers in " << session_id << llendl; // MAINT-1551 : If the list is empty for too long, we should send a message to the sim so that // it sends the participant list again. updateSession(); @@ -557,21 +560,50 @@ void LLSpeakerMgr::updateSpeakerList() void LLSpeakerMgr::updateSession() { + // We perform this update if is has never been done or if the session id changed (which happens in ad-hoc sessions) + if (mSessionUpdated && (mSessionID == getSessionID())) + return; + std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); LLSD data; - data["method"] = "accept invitation"; -// data["method"] = "session update"; + +// That doesn't work apparently because we are not in the invite list so we get error 500 +// data["method"] = "accept invitation"; +// data["session-id"] = getSessionID(); + +// That doesn't work because we're not a moderator on an IM session so our request is rejected as such (error 403) + data["method"] = "session update"; + data["session-id"] = getSessionID(); + data["params"] = LLSD::emptyMap(); + data["params"]["update_info"] = LLSD::emptyMap(); + data["params"]["update_info"]["moderated_mode"] = LLSD::emptyMap(); + data["params"]["update_info"]["moderated_mode"]["voice"] = false; + +// That doesn't work, we eventually time out (error 502)... +// data["method"] = "call"; +// data["session-id"] = getSessionID(); + + data["params"] = LLSD::emptyArray(); +// for (int i = 0; i < count; i++) +// { +// data["params"].append(ids[i]); +// } + data["params"].append(gAgentID); + data["method"] = "invite"; data["session-id"] = getSessionID(); -// data["params"] = LLSD::emptyMap(); - -// data["params"]["update_info"] = LLSD::emptyMap(); - -// data["params"]["update_info"]["moderated_mode"] = LLSD::emptyMap(); -// data["params"]["update_info"]["moderated_mode"]["voice"] = false; llinfos << "Merov debug : viewer->sim : LLSpeakerMgr::updateSession, session id = " << getSessionID() << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post(url, data, new UpdateResponder(getSessionID())); + + // bit of extra in the case of invite being sent + data.clear(); + data["method"] = "accept invitation"; + data["session-id"] = getSessionID(); + LLHTTPClient::post(url, data, new UpdateResponder(getSessionID())); + + mSessionUpdated = true; + mSessionID = getSessionID(); } void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp) diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 671b3fb341..8a80c4619e 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -259,6 +259,8 @@ protected: bool removeSpeaker(const LLUUID& speaker_id); void updateSession(); + bool mSessionUpdated; + LLUUID mSessionID; typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t; speaker_map_t mSpeakers; -- cgit v1.2.3 From 8a42d5cea3787edf294eec135af38c12ae322325 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Thu, 18 Oct 2012 00:04:46 +0300 Subject: CHUI-399 (When user has Pressing Letter Keys starts local chat setting on, first presses of letter keys do not open chat) fixed --- indra/newview/llviewerwindow.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 403288b2fd..f80abc816f 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2561,9 +2561,16 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) // If "Pressing letter keys starts local chat" option is selected, we are not in mouselook, // no view has keyboard focus, this is a printable character key (and no modifier key is // pressed except shift), then give focus to nearby chat (STORM-560) - if ( nearby_chat && gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && - !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) - { + if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && + !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) + { + // Initialize nearby chat if it's missing + if (!nearby_chat) + { + LLSD name("im_container"); + LLFloaterReg::toggleInstanceOrBringToFront(name); + } + LLChatEntry* chat_editor = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")->getChatBox(); if (chat_editor) { -- cgit v1.2.3 From 05a72687d848c13754039f6e720a137827533fdb Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 17 Oct 2012 14:55:36 -0700 Subject: CHUI-410: Now when a converation floater is focused the default text 'To <Some User>' displays only when the text input field is empty. --- indra/llui/llchatentry.cpp | 28 ++++++++++++++++++++++ indra/llui/llchatentry.h | 5 ++++ indra/llui/lltextbase.cpp | 20 ++++++++++++++-- indra/llui/lltextbase.h | 4 +++- .../skins/default/xui/en/floater_im_session.xml | 3 ++- 5 files changed, 56 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index 2a6ccc3dc9..38e2a8106a 100644 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -136,6 +136,34 @@ void LLChatEntry::updateHistory() } } +void LLChatEntry::beforeValueChange() +{ + if(this->getLength() == 0 && !mLabel.empty()) + { + this->clearSegments(); + } +} + +void LLChatEntry::onValueChange(S32 start, S32 end) +{ + resetLabel(); +} + +BOOL LLChatEntry::useLabel() +{ + return !getLength() && !mLabel.empty(); +} + +void LLChatEntry::onFocusReceived() +{ + +} + +void LLChatEntry::onFocusLost() +{ + +} + BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask) { BOOL handled = FALSE; diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h index 10a4594e83..1f3fcf8945 100644 --- a/indra/llui/llchatentry.h +++ b/indra/llui/llchatentry.h @@ -54,11 +54,16 @@ protected: friend class LLUICtrlFactory; LLChatEntry(const Params& p); + /*virtual*/ void beforeValueChange(); + /*virtual*/ void onValueChange(S32 start, S32 end); + /*virtual*/ BOOL useLabel(); public: virtual void draw(); virtual void onCommit(); + /*virtual*/ void onFocusReceived(); + /*virtual*/ void onFocusLost(); boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 98624f42b9..15856ae4ef 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -338,6 +338,11 @@ const LLStyle::Params& LLTextBase::getStyleParams() return mStyle; } +void LLTextBase::beforeValueChange() +{ + +} + void LLTextBase::onValueChange(S32 start, S32 end) { } @@ -530,7 +535,7 @@ void LLTextBase::drawText() { return; } - else if (text_len <= 0 && !mLabel.empty() && !hasFocus()) + else if (useLabel() == TRUE) { text_len = mLabel.getWString().length(); } @@ -747,6 +752,8 @@ void LLTextBase::drawText() S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::segment_vec_t* segments ) { + beforeValueChange(); + S32 old_len = getLength(); // length() returns character length S32 insert_len = wstr.length(); @@ -822,6 +829,8 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length) { + + beforeValueChange(); segment_set_t::iterator seg_iter = getSegIterContaining(pos); while(seg_iter != mSegments.end()) { @@ -880,6 +889,8 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length) S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc) { + beforeValueChange(); + if (pos > (S32)getLength()) { return 0; @@ -2048,7 +2059,7 @@ BOOL LLTextBase::setLabelArg(const std::string& key, const LLStringExplicit& tex void LLTextBase::resetLabel() { - if (!getLength() && !mLabel.empty() && !hasFocus()) + if (useLabel() == TRUE) { clearSegments(); @@ -2061,6 +2072,11 @@ void LLTextBase::resetLabel() } } +BOOL LLTextBase::useLabel() +{ + return !getLength() && !mLabel.empty() && !hasFocus(); +} + void LLTextBase::setFont(const LLFontGL* font) { mFont = font; diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 79662ebd33..44b149d264 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -382,7 +382,7 @@ public: /** * If label is set, draws text label (which is LLLabelTextSegment) - * that is visible when no user text provided and has no focus + * that is visible when no user text provided */ void resetLabel(); @@ -501,7 +501,9 @@ protected: LLTextBase(const Params &p); virtual ~LLTextBase(); void initFromParams(const Params& p); + virtual void beforeValueChange(); virtual void onValueChange(S32 start, S32 end); + virtual BOOL useLabel(); // draw methods void drawSelectionBackground(); // draws the black box behind the selected text diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 8cd0463de8..2b542595c5 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -255,11 +255,12 @@ bottom="0" expand_lines_count="5" follows="left|right|bottom" - font="SansSerifSmall" + font="SansSerifSmall" visible="true" height="20" is_expandable="true" label="To" + text_tentative_color="TextFgTentativeColor" layout="bottomleft" name="chat_editor" max_length="1023" -- cgit v1.2.3 From 3ee73ee98d31e572e284371074b7cd4744005a29 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 17 Oct 2012 15:26:51 -0700 Subject: warn-on-failure:unix-eol --- indra/newview/llviewerwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 403288b2fd..11fe8fda26 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -283,7 +283,7 @@ private: struct Line { Line(const std::string& in_text, S32 in_x, S32 in_y) : text(in_text), x(in_x), y(in_y) {} - std::string text; + std::string text; S32 x,y; }; -- cgit v1.2.3 From 1006e2fd259d5f8136ca933eba8d57c8a980bf31 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 17 Oct 2012 17:14:44 -0700 Subject: CHUI-422 : Update the ad-hoc conversation with the known list of on line agents without waiting for server message (which often doesn't come...). --- indra/newview/llavataractions.cpp | 3 -- indra/newview/lleventpoll.cpp | 42 +++++++----------- indra/newview/llimview.cpp | 3 +- indra/newview/llspeakers.cpp | 92 ++++++--------------------------------- indra/newview/llspeakers.h | 4 -- 5 files changed, 32 insertions(+), 112 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 600df31c8b..7322b3bb0b 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -303,9 +303,6 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids, const LLUUID& float } LLIMFloater::show(session_id); -// gIMMgr->processAgentListUpdates(session_id, LLSD()); -// gIMMgr->startCall(session_id,LLVoiceChannel::OUTGOING_CALL); -// gIMMgr->endCall(session_id); make_ui_sound("UISndStartIM"); } diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 27f79dda2c..4f4d9a40b4 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -37,7 +37,6 @@ #include "llviewerregion.h" #include "message.h" #include "lltrans.h" -#include "llsdserialize.h" namespace { @@ -110,14 +109,14 @@ namespace const std::string& pollURL, const LLHost& sender) { LLHTTPClient::ResponderPtr result = new LLEventPollResponder(pollURL, sender); - llinfos << "Merov debug : LLEventPollResponder::start <" << sCount << "> " + llinfos << "LLEventPollResponder::start <" << sCount << "> " << pollURL << llendl; return result; } void LLEventPollResponder::stop() { - llinfos << "Merov debug : LLEventPollResponder::stop <" << mCount << "> " + llinfos << "LLEventPollResponder::stop <" << mCount << "> " << mPollURL << llendl; // there should be a way to stop a LLHTTPClient request in progress mDone = true; @@ -135,17 +134,17 @@ namespace LLViewerRegion *regionp = gAgent.getRegion(); if (!regionp) { - llinfos << "Merov debug : LLEventPoll initialized before region is added." << llendl; + llerrs << "LLEventPoll initialized before region is added." << llendl; } mSender = sender.getIPandPort(); - llinfos << "Merov debug : LLEventPoll initialized with sender " << mSender << llendl; + llinfos << "LLEventPoll initialized with sender " << mSender << llendl; makeRequest(); } LLEventPollResponder::~LLEventPollResponder() { stop(); - llinfos << "Merov debug : LLEventPollResponder::~Impl <" << mCount << "> " + lldebugs << "LLEventPollResponder::~Impl <" << mCount << "> " << mPollURL << llendl; } @@ -155,13 +154,11 @@ namespace const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - llinfos << "Merov debug : LLEventPollResponder::completedRaw url <" << mPollURL << ">, status = " << status << ", reason = " << reason << llendl; if (status == HTTP_BAD_GATEWAY) { // These errors are not parsable as LLSD, // which LLHTTPClient::Responder::completedRaw will try to do. - //completed(status, reason, LLSD()); - error(status, reason); + completed(status, reason, LLSD()); } else { @@ -175,12 +172,8 @@ namespace request["ack"] = mAcknowledge; request["done"] = mDone; - llinfos << "Merov debug : viewer->sim : LLEventPollResponder::makeRequest <" << mCount - << "> ack = " << LLSDXMLStreamer(mAcknowledge) - << ", error = " << mErrorCount - << ", sender = " << mSender - << ", url = " << mPollURL - << ", done = " << mDone << llendl; + lldebugs << "LLEventPollResponder::makeRequest <" << mCount << "> ack = " + << LLSDXMLStreamer(mAcknowledge) << llendl; LLHTTPClient::post(mPollURL, request, this); } @@ -190,16 +183,13 @@ namespace LLSD message; message["sender"] = mSender; message["body"] = content["body"]; - llinfos << "Merov debug : sim->viewer : LLEventPollResponder::handleMessage, msg_name = " << msg_name << ", message = " << LLSDOStreamer<LLSDNotationFormatter>(message) << llendl; LLMessageSystem::dispatch(msg_name, message); } //virtual void LLEventPollResponder::error(U32 status, const std::string& reason) { - llinfos << "Merov debug : LLEventPollResponder::error, status = " << status << ", reason = " << reason << llendl; if (mDone) return; - llinfos << "Merov debug : LLEventPollResponder::error, status = " << status << ", reason = " << reason << llendl; // A HTTP_BAD_GATEWAY (502) error is our standard timeout response // we get this when there are no events. @@ -217,11 +207,11 @@ namespace + mErrorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC , this); - llinfos << "Merov debug : Unexpected HTTP error. status: " << status << ", reason: " << reason << llendl; + llwarns << "Unexpected HTTP error. status: " << status << ", reason: " << reason << llendl; } else { - llinfos << "Merov debug : LLEventPollResponder::error: <" << mCount << "> got " + llwarns << "LLEventPollResponder::error: <" << mCount << "> got " << status << ": " << reason << (mDone ? " -- done" : "") << llendl; stop(); @@ -237,7 +227,7 @@ namespace // continue running. if(gAgent.getRegion() && gAgent.getRegion()->getHost().getIPandPort() == mSender) { - llinfos << "Merov debug : Forcing disconnect due to stalled main region event poll." << llendl; + llwarns << "Forcing disconnect due to stalled main region event poll." << llendl; LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection")); } } @@ -246,8 +236,8 @@ namespace //virtual void LLEventPollResponder::result(const LLSD& content) { - llinfos << "Merov debug : LLEventPollResponder::result <" << mCount << "> " - << (mDone ? " -- done" : "") << ", content = " << LLSDOStreamer<LLSDNotationFormatter>(content) << llendl; + lldebugs << "LLEventPollResponder::result <" << mCount << ">" + << (mDone ? " -- done" : "") << llendl; if (mDone) return; @@ -256,7 +246,7 @@ namespace if (!content.get("events") || !content.get("id")) { - llinfos << "Merov debug : received event poll with no events or id key" << llendl; + llwarns << "received event poll with no events or id key" << llendl; makeRequest(); return; } @@ -266,11 +256,11 @@ namespace if(mAcknowledge.isUndefined()) { - llinfos << "Merov debug : LLEventPollResponder: id undefined" << llendl; + llwarns << "LLEventPollResponder: id undefined" << llendl; } // was llinfos but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG - llinfos << "Merov debug : LLEventPollResponder::completed <" << mCount << "> " << events.size() << "events (id " + lldebugs << "LLEventPollResponder::completed <" << mCount << "> " << events.size() << "events (id " << LLSDXMLStreamer(mAcknowledge) << ")" << llendl; LLSD::array_const_iterator i = events.beginArray(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index e6f93aa9be..b5f22731f1 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -238,7 +238,6 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& //we need to wait for session initialization for outgoing ad-hoc and group chat session //correct session id for initiated ad-hoc chat will be received from the server - // Merov : MAINT-1551 : We need to read that mInitialTargetIDs when initializing the conversation if (!LLIMModel::getInstance()->sendStartSession(mSessionID, mOtherParticipantID, mInitialTargetIDs, mType)) { @@ -1301,6 +1300,7 @@ bool LLIMModel::sendStartSession( else if ( dialog == IM_SESSION_CONFERENCE_START ) { LLSD agents; + agents.append(gAgent.getID()); for (int i = 0; i < (S32) ids.size(); i++) { agents.append(ids[i]); @@ -1319,6 +1319,7 @@ bool LLIMModel::sendStartSession( data["params"] = agents; llinfos << "Merov debug : viewer-> sim : LLIMModel::sendStartSession, session id = " << temp_session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; + llinfos << "Merov debug : Extra info for LLIMModel::sendStartSession, other_participant_id = " << other_participant_id << ", agent id = " << gAgent.getID() << llendl; LLHTTPClient::post( url, data, diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 217efdf4af..64477765e1 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -36,7 +36,6 @@ #include "llviewerobjectlist.h" #include "llvoavatar.h" #include "llworld.h" -#include "llsdserialize.h" const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f); const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f); @@ -297,23 +296,6 @@ private: LLUUID mSessionID; }; -class UpdateResponder : public LLHTTPClient::Responder -{ -public: - UpdateResponder(const LLUUID& session_id) - { - mSessionID = session_id; - } - - virtual void error(U32 status, const std::string& reason) - { - llinfos << "Merov debug : UpdateResponder error, on " << mSessionID << ", status = " << status << ": " << reason << llendl; - } - -private: - LLUUID mSessionID; -}; - // // LLSpeakerMgr // @@ -322,11 +304,8 @@ LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) : mVoiceChannel(channelp) , mVoiceModerated(false) , mModerateModeHandledFirstTime(false) -, mSessionUpdated(false) -, mSessionID() { static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0); -// mSessionID = getSessionID(); mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay); } @@ -348,7 +327,6 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin mSpeakers.insert(std::make_pair(speakerp->mID, speakerp)); mSpeakersSorted.push_back(speakerp); LL_DEBUGS("Speakers") << "Added speaker " << id << llendl; - //llinfos << "Merov debug : setSpeaker, add, id = " << id << ", name = " << name << llendl; fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add"); } else @@ -369,7 +347,6 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin } else { - llinfos << "Merov debug : setSpeaker, speaker not found? id = " << id << ", name = " << name << llendl; LL_WARNS("Speakers") << "Speaker " << id << " not found" << llendl; } } @@ -550,62 +527,24 @@ void LLSpeakerMgr::updateSpeakerList() LLUUID session_id = getSessionID(); if ((mSpeakers.size() == 0) && (!session_id.isNull())) { - //llinfos << "Merov debug : LLSpeakerMgr::updateSpeakerList: No speakers in " << session_id << llendl; - // MAINT-1551 : If the list is empty for too long, we should send a message to the sim so that - // it sends the participant list again. - updateSession(); + // If the list is empty, we update it with whatever was used to initiate the call so that it doesn't stay empty too long. + // *TODO: Fix the server side code that sometimes forgets to send back the list of agents after a chat started + // (IOW, fix why we get no ChatterBoxSessionAgentListUpdates message after the initial ChatterBoxSessionStartReply) + LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); + for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it) + { + // We only add avatars that are on line + if (LLAvatarTracker::instance().isBuddyOnline(*it)) + { + setSpeaker(*it, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + } + } + // Also add the current agent + setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } } } -void LLSpeakerMgr::updateSession() -{ - // We perform this update if is has never been done or if the session id changed (which happens in ad-hoc sessions) - if (mSessionUpdated && (mSessionID == getSessionID())) - return; - - std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); - LLSD data; - -// That doesn't work apparently because we are not in the invite list so we get error 500 -// data["method"] = "accept invitation"; -// data["session-id"] = getSessionID(); - -// That doesn't work because we're not a moderator on an IM session so our request is rejected as such (error 403) - data["method"] = "session update"; - data["session-id"] = getSessionID(); - data["params"] = LLSD::emptyMap(); - data["params"]["update_info"] = LLSD::emptyMap(); - data["params"]["update_info"]["moderated_mode"] = LLSD::emptyMap(); - data["params"]["update_info"]["moderated_mode"]["voice"] = false; - -// That doesn't work, we eventually time out (error 502)... -// data["method"] = "call"; -// data["session-id"] = getSessionID(); - - data["params"] = LLSD::emptyArray(); -// for (int i = 0; i < count; i++) -// { -// data["params"].append(ids[i]); -// } - data["params"].append(gAgentID); - data["method"] = "invite"; - data["session-id"] = getSessionID(); - - llinfos << "Merov debug : viewer->sim : LLSpeakerMgr::updateSession, session id = " << getSessionID() << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; - - LLHTTPClient::post(url, data, new UpdateResponder(getSessionID())); - - // bit of extra in the case of invite being sent - data.clear(); - data["method"] = "accept invitation"; - data["session-id"] = getSessionID(); - LLHTTPClient::post(url, data, new UpdateResponder(getSessionID())); - - mSessionUpdated = true; - mSessionID = getSessionID(); -} - void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp) { speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; @@ -872,7 +811,6 @@ void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) //current value represents ability to type, so invert data["params"]["mute_info"]["text"] = !speakerp->mModeratorMutedText; - llinfos << "Merov debug : viewer->sim : LLIMSpeakerMgr::toggleAllowTextChat, session id = " << getSessionID() << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post(url, data, new ModerationResponder(getSessionID())); } @@ -897,7 +835,6 @@ void LLIMSpeakerMgr::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmu data["params"]["mute_info"] = LLSD::emptyMap(); data["params"]["mute_info"]["voice"] = !unmute; - llinfos << "Merov debug : viewer->sim : LLIMSpeakerMgr::moderateVoiceParticipant, session id = " << getSessionID() << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post( url, data, @@ -940,7 +877,6 @@ void LLIMSpeakerMgr::moderateVoiceSession(const LLUUID& session_id, bool disallo data["params"]["update_info"]["moderated_mode"] = LLSD::emptyMap(); data["params"]["update_info"]["moderated_mode"]["voice"] = disallow_voice; - llinfos << "Merov debug : viewer->sim : LLIMSpeakerMgr::moderateVoiceSession, session id = " << session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post(url, data, new ModerationResponder(session_id)); } diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 8a80c4619e..8ab08661d3 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -258,10 +258,6 @@ protected: void setSpeakerNotInChannel(LLSpeaker* speackerp); bool removeSpeaker(const LLUUID& speaker_id); - void updateSession(); - bool mSessionUpdated; - LLUUID mSessionID; - typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t; speaker_map_t mSpeakers; -- cgit v1.2.3 From 1cd3c8408fb485792cf20a73156b0fd43f0d90cc Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 17 Oct 2012 17:45:29 -0700 Subject: CHUI-422 : Clean up of leftover traces and tests --- indra/newview/llimfloater.cpp | 4 +--- indra/newview/llimview.cpp | 9 --------- indra/newview/llvoicechannel.cpp | 1 - 3 files changed, 1 insertion(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 47e091a57c..467f48600a 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -59,7 +59,6 @@ #include "llviewerchat.h" #include "llnotificationmanager.h" #include "llautoreplace.h" -#include "llsdserialize.h" floater_showed_signal_t LLIMFloater::sIMFloaterShowedSignal; @@ -1209,12 +1208,11 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) } data["method"] = "invite"; data["session-id"] = mSessionID; - llinfos << "Merov debug : viewer->sim : LLIMFloater::inviteToSession, session id = " << mSessionID << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post(url, data,new LLSessionInviteResponder(mSessionID)); } else { - llinfos << "Merov debug : LLIMFloater::inviteToSession -" + llinfos << "LLIMFloater::inviteToSession -" << " no need to invite agents for " << mDialog << llendl; // successful add, because everyone that needed to get added diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index b5f22731f1..b45903835a 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -63,7 +63,6 @@ #include "lltoolbarview.h" #include "llviewercontrol.h" #include "llviewerparcelmgr.h" -#include "llsdserialize.h" const static std::string ADHOC_NAME_SUFFIX(" Conference"); @@ -1300,7 +1299,6 @@ bool LLIMModel::sendStartSession( else if ( dialog == IM_SESSION_CONFERENCE_START ) { LLSD agents; - agents.append(gAgent.getID()); for (int i = 0; i < (S32) ids.size(); i++) { agents.append(ids[i]); @@ -1318,8 +1316,6 @@ bool LLIMModel::sendStartSession( data["params"] = agents; - llinfos << "Merov debug : viewer-> sim : LLIMModel::sendStartSession, session id = " << temp_session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; - llinfos << "Merov debug : Extra info for LLIMModel::sendStartSession, other_participant_id = " << other_participant_id << ", agent id = " << gAgent.getID() << llendl; LLHTTPClient::post( url, data, @@ -2257,7 +2253,6 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload LLSD data; data["method"] = "accept invitation"; data["session-id"] = session_id; - llinfos << "Merov debug : viewer-> sim : LLIncomingCallDialog::processCallResponse, accept, session id = " << session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post( url, data, @@ -2298,7 +2293,6 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload LLSD data; data["method"] = "decline invitation"; data["session-id"] = session_id; - llinfos << "Merov debug : viewer-> sim : LLIncomingCallDialog::processCallResponse, decline, session id = " << session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post( url, data, @@ -2352,7 +2346,6 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response) LLSD data; data["method"] = "accept invitation"; data["session-id"] = session_id; - llinfos << "Merov debug : viewer-> sim : inviteUserResponse, accept, session id = " << session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post( url, data, @@ -2388,7 +2381,6 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response) LLSD data; data["method"] = "decline invitation"; data["session-id"] = session_id; - llinfos << "Merov debug : viewer-> sim : inviteUserResponse, decline, session id = " << session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post( url, data, @@ -3353,7 +3345,6 @@ public: LLSD data; data["method"] = "accept invitation"; data["session-id"] = session_id; - llinfos << "Merov debug : viewer-> sim : LLViewerChatterBoxInvitation, session id = " << session_id << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post( url, data, diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 62a43333dd..38f9bbc67f 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -540,7 +540,6 @@ void LLVoiceChannelGroup::getChannelInfo() LLSD data; data["method"] = "call"; data["session-id"] = mSessionID; - llinfos << "Merov debug : viewer-> sim : LLVoiceChannelGroup::getChannelInfo, session id = " << mSessionID << ", data = " << LLSDOStreamer<LLSDNotationFormatter>(data) << llendl; LLHTTPClient::post(url, data, new LLVoiceCallCapResponder(mSessionID)); -- cgit v1.2.3 From 49ad7fd4b57cec635c557070be02556094e90ff6 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 17 Oct 2012 17:52:10 -0700 Subject: CHUI-410: Post code review submit, changed useLabel() to return bool instead of BOOL. Adjusted code accordingly. --- indra/llui/llchatentry.cpp | 3 ++- indra/llui/llchatentry.h | 2 +- indra/llui/lltextbase.cpp | 6 +++--- indra/llui/lltextbase.h | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index 38e2a8106a..8e9c6555c3 100644 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -146,10 +146,11 @@ void LLChatEntry::beforeValueChange() void LLChatEntry::onValueChange(S32 start, S32 end) { + //Internally resetLabel() must meet a condition before it can reset the label resetLabel(); } -BOOL LLChatEntry::useLabel() +bool LLChatEntry::useLabel() { return !getLength() && !mLabel.empty(); } diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h index 1f3fcf8945..49181c8d78 100644 --- a/indra/llui/llchatentry.h +++ b/indra/llui/llchatentry.h @@ -56,7 +56,7 @@ protected: LLChatEntry(const Params& p); /*virtual*/ void beforeValueChange(); /*virtual*/ void onValueChange(S32 start, S32 end); - /*virtual*/ BOOL useLabel(); + /*virtual*/ bool useLabel(); public: diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 15856ae4ef..b827acb185 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -535,7 +535,7 @@ void LLTextBase::drawText() { return; } - else if (useLabel() == TRUE) + else if (useLabel()) { text_len = mLabel.getWString().length(); } @@ -2059,7 +2059,7 @@ BOOL LLTextBase::setLabelArg(const std::string& key, const LLStringExplicit& tex void LLTextBase::resetLabel() { - if (useLabel() == TRUE) + if (useLabel()) { clearSegments(); @@ -2072,7 +2072,7 @@ void LLTextBase::resetLabel() } } -BOOL LLTextBase::useLabel() +bool LLTextBase::useLabel() { return !getLength() && !mLabel.empty() && !hasFocus(); } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 44b149d264..629b304b25 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -503,7 +503,7 @@ protected: void initFromParams(const Params& p); virtual void beforeValueChange(); virtual void onValueChange(S32 start, S32 end); - virtual BOOL useLabel(); + virtual bool useLabel(); // draw methods void drawSelectionBackground(); // draws the black box behind the selected text -- cgit v1.2.3 From e56145176875a09dc9e1524a47bcc1259582c896 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 17 Oct 2012 18:14:37 -0700 Subject: CHUI-422 : One last clean up --- indra/newview/llvoicechannel.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 38f9bbc67f..ceff75a0cc 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -35,7 +35,6 @@ #include "llrecentpeople.h" #include "llviewercontrol.h" #include "llvoicechannel.h" -#include "llsdserialize.h" LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap; -- cgit v1.2.3 From c0b60841ce14a1c449ede17284d2aa6939322be3 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Thu, 18 Oct 2012 16:50:40 +0300 Subject: CHUI-412 (User restricted in resizing conversation floater width) fixed --- indra/newview/llimfloatercontainer.cpp | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index c9c7e94af9..8a6659667d 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -286,32 +286,21 @@ void LLIMFloaterContainer::onCloseFloater(LLUUID& id) // virtual void LLIMFloaterContainer::computeResizeLimits(S32& new_min_width, S32& new_min_height) { - bool is_left_pane_expanded = !mConversationsPane->isCollapsed(); - bool is_right_pane_expanded = !mMessagesPane->isCollapsed(); - - S32 conversations_pane_min_dim = mConversationsPane->getMinDim(); - - if (is_right_pane_expanded) + // possibly increase floater's minimum height according to children's minimums + for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) { - S32 conversations_pane_width = - (is_left_pane_expanded ? gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") : conversations_pane_min_dim); - - // possibly increase minimum size constraint due to children's minimums. - for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getPanelByIndex(tab_idx)); + if (floaterp) { - LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getPanelByIndex(tab_idx)); - if (floaterp) - { - new_min_width = llmax(new_min_width, - floaterp->getMinWidth() + conversations_pane_width + LLPANEL_BORDER_WIDTH * 2); - new_min_height = llmax(new_min_height, floaterp->getMinHeight()); - } + new_min_height = llmax(new_min_height, floaterp->getMinHeight()); } } - else - { - new_min_width = conversations_pane_min_dim; - } + + S32 conversations_pane_min_dim = mConversationsPane->getRelevantMinDim(); + S32 messages_pane_min_dim = mMessagesPane->getRelevantMinDim(); + + // set floater's minimum width according to relevant minimal children's dimensionals + new_min_width = conversations_pane_min_dim + messages_pane_min_dim + LLPANEL_BORDER_WIDTH*2; } void LLIMFloaterContainer::onNewMessageReceived(const LLSD& data) -- cgit v1.2.3 From 36ea92678e028abb54e02c603b657dfa10c91da1 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 18 Oct 2012 11:44:52 -0700 Subject: CHUI-329: The text is now gray due to CHUI 410. The only change in this commit is that parenthesis surround the nearby chat text (Nearby chat). --- indra/newview/llimfloatercontainer.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index c9c7e94af9..6edda76ad2 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -1175,8 +1175,18 @@ void LLIMFloaterContainer::setNearbyDistances() void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/) { bool is_nearby_chat = uuid.isNull(); - - std::string display_name = is_nearby_chat ? LLTrans::getString("NearbyChatTitle") : LLIMModel::instance().getName(uuid); + std::string display_name; + + //Stores the display name for the conversation line item + if(is_nearby_chat) + { + //Adds parenthesis in code since these are independent of the translated string + display_name = "(" + LLTrans::getString("NearbyChatTitle") + ")"; + } + else + { + display_name = LLIMModel::instance().getName(uuid); + } // Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do) // Note: this happens often, when reattaching a torn off conversation for instance -- cgit v1.2.3 From 2301c7cff60eca879f605a3ee3f26b960597d8c3 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 18 Oct 2012 13:16:00 -0700 Subject: CHUI-329: Post code review commit, instead of hard coded the parenthesis, created a custom string in string.xml. The reasoning for this is because some languages may not use the parenthesis or perhaps even use brackets if needed...basically allows for flexibility. --- indra/newview/llimfloatercontainer.cpp | 11 +---------- indra/newview/skins/default/xui/en/strings.xml | 1 + 2 files changed, 2 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 6edda76ad2..5d328bb283 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -1175,18 +1175,9 @@ void LLIMFloaterContainer::setNearbyDistances() void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/) { bool is_nearby_chat = uuid.isNull(); - std::string display_name; //Stores the display name for the conversation line item - if(is_nearby_chat) - { - //Adds parenthesis in code since these are independent of the translated string - display_name = "(" + LLTrans::getString("NearbyChatTitle") + ")"; - } - else - { - display_name = LLIMModel::instance().getName(uuid); - } + std::string display_name = is_nearby_chat ? LLTrans::getString("NearbyChatLabel") : LLIMModel::instance().getName(uuid); // Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do) // Note: this happens often, when reattaching a torn off conversation for instance diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 696c282887..01da0a3686 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -385,6 +385,7 @@ Please try logging in again in a minute.</string> <!-- Chat --> <string name="NearbyChatTitle">Nearby chat</string> + <string name="NearbyChatLabel">(Nearby chat)</string> <string name="whisper">whispers:</string> <string name="shout">shouts:</string> <string name="ringing">Connecting to in-world Voice Chat...</string> -- cgit v1.2.3 From d840a60ecc9f7a9e1e9521dc63a79bc73267ed88 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 18 Oct 2012 21:49:02 -0700 Subject: CHUI-373 : Fix : Refresh panel after setting parcel for sale --- indra/newview/llfloaterland.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 4fc6684e8e..a5dd197336 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -1045,6 +1045,8 @@ void LLPanelLandGeneral::onCommitAny(LLUICtrl *ctrl, void *userdata) void LLPanelLandGeneral::onClickSellLand(void* data) { LLViewerParcelMgr::getInstance()->startSellLand(); + LLPanelLandGeneral *panelp = (LLPanelLandGeneral *)data; + panelp->refresh(); } // static -- cgit v1.2.3 From 89ba6b793a5a8b3e0599cd2c8db2f1b479ec0fb4 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Fri, 19 Oct 2012 13:50:55 +0300 Subject: CHUI-418 FIXED Check the existence of mViewModelItem before calling potentiallyVisible(). --- indra/llui/llfolderview.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index c1a11851e2..c8b8bcae48 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -504,7 +504,11 @@ void LLFolderView::sanitizeSelection() LLFolderViewItem* item = *item_iter; // ensure that each ancestor is open and potentially passes filtering - BOOL visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item + BOOL visible = false; + if(item->getViewModelItem()) + { + visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item + } // modify with parent open and filters states LLFolderViewFolder* parent_folder = item->getParentFolder(); // Move up through parent folders and see what's visible -- cgit v1.2.3 From 155cb976cb807771772b6bab62709709348c918b Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Fri, 19 Oct 2012 19:10:35 +0300 Subject: CHUI-416 FIXED Check if conversationItem is not NULL before calling getType(). --- indra/newview/llimfloatercontainer.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index c4eeccecbe..14ed0b3c3e 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -927,15 +927,18 @@ void LLIMFloaterContainer::doToSelected(const LLSD& userdata) const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); uuid_vec_t selected_uuids; - getParticipantUUIDs(selected_uuids); - - if(conversationItem->getType() == LLConversationItem::CONV_PARTICIPANT) - { - doToParticipants(command, selected_uuids); - } - else + if(conversationItem != NULL) { - doToSelectedConversation(command, selected_uuids); + getParticipantUUIDs(selected_uuids); + + if(conversationItem->getType() == LLConversationItem::CONV_PARTICIPANT) + { + doToParticipants(command, selected_uuids); + } + else + { + doToSelectedConversation(command, selected_uuids); + } } } -- cgit v1.2.3 From 2d0b6f033eadb4382da60ba7af913f743c7b0380 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Fri, 19 Oct 2012 13:32:23 -0700 Subject: CHUI-391: Replacing nearby chat icon. --- .../skins/default/textures/icons/nearby_chat_icon.png | Bin 793 -> 553 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/textures/icons/nearby_chat_icon.png b/indra/newview/skins/default/textures/icons/nearby_chat_icon.png index 7c3ad40381..48c2379133 100644 Binary files a/indra/newview/skins/default/textures/icons/nearby_chat_icon.png and b/indra/newview/skins/default/textures/icons/nearby_chat_icon.png differ -- cgit v1.2.3 From e6a7133ef1fa1760e0bfb53f5b14e7b6e76da0f5 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 19 Oct 2012 13:57:40 -0700 Subject: CHUI-422 : Add invited non buddies to the initial set of speakers --- indra/newview/llspeakers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 64477765e1..46fd8c1290 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -533,8 +533,8 @@ void LLSpeakerMgr::updateSpeakerList() LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it) { - // We only add avatars that are on line - if (LLAvatarTracker::instance().isBuddyOnline(*it)) + // Allow to set buddies if they are on line. Allow any other avatar. + if (!LLAvatarTracker::instance().isBuddy(*it) || LLAvatarTracker::instance().isBuddyOnline(*it)) { setSpeaker(*it, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } -- cgit v1.2.3 From 0356ef61cf9f70b97dc78a59fba58465d99f5fc0 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Fri, 19 Oct 2012 16:21:35 -0700 Subject: CHUI-243: Add calls the parent class's implementation for onFocusReceived() and onFocusLost() to ensure that the focus change messages are properly propagated. --- indra/llui/lltextbase.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index b827acb185..8839afb60d 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1359,6 +1359,7 @@ void LLTextBase::onSpellCheckSettingsChange() void LLTextBase::onFocusReceived() { + LLUICtrl::onFocusReceived(); if (!getLength() && !mLabel.empty()) { // delete label which is LLLabelTextSegment @@ -1368,6 +1369,7 @@ void LLTextBase::onFocusReceived() void LLTextBase::onFocusLost() { + LLUICtrl::onFocusLost(); if (!getLength() && !mLabel.empty()) { resetLabel(); -- cgit v1.2.3 From b0c54dfd3e2ecc8d4f875276397a55cef40a3d9a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 19 Oct 2012 17:47:28 -0700 Subject: CHUI-433: Problem: Toasts were not being displayed due to incorrect tracking of the current conversation with focus. Resolution: Now when a conversation gains focus it will set a flag to ignore toasts. And when a conversation loses focus it will set a flag to re-enable toasts. --- indra/newview/llimconversation.cpp | 13 ++++--------- indra/newview/llimview.cpp | 5 ++--- 2 files changed, 6 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index bd2a2419a8..f4b8d39cd0 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -202,16 +202,10 @@ void LLIMConversation::onFocusReceived() { setBackgroundOpaque(true); - if (mSessionID.notNull()) + if (mSessionID.notNull() && isInVisibleChain()) { - LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, true); - - if (getVisible()) - { - // suppress corresponding toast only if this floater is visible and have focus - LLIMModel::getInstance()->setActiveSessionID(mSessionID); - LLIMModel::instance().sendNoUnreadMessages(mSessionID); - } + LLIMModel::getInstance()->setActiveSessionID(mSessionID); + LLIMModel::instance().sendNoUnreadMessages(mSessionID); } LLTransientDockableFloater::onFocusReceived(); @@ -219,6 +213,7 @@ void LLIMConversation::onFocusReceived() void LLIMConversation::onFocusLost() { + LLIMModel::getInstance()->resetActiveSessionID(); setBackgroundOpaque(false); LLTransientDockableFloater::onFocusLost(); } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 115da54ec8..572f36ff7d 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -119,8 +119,7 @@ void toast_callback(const LLSD& msg){ } // check whether incoming IM belongs to an active session or not - if (LLIMModel::getInstance()->getActiveSessionID().notNull() - && LLIMModel::getInstance()->getActiveSessionID() == msg["session_id"]) + if (LLIMModel::getInstance()->getActiveSessionID() == msg["session_id"]) { return; } @@ -147,7 +146,7 @@ void toast_callback(const LLSD& msg){ // Skip toasting if we have open window of IM with this session id LLIMFloater* open_im_floater = LLIMFloater::findInstance(msg["session_id"]); - if (open_im_floater && open_im_floater->getVisible()) + if (open_im_floater && open_im_floater->isInVisibleChain() && open_im_floater->hasFocus()) { return; } -- cgit v1.2.3 From 364e8118670f7ea80a1fa7187b23cc46ad2fc2f7 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Mon, 22 Oct 2012 04:35:31 +0300 Subject: CHUI-428 (Scroll conversation list to the newly created conversation) fixed --- indra/newview/llimfloatercontainer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 14ed0b3c3e..cf4d054dd5 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -1113,6 +1113,9 @@ void LLIMFloaterContainer::setItemSelect(const LLUUID& session_id) mSelectedSession = session_id; LLFolderViewItem* widget = mConversationsWidgets[session_id]; (widget->getRoot())->setSelection(widget, FALSE, FALSE); + + // Scroll to selected item + mConversationsRoot->scrollToShowSelection(); } } } @@ -1228,6 +1231,9 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWi // set the widget to minimized mode if conversations pane is collapsed widget->toggleMinimizedMode(mConversationsPane->isCollapsed()); + // scroll to newly added item + mConversationsRoot->scrollToShowSelection(); + return; } -- cgit v1.2.3 From 0d25cca2e1e117962aad57dc951c102bec52cb50 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Mon, 22 Oct 2012 15:01:03 -0700 Subject: Backed out changeset: 4202e227f8e4 --- indra/llui/llfloaterreg.cpp | 2 +- indra/llui/llfloaterreg.h | 24 ++++++++++++------------ indra/newview/llnearbychat.cpp | 12 ++++++------ 3 files changed, 19 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 920525448c..9115eb7174 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -318,7 +318,7 @@ void LLFloaterReg::showInitialVisibleInstances() BOOL isvis = LLFloater::getControlGroup()->getBOOL(controlname); if (isvis) { - showInstance(name, LLSD(LLUUID())); // keyed floaters shouldn't set save_vis to true + showInstance(name, LLSD()); // keyed floaters shouldn't set save_vis to true } } } diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h index 7924b2a7b8..a1e1f8a988 100644 --- a/indra/llui/llfloaterreg.h +++ b/indra/llui/llfloaterreg.h @@ -90,23 +90,23 @@ public: static LLFloater* getLastFloaterCascading(); // Find / get (create) / remove / destroy - static LLFloater* findInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); - static LLFloater* getInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); - static LLFloater* removeInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); - static bool destroyInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); + static LLFloater* findInstance(const std::string& name, const LLSD& key = LLSD()); + static LLFloater* getInstance(const std::string& name, const LLSD& key = LLSD()); + static LLFloater* removeInstance(const std::string& name, const LLSD& key = LLSD()); + static bool destroyInstance(const std::string& name, const LLSD& key = LLSD()); // Iterators static const_instance_list_t& getFloaterList(const std::string& name); // Visibility Management // return NULL if instance not found or can't create instance (no builder) - static LLFloater* showInstance(const std::string& name, const LLSD& key = LLSD(LLUUID()), BOOL focus = FALSE); + static LLFloater* showInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE); // Close a floater (may destroy or set invisible) // return false if can't find instance - static bool hideInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); + static bool hideInstance(const std::string& name, const LLSD& key = LLSD()); // return true if instance is visible: - static bool toggleInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); - static bool instanceVisible(const std::string& name, const LLSD& key = LLSD(LLUUID())); + static bool toggleInstance(const std::string& name, const LLSD& key = LLSD()); + static bool instanceVisible(const std::string& name, const LLSD& key = LLSD()); static void showInitialVisibleInstances(); static void hideVisibleInstances(const std::set<std::string>& exceptions = std::set<std::string>()); @@ -126,23 +126,23 @@ public: static void registerControlVariables(); // Callback wrappers - static void toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD(LLUUID())); + static void toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD()); // Typed find / get / show template <class T> - static T* findTypedInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())) + static T* findTypedInstance(const std::string& name, const LLSD& key = LLSD()) { return dynamic_cast<T*>(findInstance(name, key)); } template <class T> - static T* getTypedInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())) + static T* getTypedInstance(const std::string& name, const LLSD& key = LLSD()) { return dynamic_cast<T*>(getInstance(name, key)); } template <class T> - static T* showTypedInstance(const std::string& name, const LLSD& key = LLSD(LLUUID()), BOOL focus = FALSE) + static T* showTypedInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE) { return dynamic_cast<T*>(showInstance(name, key, focus)); } diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a89ae4a2dc..5b274dd389 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -287,10 +287,10 @@ void LLNearbyChat::setVisible(BOOL visible) { LLIMConversation::setVisible(visible); - if(visible) - { - removeScreenChat(); - } + if(visible) + { + removeScreenChat(); + } setFocus(visible); } @@ -327,7 +327,7 @@ void LLNearbyChat::addToHost() mIsHostSet = true; } -} + } bool LLNearbyChat::isHostSet() { @@ -722,7 +722,7 @@ void LLNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BO send_chat_from_viewer(utf8_out_text, type, channel); } -// static +// static bool LLNearbyChat::isWordsName(const std::string& name) { // checking to see if it's display name plus username in parentheses -- cgit v1.2.3 From 23d58c0c0906bd5434611cc73da9437ec7a5b830 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 22 Oct 2012 17:31:51 -0700 Subject: CHUI-433: Implemented an alternate solution to the problem. The original solution was ambiguous and incomplete and also preserved an existing hack. The new solution removes a hack/deprecated code (setActiveSession/getActiveSession functions). Basically, a toast message is not displayed if the user already has the conversation in focus. When the conversation floater loses focus toasts message will be displayed for that conversation. --- indra/newview/llimconversation.cpp | 2 -- indra/newview/llimview.cpp | 30 ++++++----------------------- indra/newview/llimview.h | 7 ------- indra/newview/llnotificationhandlerutil.cpp | 17 ---------------- 4 files changed, 6 insertions(+), 50 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index f4b8d39cd0..74bf8cb6fe 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -204,7 +204,6 @@ void LLIMConversation::onFocusReceived() if (mSessionID.notNull() && isInVisibleChain()) { - LLIMModel::getInstance()->setActiveSessionID(mSessionID); LLIMModel::instance().sendNoUnreadMessages(mSessionID); } @@ -213,7 +212,6 @@ void LLIMConversation::onFocusReceived() void LLIMConversation::onFocusLost() { - LLIMModel::getInstance()->resetActiveSessionID(); setBackgroundOpaque(false); LLTransientDockableFloater::onFocusLost(); } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 572f36ff7d..4c5631d5e1 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -118,11 +118,12 @@ void toast_callback(const LLSD& msg){ return; } - // check whether incoming IM belongs to an active session or not - if (LLIMModel::getInstance()->getActiveSessionID() == msg["session_id"]) - { - return; - } + // Skip toasting if we have open window of IM with this session id + LLIMFloater* open_im_floater = LLIMFloater::findInstance(msg["session_id"]); + if (open_im_floater && open_im_floater->isInVisibleChain() && open_im_floater->hasFocus()) + { + return; + } // Skip toasting for system messages if (msg["from_id"].asUUID() == LLUUID::null) @@ -144,30 +145,11 @@ void toast_callback(const LLSD& msg){ return; } - // Skip toasting if we have open window of IM with this session id - LLIMFloater* open_im_floater = LLIMFloater::findInstance(msg["session_id"]); - if (open_im_floater && open_im_floater->isInVisibleChain() && open_im_floater->hasFocus()) - { - return; - } - LLAvatarNameCache::get(msg["from_id"].asUUID(), boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); } -void LLIMModel::setActiveSessionID(const LLUUID& session_id) -{ - // check if such an ID really exists - if (!findIMSession(session_id)) - { - llwarns << "Trying to set as active a non-existent session!" << llendl; - return; - } - - mActiveSessionID = session_id; -} - LLIMModel::LLIMModel() { addNewMsgCallback(boost::bind(&LLIMFloater::newIMCallback, _1)); diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 00b67f520c..054388bc6c 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -147,13 +147,6 @@ public: LLIMModel(); - - //we should control the currently active session - LLUUID mActiveSessionID; - void setActiveSessionID(const LLUUID& session_id); - void resetActiveSessionID() { mActiveSessionID.setNull(); } - LLUUID getActiveSessionID() { return mActiveSessionID; } - /** Session id to session object */ std::map<LLUUID, LLIMSession*> mId2SessionMap; diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 9fd73746e8..b4e8927879 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -93,13 +93,6 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type, } else { - // store active session id - const LLUUID & active_session_id = - LLIMModel::instance().getActiveSessionID(); - - // set searched session as active to avoid IM toast popup - LLIMModel::instance().setActiveSessionID(session_id); - S32 unread = session->mNumUnread; S32 participant_unread = session->mParticipantUnreadMessageCount; LLIMModel::instance().addMessageSilently(session_id, from, from_id, @@ -110,16 +103,6 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type, // update IM floater messages updateIMFLoaterMesages(session_id); - - // restore active session id - if (active_session_id.isNull()) - { - LLIMModel::instance().resetActiveSessionID(); - } - else - { - LLIMModel::instance().setActiveSessionID(active_session_id); - } } } -- cgit v1.2.3 From 3f020d0be92859e1d9261261ccc9c377df700118 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 22 Oct 2012 19:26:18 -0700 Subject: CHUI-441 : WIP : Initial changes to LLIMFloater to use the same model as LLIMFloaterContainer --- indra/newview/llimfloater.cpp | 8 +++++--- indra/newview/llimfloater.h | 4 ++-- indra/newview/llimfloatercontainer.cpp | 19 ++++++++++--------- indra/newview/llimfloatercontainer.h | 2 +- 4 files changed, 18 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index e4032738a7..29e84e1332 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -582,7 +582,7 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) } } -void LLIMFloater::addToHost(const LLUUID& session_id, const bool force) +void LLIMFloater::addToHost(const LLUUID& session_id, LLConversationItemSession* session_root_model, const bool force) { if (!LLIMConversation::isChatMultiTab() || !gIMMgr->hasSession(session_id)) { @@ -593,7 +593,7 @@ void LLIMFloater::addToHost(const LLUUID& session_id, const bool force) bool exist = findInstance(session_id); // Get the floater: this will create the instance if it didn't exist - LLIMFloater* floater = getInstance(session_id); + LLIMFloater* floater = getInstance(session_id, session_root_model); if (floater) { @@ -672,11 +672,12 @@ LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id) return conversation; } -LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) +LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id, LLConversationItemSession* session_root_model) { LLIMFloater* conversation = LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id); + conversation->setSessionRoot(session_root_model); return conversation; } @@ -1322,6 +1323,7 @@ void LLIMFloater::sRemoveTypingIndicator(const LLSD& data) floater->removeTypingIndicator(); } +// CHUI-441 : We should not create a floater here but go through LLIMFLoaterContainer void LLIMFloater::onIMChicletCreated( const LLUUID& session_id ) { LLIMFloater::addToHost(session_id); diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 26daf00afd..fd08612c32 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -71,8 +71,8 @@ public: // Check typing timeout timer. static LLIMFloater* findInstance(const LLUUID& session_id); - static LLIMFloater* getInstance(const LLUUID& session_id); - static void addToHost(const LLUUID& session_id, const bool force = false); + static LLIMFloater* getInstance(const LLUUID& session_id, LLConversationItemSession* session_root_model); + static void addToHost(const LLUUID& session_id, LLConversationItemSession* session_root_model, const bool force = false); // LLFloater overrides /*virtual*/ void onClose(bool app_quitting); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index cf4d054dd5..75ccc56885 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -98,8 +98,8 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - LLIMFloater::addToHost(session_id, true); - addConversationListItem(session_id, true); + LLConversationItemSession* item = addConversationListItem(session_id, true); + LLIMFloater::addToHost(session_id, item, true); } void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) @@ -109,12 +109,13 @@ void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std: void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { - LLIMFloater::addToHost(session_id, true); - addConversationListItem(session_id, true); + LLConversationItemSession* item = addConversationListItem(session_id, true); + LLIMFloater::addToHost(session_id, item, true); } void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) { + // CHUI-441 : We should do this *without* delete and recreate addConversationListItem(new_session_id, removeConversationListItem(old_session_id)); } @@ -1167,11 +1168,11 @@ void LLIMFloaterContainer::setNearbyDistances() } } -void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/) +LLConversationItemSession* LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/) { bool is_nearby_chat = uuid.isNull(); - //Stores the display name for the conversation line item + // Stores the display name for the conversation line item std::string display_name = is_nearby_chat ? LLTrans::getString("NearbyChatLabel") : LLIMModel::instance().getName(uuid); // Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do) @@ -1179,7 +1180,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWi conversations_items_map::iterator item_it = mConversationsItems.find(uuid); if (item_it != mConversationsItems.end()) { - return; + return item_it->second; } // Remove the conversation item that might exist already: it'll be recreated anew further down anyway @@ -1196,7 +1197,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWi if (!item) { llwarns << "Couldn't create conversation session item : " << display_name << llendl; - return; + return NULL; } item->renameItem(display_name); item->updateParticipantName(NULL); @@ -1234,7 +1235,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWi // scroll to newly added item mConversationsRoot->scrollToShowSelection(); - return; + return item; } bool LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index ba2d085858..5823a47a8d 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -151,7 +151,7 @@ private: // Conversation list implementation public: bool removeConversationListItem(const LLUUID& uuid, bool change_focus = true); - void addConversationListItem(const LLUUID& uuid, bool isWidgetSelected = false); + LLConversationItemSession* addConversationListItem(const LLUUID& uuid, bool isWidgetSelected = false); void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); void setNearbyDistances(); -- cgit v1.2.3 From a780eb1a92811c2531c2fc1d211e8e5dd03da103 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Tue, 23 Oct 2012 13:20:53 +0300 Subject: CHUI-418 FIXED Check that mViewModelItem is not NULL --- indra/llui/llfolderview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index c8b8bcae48..c31a832141 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -505,7 +505,7 @@ void LLFolderView::sanitizeSelection() // ensure that each ancestor is open and potentially passes filtering BOOL visible = false; - if(item->getViewModelItem()) + if(item->getViewModelItem() != NULL) { visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item } -- cgit v1.2.3 From 52a8ea96a1b9ad52a01c4617de63f8cc1bec1e31 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Tue, 23 Oct 2012 10:38:04 -0700 Subject: Backed out changeset: 174fccc7016d --- indra/llui/llui.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index f43409a1ff..41a948e545 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1629,10 +1629,10 @@ void LLUI::initClass(const settings_map_t& settings, LLUICtrl::CommitCallbackRegistry::Registrar& reg = LLUICtrl::CommitCallbackRegistry::defaultRegistrar(); // Callbacks for associating controls with floater visibility: - reg.add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleInstance, _2, LLSD(LLUUID()))); - reg.add("Floater.ToggleOrBringToFront", boost::bind(&LLFloaterReg::toggleInstanceOrBringToFront, _2, LLSD(LLUUID()))); - reg.add("Floater.Show", boost::bind(&LLFloaterReg::showInstance, _2, LLSD(LLUUID()), FALSE)); - reg.add("Floater.Hide", boost::bind(&LLFloaterReg::hideInstance, _2, LLSD(LLUUID()))); + reg.add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleInstance, _2, LLSD())); + reg.add("Floater.ToggleOrBringToFront", boost::bind(&LLFloaterReg::toggleInstanceOrBringToFront, _2, LLSD())); + reg.add("Floater.Show", boost::bind(&LLFloaterReg::showInstance, _2, LLSD(), FALSE)); + reg.add("Floater.Hide", boost::bind(&LLFloaterReg::hideInstance, _2, LLSD())); // Button initialization callback for toggle buttons reg.add("Button.SetFloaterToggle", boost::bind(&LLButton::setFloaterToggle, _1, _2)); @@ -1647,8 +1647,8 @@ void LLUI::initClass(const settings_map_t& settings, reg.add("Button.ToggleFloater", boost::bind(&LLButton::toggleFloaterAndSetToggleState, _1, _2)); // Used by menus along with Floater.Toggle to display visibility as a check-mark - LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.Visible", boost::bind(&LLFloaterReg::instanceVisible, _2, LLSD(LLUUID()))); - LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.IsOpen", boost::bind(&LLFloaterReg::instanceVisible, _2, LLSD(LLUUID()))); + LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.Visible", boost::bind(&LLFloaterReg::instanceVisible, _2, LLSD())); + LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.IsOpen", boost::bind(&LLFloaterReg::instanceVisible, _2, LLSD())); // Parse the master list of commands LLCommandManager::load(); -- cgit v1.2.3 From 06978c99d12a1261f3834fa2ebc19e24c54fd1d4 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Wed, 24 Oct 2012 13:06:30 +0300 Subject: CHUI-430 FIXED Open Nearby chat if is is the only conversation in the list. --- indra/newview/llimfloatercontainer.cpp | 16 ++++++++++++++++ indra/newview/llimfloatercontainer.h | 1 + 2 files changed, 17 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index cf4d054dd5..7821f2ee0d 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -222,6 +222,7 @@ BOOL LLIMFloaterContainer::postBuild() void LLIMFloaterContainer::onOpen(const LLSD& key) { LLMultiFloater::onOpen(key); + openNearbyChat(); } // virtual @@ -508,6 +509,7 @@ void LLIMFloaterContainer::setVisible(BOOL visible) LLSD name("nearby_chat"); LLFloaterReg::toggleInstanceOrBringToFront(name); } + openNearbyChat(); } nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); @@ -1491,4 +1493,18 @@ void LLIMFloaterContainer::toggleAllowTextChat(const LLUUID& participant_uuid) } } +void LLIMFloaterContainer::openNearbyChat() +{ + // If there's only one conversation in the container and that conversation is the nearby chat + //(which it should be...), open it so to make the list of participants visible. This happens to be the most common case when opening the Chat floater. + if(mConversationsItems.size() == 1) + { + LLConversationViewSession* nearby_chat = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[LLUUID()]); + if (nearby_chat) + { + nearby_chat->setOpen(TRUE); + } + } +} + // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index ba2d085858..75fed18502 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -138,6 +138,7 @@ private: void moderateVoiceAllParticipants(bool unmute); void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); void toggleAllowTextChat(const LLUUID& participant_uuid); + void openNearbyChat(); LLButton* mExpandCollapseBtn; LLLayoutPanel* mMessagesPane; -- cgit v1.2.3 From a9f8b945519eece7943694f7ac8c200828e5adfa Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 24 Oct 2012 10:51:29 -0700 Subject: CHUI-363: Problem: Nearby chat is a set to be a null converstation. Because of this, when the voice indicator was set to only show for active conversations...voice indicators inside null conversations were not being turned toggled. Resolution: Now will adjust the speaker indicator even if it exists in a null (nearby chat) conversation. --- indra/newview/llspeakingindicatormanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 9b38bf22ff..900379ae1e 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -241,7 +241,7 @@ void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& spea BOOL switch_current_on = switch_on; // we should show indicator for specified voice session only if this is current channel. EXT-5562. - if (switch_current_on && indicator->getTargetSessionID().notNull()) + if (switch_current_on) { switch_current_on = indicator->getTargetSessionID() == session_id; LL_DEBUGS("SpeakingIndicator") << "Session: " << session_id << ", target: " << indicator->getTargetSessionID() << ", the same? = " << switch_current_on << LL_ENDL; -- cgit v1.2.3 From 68815045a629eeb0e4ab33c05d3773d272eafb50 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 24 Oct 2012 13:18:41 -0700 Subject: CHUI-441 : WIP : Initial refactor part 2. Works but the list doesn't update in the torn off dialog. --- indra/newview/llimconversation.cpp | 98 ++++++++++++++++++++-- indra/newview/llimconversation.h | 13 ++- indra/newview/llimfloater.cpp | 10 ++- indra/newview/llimfloater.h | 4 +- indra/newview/llimfloatercontainer.cpp | 28 +++++-- indra/newview/llimfloatercontainer.h | 3 +- .../skins/default/xui/en/floater_im_session.xml | 12 --- 7 files changed, 132 insertions(+), 36 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index bd2a2419a8..1e268bcaf9 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -49,7 +49,7 @@ LLIMConversation::LLIMConversation(const LLSD& session_id) , mTearOffBtn(NULL) , mCloseBtn(NULL) , mSessionID(session_id.asUUID()) - , mParticipantList(NULL) +// , mParticipantList(NULL) , mChatHistory(NULL) , mInputEditor(NULL) , mInputEditorTopPad(0) @@ -73,11 +73,13 @@ LLIMConversation::LLIMConversation(const LLSD& session_id) LLIMConversation::~LLIMConversation() { + /* if (mParticipantList) { delete mParticipantList; mParticipantList = NULL; } + */ delete mRefreshTimer; } @@ -127,11 +129,41 @@ BOOL LLIMConversation::postBuild() mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this)); - mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); - mTearOffBtn = getChild<LLButton>("tear_off_btn"); mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); + mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); + + // Create a root view folder for all participants + LLConversationItem* base_item = new LLConversationItem(mConversationViewModel); + LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); + //p.name = getName(); + //p.title = getLabel(); + p.rect = LLRect(0, 0, getRect().getWidth(), 0); + p.parent_panel = mParticipantListPanel; + //p.tool_tip = p.name; + p.listener = base_item; + p.view_model = &mConversationViewModel; + p.root = NULL; + p.use_ellipses = true; + //p.options_menu = "menu_conversation.xml"; + mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); + mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + + // Add a scroller for the folder (participant) view + LLRect scroller_view_rect = mParticipantListPanel->getRect(); + scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); + LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>()); + scroller_params.rect(scroller_view_rect); + LLScrollContainer* scroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); + scroller->setFollowsAll(); + mParticipantListPanel->addChild(scroller); + scroller->addChild(mConversationsRoot); + mConversationsRoot->setScrollContainer(scroller); + mConversationsRoot->setFollowsAll(); + mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); + + mChatHistory = getChild<LLChatHistory>("chat_history"); mInputEditor = getChild<LLChatEntry>("chat_editor"); @@ -167,15 +199,20 @@ BOOL LLIMConversation::postBuild() return result; } +LLParticipantList* LLIMConversation::getParticipantList() +{ + return dynamic_cast<LLParticipantList*>(LLIMFloaterContainer::getInstance()->getSessionModel(mSessionID)); +} + void LLIMConversation::draw() { LLTransientDockableFloater::draw(); if (mRefreshTimer->hasExpired()) { - if (mParticipantList) + if (getParticipantList()) { - mParticipantList->update(); + getParticipantList()->update(); } refresh(); @@ -274,6 +311,7 @@ void LLIMConversation::appendMessage(const LLChat& chat, const LLSD &args) void LLIMConversation::buildParticipantList() { + /* if (mIsNearbyChat) { LLLocalSpeakerMgr* speaker_manager = LLLocalSpeakerMgr::getInstance(); @@ -289,13 +327,57 @@ void LLIMConversation::buildParticipantList() mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), mConversationViewModel, true, false); } } - updateHeaderAndToolbar(); + */ + + // Create the participants widgets now + // Note: inspired from LLIMFloaterContainer::addConversationListItem() + LLParticipantList* item = getParticipantList(); + if (!item) + { + llinfos << "Merov debug : buildParticipantList, no list!" << llendl; + return; + } + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); + while (current_participant_model != end_participant_model) + { + LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); + LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(mConversationsRoot); // ! Not sure about that. TBC... + participant_view->setVisible(TRUE); + current_participant_model++; + } + + //updateHeaderAndToolbar(); +} + +// Copied from LLIMFloaterContainer::createConversationViewParticipant(). Refactor opportunity! +LLConversationViewParticipant* LLIMConversation::createConversationViewParticipant(LLConversationItem* item) +{ + LLConversationViewParticipant::Params params; + LLRect panel_rect = mParticipantListPanel->getRect(); + + params.name = item->getDisplayName(); + //params.icon = bridge->getIcon(); + //params.icon_open = bridge->getOpenIcon(); + //params.creation_date = bridge->getCreationDate(); + params.root = mConversationsRoot; + params.listener = item; + + //24 is the the current hight of an item (itemHeight) loaded from conversation_view_participant.xml. + params.rect = LLRect (0, 24, panel_rect.getWidth(), 0); + params.tool_tip = params.name; + params.participant_id = item->getUUID(); + + llinfos << "Merov debug : LLIMConversation, create participant, name = " << item->getDisplayName() << llendl; + + return LLUICtrlFactory::create<LLConversationViewParticipant>(params); } void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata) { // TODO: Check this code when sort order menu will be added. (EM) - if (!mParticipantList) + if (!getParticipantList()) { return; } @@ -304,7 +386,7 @@ void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata) if (chosen_item == "sort_name") { - mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME); + getParticipantList()->setSortOrder(LLParticipantList::E_SORT_BY_NAME); } } diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 603e0d0197..c3f885c8be 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -35,6 +35,7 @@ #include "lleventtimer.h" #include "llimview.h" #include "llconversationmodel.h" +#include "llconversationview.h" class LLPanelChatControlPanel; class LLChatEntry; @@ -114,10 +115,16 @@ protected: LLIMModel::LLIMSession* mSession; - LLLayoutPanel* mParticipantListPanel; - LLParticipantList* mParticipantList; - LLUUID mSessionID; + // Participants list: model and view + LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item); + + LLUUID mSessionID; + LLLayoutPanel* mParticipantListPanel; // add the widgets to that see mConversationsListPanel + //LLParticipantList* mParticipantList; get this from the mConversationsItems for the moment + LLParticipantList* getParticipantList(); + conversations_widgets_map mConversationsWidgets; LLConversationViewModel mConversationViewModel; + LLFolderView* mConversationsRoot; LLChatHistory* mChatHistory; LLChatEntry* mInputEditor; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 29e84e1332..9f7b3cd50b 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -582,10 +582,11 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) } } -void LLIMFloater::addToHost(const LLUUID& session_id, LLConversationItemSession* session_root_model, const bool force) +void LLIMFloater::addToHost(const LLUUID& session_id, const bool force) { if (!LLIMConversation::isChatMultiTab() || !gIMMgr->hasSession(session_id)) { + llinfos << "Merov debug : addToHost, not added! multitab = " << LLIMConversation::isChatMultiTab() << ", has session = " << gIMMgr->hasSession(session_id) << llendl; return; } @@ -593,12 +594,14 @@ void LLIMFloater::addToHost(const LLUUID& session_id, LLConversationItemSession* bool exist = findInstance(session_id); // Get the floater: this will create the instance if it didn't exist - LLIMFloater* floater = getInstance(session_id, session_root_model); + LLIMFloater* floater = getInstance(session_id); if (floater) { LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); + llinfos << "Merov debug : addToHost, done! exist = " << exist << llendl; + // Do not add again existing floaters if (!exist) { @@ -672,12 +675,11 @@ LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id) return conversation; } -LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id, LLConversationItemSession* session_root_model) +LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) { LLIMFloater* conversation = LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id); - conversation->setSessionRoot(session_root_model); return conversation; } diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index fd08612c32..26daf00afd 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -71,8 +71,8 @@ public: // Check typing timeout timer. static LLIMFloater* findInstance(const LLUUID& session_id); - static LLIMFloater* getInstance(const LLUUID& session_id, LLConversationItemSession* session_root_model); - static void addToHost(const LLUUID& session_id, LLConversationItemSession* session_root_model, const bool force = false); + static LLIMFloater* getInstance(const LLUUID& session_id); + static void addToHost(const LLUUID& session_id, const bool force = false); // LLFloater overrides /*virtual*/ void onClose(bool app_quitting); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 75ccc56885..6f2b8bcf32 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -98,8 +98,10 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - LLConversationItemSession* item = addConversationListItem(session_id, true); - LLIMFloater::addToHost(session_id, item, true); + llinfos << "Merov debug : sessionAdded, adding LLIMFloater, id = " << session_id << llendl; + LLIMFloater::addToHost(session_id, true); + llinfos << "Merov debug : sessionAdded, adding conversation item, id = " << session_id << llendl; + addConversationListItem(session_id, true); } void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) @@ -109,8 +111,10 @@ void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std: void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { - LLConversationItemSession* item = addConversationListItem(session_id, true); - LLIMFloater::addToHost(session_id, item, true); + llinfos << "Merov debug : sessionVoiceOrIMStarted, adding LLIMFloater, id = " << session_id << llendl; + LLIMFloater::addToHost(session_id, true); + llinfos << "Merov debug : sessionVoiceOrIMStarted, adding conversation item, id = " << session_id << llendl; + addConversationListItem(session_id, true); } void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) @@ -129,6 +133,7 @@ void LLIMFloaterContainer::onCurrentChannelChanged(const LLUUID& session_id) { if (session_id != LLUUID::null) { + llinfos << "Merov debug : onCurrentChannelChanged, LLIMFloater::show, id = " << session_id << llendl; LLIMFloater::show(session_id); } } @@ -343,6 +348,12 @@ LLIMFloaterContainer* LLIMFloaterContainer::getInstance() return LLFloaterReg::getTypedInstance<LLIMFloaterContainer>("im_container"); } +LLConversationItemSession* LLIMFloaterContainer::getSessionModel(const LLUUID& session_id) +{ + LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]); + return session_model; +} + void LLIMFloaterContainer::setMinimized(BOOL b) { if (isMinimized() == b) return; @@ -813,6 +824,7 @@ void LLIMFloaterContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) //When a one-on-one conversation exists, retrieve the participant id from the conversation floater else if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) { + llinfos << "Merov debug : getParticipantUUIDs, LLIMFloater::findInstance, id = " << conversationItem->getUUID() << llendl; LLIMFloater *conversationFloater = LLIMFloater::findInstance(conversationItem->getUUID()); LLUUID participantID = conversationFloater->getOtherParticipantUUID(); selected_uuids.push_back(participantID); @@ -888,6 +900,7 @@ void LLIMFloaterContainer::doToSelectedConversation(const std::string& command, { //Find the conversation floater associated with the selected id const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); + llinfos << "Merov debug : doToSelectedConversation, LLIMFloater::findInstance, id = " << conversationItem->getUUID() << llendl; LLIMFloater *conversationFloater = LLIMFloater::findInstance(conversationItem->getUUID()); if(conversationFloater) @@ -1168,7 +1181,7 @@ void LLIMFloaterContainer::setNearbyDistances() } } -LLConversationItemSession* LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/) +LLConversationItem* LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/) { bool is_nearby_chat = uuid.isNull(); @@ -1180,7 +1193,9 @@ LLConversationItemSession* LLIMFloaterContainer::addConversationListItem(const L conversations_items_map::iterator item_it = mConversationsItems.find(uuid); if (item_it != mConversationsItems.end()) { - return item_it->second; + llinfos << "Merov debug : addConversationListItem, item already present -> exit, id = " << uuid << llendl; + // HACK!!! DO NOT COMMIT!! Understand why this thing is already present... + //return item_it->second; } // Remove the conversation item that might exist already: it'll be recreated anew further down anyway @@ -1196,6 +1211,7 @@ LLConversationItemSession* LLIMFloaterContainer::addConversationListItem(const L } if (!item) { + llinfos << "Merov debug : Couldn't create conversation session item : " << display_name << llendl; llwarns << "Couldn't create conversation session item : " << display_name << llendl; return NULL; } diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 5823a47a8d..c5abc96162 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -92,6 +92,7 @@ public: LLConversationViewModel& getRootViewModel() { return mConversationViewModel; } LLUUID getSelectedSession() { return mSelectedSession; } void setSelectedSession(LLUUID sessionID) { mSelectedSession = sessionID; } + LLConversationItemSession* getSessionModel(const LLUUID& session_id); private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; @@ -151,7 +152,7 @@ private: // Conversation list implementation public: bool removeConversationListItem(const LLUUID& uuid, bool change_focus = true); - LLConversationItemSession* addConversationListItem(const LLUUID& uuid, bool isWidgetSelected = false); + LLConversationItem* addConversationListItem(const LLUUID& uuid, bool isWidgetSelected = false); void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); void setNearbyDistances(); diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 2b542595c5..84fba0a3b3 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -158,18 +158,6 @@ width="150" height="310" auto_resize="false"> - <avatar_list - color="DkGray2" - follows="all" - height="310" - ignore_online_status="true" - layout="topleft" - name="speakers_list" - opaque="false" - show_info_btn="true" - show_profile_btn="false" - show_speaking_indicator="false" - width="150" /> </layout_panel> <layout_panel default_tab_group="3" -- cgit v1.2.3 From b77e2f17aa9755120032ee977d34e9e923cba0be Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 24 Oct 2012 16:02:58 -0700 Subject: CHUI-449: Problem: When a toast was clicked, the conversation floater was displayed without selecting the conversation line item. Resolution: Added a function that will show the conversation floater container and then trigger selecting the conversation line item. When the conversation line item is selecting this implicitly will cause the correct conversation floater to be displayed. --- indra/newview/llconversationview.cpp | 27 ++++++++++----------------- indra/newview/llimfloatercontainer.cpp | 6 ++++++ indra/newview/llimfloatercontainer.h | 2 ++ indra/newview/llimview.cpp | 3 ++- 4 files changed, 20 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 9144f402b4..92493194b8 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -437,29 +437,22 @@ void LLConversationViewParticipant::selectItem() LLIMFloaterContainer* container = LLIMFloaterContainer::getInstance(); LLFloater* session_floater; - //Only execute when switching floaters (conversations) - if(vmi && vmi->getUUID() != container->getSelectedSession()) + if(vmi) { - //When null, show the nearby chat conversation floater - if(vmi->getUUID().isNull()) + session_floater = LLIMConversation::getConversation(vmi->getUUID()); + + //Only execute when switching floaters (conversations) + if(vmi->getUUID() != container->getSelectedSession()) { - LLNearbyChat* nearbyChat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); - nearbyChat->show(); + container->selectFloater(session_floater); + // Store the active session + container->setSelectedSession(vmi->getUUID()); } - //Otherwise, show the IM conversation floater + //Focus the current conversation floater (it is already visible so just focus it) else { - LLIMFloater::show(vmi->getUUID()); + session_floater->setFocus(TRUE); } - - // Store the active session - container->setSelectedSession(vmi->getUUID()); - } - //Focus the current conversation floater (it is already visible so just focus it) - else - { - session_floater = LLIMConversation::getConversation(vmi->getUUID()); - session_floater->setFocus(TRUE); } LLFolderViewItem::selectItem(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 7821f2ee0d..0538a286ce 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -1089,6 +1089,12 @@ bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata) return false; } +void LLIMFloaterContainer::showConversation(const LLUUID& session_id) +{ + setVisibleAndFrontmost(false); + setConvItemSelect(session_id); +} + //Will select only the conversation item void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id) { diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 75fed18502..b884ad5d4b 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -65,6 +65,8 @@ public: /*virtual*/ void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); + + void showConversation(const LLUUID& session_id); void setConvItemSelect(const LLUUID& session_id); void setItemSelect(const LLUUID& session_id); /*virtual*/ void tabClose(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 4c5631d5e1..d5f1e81933 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -49,6 +49,7 @@ #include "llcallingcard.h" #include "llchat.h" #include "llimfloater.h" +#include "llimfloatercontainer.h" #include "llgroupiconctrl.h" #include "llmd5.h" #include "llmutelist.h" @@ -108,7 +109,7 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id, args["FROM"] = av_name.getCompleteName(); args["FROM_ID"] = msg["from_id"]; args["SESSION_ID"] = msg["session_id"]; - LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID())); + LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLIMFloaterContainer::showConversation, LLIMFloaterContainer::getInstance(), msg["session_id"].asUUID())); } void toast_callback(const LLSD& msg){ -- cgit v1.2.3 From e6e2b0dda2b1c3cb8d96a885a569a645d97e0756 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 24 Oct 2012 16:37:08 -0700 Subject: CHUI-441 : WIP : Fixed the creation of empty model records in the list model --- indra/newview/llimfloatercontainer.cpp | 70 +++++++++++++++------------------- 1 file changed, 30 insertions(+), 40 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 6f2b8bcf32..60cc5c6d7e 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -348,10 +348,10 @@ LLIMFloaterContainer* LLIMFloaterContainer::getInstance() return LLFloaterReg::getTypedInstance<LLIMFloaterContainer>("im_container"); } +// Returns a pointer to the session model if found, NULL otherwise. LLConversationItemSession* LLIMFloaterContainer::getSessionModel(const LLUUID& session_id) { - LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]); - return session_model; + return (mConversationsItems.find(session_id) != mConversationsItems.end() ? dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]) : NULL); } void LLIMFloaterContainer::setMinimized(BOOL b) @@ -454,7 +454,7 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) { if (!participant_view) { - LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]); + LLConversationItemSession* session_model = getSessionModel(session_id); if (session_model) { LLConversationItemParticipant* participant_model = session_model->findParticipant(participant_id); @@ -1137,47 +1137,39 @@ void LLIMFloaterContainer::setItemSelect(const LLUUID& session_id) void LLIMFloaterContainer::setTimeNow(const LLUUID& session_id, const LLUUID& participant_id) { - conversations_items_map::iterator item_it = mConversationsItems.find(session_id); - if (item_it != mConversationsItems.end()) + LLConversationItemSession* item = getSessionModel(session_id); + if (item) { - LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(item_it->second); - if (item) - { - item->setTimeNow(participant_id); - mConversationViewModel.requestSortAll(); - mConversationsRoot->arrangeAll(); - } + item->setTimeNow(participant_id); + mConversationViewModel.requestSortAll(); + mConversationsRoot->arrangeAll(); } } void LLIMFloaterContainer::setNearbyDistances() { - // Get the nearby chat session: that's the one with uuid nul in mConversationsItems - conversations_items_map::iterator item_it = mConversationsItems.find(LLUUID()); - if (item_it != mConversationsItems.end()) - { - LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(item_it->second); - if (item) + // Get the nearby chat session: that's the one with uuid nul + LLConversationItemSession* item = getSessionModel(LLUUID()); + if (item) + { + // Get the positions of the nearby avatars and their ids + std::vector<LLVector3d> positions; + uuid_vec_t avatar_ids; + LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); + // Get the position of the agent + const LLVector3d& me_pos = gAgent.getPositionGlobal(); + // For each nearby avatar, compute and update the distance + int avatar_count = positions.size(); + for (int i = 0; i < avatar_count; i++) { - // Get the positions of the nearby avatars and their ids - std::vector<LLVector3d> positions; - uuid_vec_t avatar_ids; - LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); - // Get the position of the agent - const LLVector3d& me_pos = gAgent.getPositionGlobal(); - // For each nearby avatar, compute and update the distance - int avatar_count = positions.size(); - for (int i = 0; i < avatar_count; i++) - { - F64 dist = dist_vec_squared(positions[i], me_pos); - item->setDistance(avatar_ids[i],dist); - } - // Also does it for the agent itself - item->setDistance(gAgent.getID(),0.0f); - // Request resort - mConversationViewModel.requestSortAll(); - mConversationsRoot->arrangeAll(); + F64 dist = dist_vec_squared(positions[i], me_pos); + item->setDistance(avatar_ids[i],dist); } + // Also does it for the agent itself + item->setDistance(gAgent.getID(),0.0f); + // Request resort + mConversationViewModel.requestSortAll(); + mConversationsRoot->arrangeAll(); } } @@ -1188,14 +1180,12 @@ LLConversationItem* LLIMFloaterContainer::addConversationListItem(const LLUUID& // Stores the display name for the conversation line item std::string display_name = is_nearby_chat ? LLTrans::getString("NearbyChatLabel") : LLIMModel::instance().getName(uuid); - // Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do) + // Check if the item is not already in the list, exit (nothing to do) // Note: this happens often, when reattaching a torn off conversation for instance conversations_items_map::iterator item_it = mConversationsItems.find(uuid); if (item_it != mConversationsItems.end()) { - llinfos << "Merov debug : addConversationListItem, item already present -> exit, id = " << uuid << llendl; - // HACK!!! DO NOT COMMIT!! Understand why this thing is already present... - //return item_it->second; + return item_it->second; } // Remove the conversation item that might exist already: it'll be recreated anew further down anyway -- cgit v1.2.3 From 853826efccfea704eb22276dd63c9155a3f77ac1 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 24 Oct 2012 18:12:27 -0700 Subject: CHUI-441 : WIP : More map clean up and better use of get_ptr_in_map() --- indra/newview/llimfloatercontainer.cpp | 36 ++++++++++++---------------------- indra/newview/llimfloatercontainer.h | 2 +- 2 files changed, 14 insertions(+), 24 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 60cc5c6d7e..9d9d49f497 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -348,12 +348,6 @@ LLIMFloaterContainer* LLIMFloaterContainer::getInstance() return LLFloaterReg::getTypedInstance<LLIMFloaterContainer>("im_container"); } -// Returns a pointer to the session model if found, NULL otherwise. -LLConversationItemSession* LLIMFloaterContainer::getSessionModel(const LLUUID& session_id) -{ - return (mConversationsItems.find(session_id) != mConversationsItems.end() ? dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]) : NULL); -} - void LLIMFloaterContainer::setMinimized(BOOL b) { if (isMinimized() == b) return; @@ -432,7 +426,7 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) LLUUID session_id = event.get("session_uuid").asUUID(); LLUUID participant_id = event.get("participant_uuid").asUUID(); - LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[session_id]); + LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,session_id)); if (!session_view) { // We skip events that are not associated to a session @@ -454,7 +448,7 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) { if (!participant_view) { - LLConversationItemSession* session_model = getSessionModel(session_id); + LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,session_id)); if (session_model) { LLConversationItemParticipant* participant_model = session_model->findParticipant(participant_id); @@ -1101,18 +1095,18 @@ bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata) return false; } -//Will select only the conversation item +// Will select only the conversation item void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id) { - LLFolderViewItem* widget = mConversationsWidgets[session_id]; - if (widget && mSelectedSession != session_id) + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); + if (widget && (mSelectedSession != session_id)) { mSelectedSession = session_id; (widget->getRoot())->setSelection(widget, FALSE, FALSE); } } -//Will select the conversation/participant item +// Will select the conversation/participant item void LLIMFloaterContainer::setItemSelect(const LLUUID& session_id) { @@ -1125,7 +1119,7 @@ void LLIMFloaterContainer::setItemSelect(const LLUUID& session_id) if(session_id != vmi->getUUID()) { mSelectedSession = session_id; - LLFolderViewItem* widget = mConversationsWidgets[session_id]; + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); (widget->getRoot())->setSelection(widget, FALSE, FALSE); // Scroll to selected item @@ -1137,7 +1131,7 @@ void LLIMFloaterContainer::setItemSelect(const LLUUID& session_id) void LLIMFloaterContainer::setTimeNow(const LLUUID& session_id, const LLUUID& participant_id) { - LLConversationItemSession* item = getSessionModel(session_id); + LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,session_id)); if (item) { item->setTimeNow(participant_id); @@ -1149,7 +1143,7 @@ void LLIMFloaterContainer::setTimeNow(const LLUUID& session_id, const LLUUID& pa void LLIMFloaterContainer::setNearbyDistances() { // Get the nearby chat session: that's the one with uuid nul - LLConversationItemSession* item = getSessionModel(LLUUID()); + LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,LLUUID())); if (item) { // Get the positions of the nearby avatars and their ids @@ -1250,15 +1244,11 @@ bool LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener bool isWidgetSelected = false; - conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(uuid); - if (widget_it != mConversationsWidgets.end()) + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); + if (widget) { - LLFolderViewItem* widget = widget_it->second; - if (widget) - { - isWidgetSelected = widget->isSelected(); - widget->destroyView(); - } + isWidgetSelected = widget->isSelected(); + widget->destroyView(); } // Suppress the conversation items and widgets from their respective maps diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index c5abc96162..45a40b8964 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -92,7 +92,7 @@ public: LLConversationViewModel& getRootViewModel() { return mConversationViewModel; } LLUUID getSelectedSession() { return mSelectedSession; } void setSelectedSession(LLUUID sessionID) { mSelectedSession = sessionID; } - LLConversationItemSession* getSessionModel(const LLUUID& session_id); + LLConversationItem* getSessionModel(const LLUUID& session_id) { return get_ptr_in_map(mConversationsItems,session_id); } private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; -- cgit v1.2.3 From b5d76c2b55666083279580f383e5a7b139517504 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 24 Oct 2012 20:08:36 -0700 Subject: CHUI-441 : WIP : Fix the initial attach code so to allow creation of the conversation item before the dialog --- indra/newview/llimfloater.cpp | 10 ++-------- indra/newview/llimfloatercontainer.cpp | 9 ++++----- 2 files changed, 6 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 9f7b3cd50b..8fbf691897 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -586,13 +586,9 @@ void LLIMFloater::addToHost(const LLUUID& session_id, const bool force) { if (!LLIMConversation::isChatMultiTab() || !gIMMgr->hasSession(session_id)) { - llinfos << "Merov debug : addToHost, not added! multitab = " << LLIMConversation::isChatMultiTab() << ", has session = " << gIMMgr->hasSession(session_id) << llendl; return; } - // Test the existence of the floater before we try to create it - bool exist = findInstance(session_id); - // Get the floater: this will create the instance if it didn't exist LLIMFloater* floater = getInstance(session_id); if (floater) @@ -600,10 +596,8 @@ void LLIMFloater::addToHost(const LLUUID& session_id, const bool force) LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); - llinfos << "Merov debug : addToHost, done! exist = " << exist << llendl; - - // Do not add again existing floaters - if (!exist) + // Do not attach to the IM container if it's already attached + if (!getFloaterHost()) { // LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; // TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 9d9d49f497..11d8b29884 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -98,10 +98,10 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - llinfos << "Merov debug : sessionAdded, adding LLIMFloater, id = " << session_id << llendl; - LLIMFloater::addToHost(session_id, true); llinfos << "Merov debug : sessionAdded, adding conversation item, id = " << session_id << llendl; addConversationListItem(session_id, true); + llinfos << "Merov debug : sessionAdded, adding LLIMFloater, id = " << session_id << llendl; + LLIMFloater::addToHost(session_id, true); } void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) @@ -111,10 +111,10 @@ void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std: void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { - llinfos << "Merov debug : sessionVoiceOrIMStarted, adding LLIMFloater, id = " << session_id << llendl; - LLIMFloater::addToHost(session_id, true); llinfos << "Merov debug : sessionVoiceOrIMStarted, adding conversation item, id = " << session_id << llendl; addConversationListItem(session_id, true); + llinfos << "Merov debug : sessionVoiceOrIMStarted, adding LLIMFloater, id = " << session_id << llendl; + LLIMFloater::addToHost(session_id, true); } void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) @@ -1195,7 +1195,6 @@ LLConversationItem* LLIMFloaterContainer::addConversationListItem(const LLUUID& } if (!item) { - llinfos << "Merov debug : Couldn't create conversation session item : " << display_name << llendl; llwarns << "Couldn't create conversation session item : " << display_name << llendl; return NULL; } -- cgit v1.2.3 From 63548b973e6de392f2bf209b3405b1dde78bda03 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 25 Oct 2012 11:43:18 -0700 Subject: CHUI-449: Got rid of a function called setItemSelect(), I wrote this code and it doesn't have a purpose anymore since I can use setConvItemSelect() instead. Also now torn off, minimized conversations are selected when clicking a toast for that conversation. Resolution: Adjusted setConvItemSelect() to be less strict when trying to select an item, now as long as the function is called it will attempt to select the conversation line item. --- indra/newview/llconversationview.cpp | 8 +++----- indra/newview/llimfloatercontainer.cpp | 27 ++------------------------- indra/newview/llimfloatercontainer.h | 1 - 3 files changed, 5 insertions(+), 31 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 92493194b8..de0c65e24f 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -448,11 +448,9 @@ void LLConversationViewParticipant::selectItem() // Store the active session container->setSelectedSession(vmi->getUUID()); } - //Focus the current conversation floater (it is already visible so just focus it) - else - { - session_floater->setFocus(TRUE); - } + + //Redirect focus to the conversation floater + session_floater->setFocus(TRUE); } LLFolderViewItem::selectItem(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 0538a286ce..ebb732b995 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -104,7 +104,7 @@ void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::str void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - setItemSelect(session_id); + setConvItemSelect(session_id); } void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) @@ -1099,35 +1099,12 @@ void LLIMFloaterContainer::showConversation(const LLUUID& session_id) void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id) { LLFolderViewItem* widget = mConversationsWidgets[session_id]; - if (widget && mSelectedSession != session_id) + if (widget) { - mSelectedSession = session_id; (widget->getRoot())->setSelection(widget, FALSE, FALSE); } } -//Will select the conversation/participant item -void LLIMFloaterContainer::setItemSelect(const LLUUID& session_id) -{ - - if(mConversationsRoot->getCurSelectedItem() && mConversationsRoot->getCurSelectedItem()->getParentFolder()) - { - //Retreive the conversation id. When a participant is selected, then have to to get the converation id from the parent. - LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(mConversationsRoot->getCurSelectedItem()->getParentFolder()->getViewModelItem()); - - //Will allow selection/highlighting of the conversation/participant - if(session_id != vmi->getUUID()) - { - mSelectedSession = session_id; - LLFolderViewItem* widget = mConversationsWidgets[session_id]; - (widget->getRoot())->setSelection(widget, FALSE, FALSE); - - // Scroll to selected item - mConversationsRoot->scrollToShowSelection(); - } - } -} - void LLIMFloaterContainer::setTimeNow(const LLUUID& session_id, const LLUUID& participant_id) { diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index b884ad5d4b..e69359321a 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -68,7 +68,6 @@ public: void showConversation(const LLUUID& session_id); void setConvItemSelect(const LLUUID& session_id); - void setItemSelect(const LLUUID& session_id); /*virtual*/ void tabClose(); static LLFloater* getCurrentVoiceFloater(); -- cgit v1.2.3 From 7127ea071922ee703cab56439a379f475cd5e4e7 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 25 Oct 2012 14:17:10 -0700 Subject: CHUI-449: Post code review with Merov, adjusted setConvItemSelect() fuction to be called selectConversation(). --- indra/newview/llimfloatercontainer.cpp | 8 ++++---- indra/newview/llimfloatercontainer.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index ebb732b995..bd7d570154 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -104,7 +104,7 @@ void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::str void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - setConvItemSelect(session_id); + selectConversation(session_id); } void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) @@ -1092,11 +1092,11 @@ bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata) void LLIMFloaterContainer::showConversation(const LLUUID& session_id) { setVisibleAndFrontmost(false); - setConvItemSelect(session_id); + selectConversation(session_id); } //Will select only the conversation item -void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id) +void LLIMFloaterContainer::selectConversation(const LLUUID& session_id) { LLFolderViewItem* widget = mConversationsWidgets[session_id]; if (widget) @@ -1210,7 +1210,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWi if (isWidgetSelected) { - setConvItemSelect(uuid); + selectConversation(uuid); } // set the widget to minimized mode if conversations pane is collapsed diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index e69359321a..7d13b37b31 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -67,7 +67,7 @@ public: LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); void showConversation(const LLUUID& session_id); - void setConvItemSelect(const LLUUID& session_id); + void selectConversation(const LLUUID& session_id); /*virtual*/ void tabClose(); static LLFloater* getCurrentVoiceFloater(); -- cgit v1.2.3 From d49de3a66a5476f4541f15dc61c68e0e509c4c70 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 25 Oct 2012 18:16:56 -0700 Subject: CHUI-441 : WIP : Fix crashes when spawning torn off floaters, added widgets creation in the torn off floater for participants. --- indra/llui/llfolderviewitem.cpp | 6 +++--- indra/llui/llfolderviewitem.h | 2 +- indra/llui/llfolderviewmodel.h | 5 +++-- indra/newview/llconversationview.cpp | 13 +++++++------ indra/newview/llimconversation.cpp | 11 +++++++++++ indra/newview/llimconversation.h | 2 ++ indra/newview/llimfloatercontainer.cpp | 29 ++++++++++++----------------- 7 files changed, 39 insertions(+), 29 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 0b04288950..099d51ce17 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -169,7 +169,6 @@ BOOL LLFolderViewItem::postBuild() // Destroys the object LLFolderViewItem::~LLFolderViewItem( void ) { - delete mViewModelItem; mViewModelItem = NULL; } @@ -473,8 +472,9 @@ void LLFolderViewItem::rename(const std::string& new_name) const std::string& LLFolderViewItem::getName( void ) const { - return getViewModelItem()->getName(); - } + static const std::string noName(""); + return getViewModelItem() ? getViewModelItem()->getName() : noName; +} // LLView functionality BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index d4002c3184..19a6b0a44a 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -87,7 +87,7 @@ protected: bool mLabelWidthDirty; S32 mLabelPaddingRight; LLFolderViewFolder* mParentFolder; - LLFolderViewModelItem* mViewModelItem; + LLPointer<LLFolderViewModelItem> mViewModelItem; LLFontGL::StyleFlags mLabelStyle; std::string mLabelSuffix; LLUIImagePtr mIcon, diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index c6030c9b71..5ec08ae211 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -129,10 +129,11 @@ public: // This is am abstract base class that users of the folderview classes // would use to bridge the folder view with the underlying data -class LLFolderViewModelItem +class LLFolderViewModelItem : public LLRefCount { public: - virtual ~LLFolderViewModelItem( void ) {}; + LLFolderViewModelItem() { } + virtual ~LLFolderViewModelItem() { } virtual void update() {} //called when drawing virtual const std::string& getName() const = 0; diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 9144f402b4..2d5665190f 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -234,9 +234,9 @@ void LLConversationViewSession::toggleOpen() void LLConversationViewSession::selectItem() { - - LLConversationItem* item = dynamic_cast<LLConversationItem*>(mViewModelItem); - LLFloater* session_floater = LLIMConversation::getConversation(item->getUUID()); + LLFolderViewModelItem* item = mViewModelItem; + LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID(); + LLFloater* session_floater = LLIMConversation::getConversation(session_uuid); LLMultiFloater* host_floater = session_floater->getHost(); if (host_floater == mContainer) @@ -250,7 +250,7 @@ void LLConversationViewSession::selectItem() // Set the focus on the selected floater session_floater->setFocus(TRUE); // Store the active session - LLIMFloaterContainer::getInstance()->setSelectedSession(item->getUUID()); + LLIMFloaterContainer::getInstance()->setSelectedSession(session_uuid); LLFolderViewItem::selectItem(); @@ -272,8 +272,9 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible) { // Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized // Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here - LLConversationItem* item = dynamic_cast<LLConversationItem*>(mViewModelItem); - LLFloater* session_floater = LLIMConversation::getConversation(item->getUUID()); + LLFolderViewModelItem* item = mViewModelItem; + LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID(); + LLFloater* session_floater = LLIMConversation::getConversation(session_uuid); if (session_floater && !session_floater->getHost() && !session_floater->isMinimized()) { diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 1e268bcaf9..532f1be6a8 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -351,6 +351,17 @@ void LLIMConversation::buildParticipantList() //updateHeaderAndToolbar(); } +void LLIMConversation::addConversationViewParticipant(LLConversationItem* participant_model) +{ + // Check if the model already has an associated view + llinfos << "Merov debug : addConversationViewParticipant(). We need to check the existence!!!" << llendl; + + // Create the participant view and attach it to the root + LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(mConversationsRoot); // ! Not sure about that. TBC... + participant_view->setVisible(TRUE); +} + // Copied from LLIMFloaterContainer::createConversationViewParticipant(). Refactor opportunity! LLConversationViewParticipant* LLIMConversation::createConversationViewParticipant(LLConversationItem* item) { diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index c3f885c8be..09d0016946 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -71,6 +71,8 @@ public: /*virtual*/ void onClose(bool app_quitting); /*virtual*/ BOOL postBuild(); /*virtual*/ void draw(); + + void addConversationViewParticipant(LLConversationItem* item); protected: diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 11d8b29884..0d62630b31 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -98,9 +98,7 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - llinfos << "Merov debug : sessionAdded, adding conversation item, id = " << session_id << llendl; addConversationListItem(session_id, true); - llinfos << "Merov debug : sessionAdded, adding LLIMFloater, id = " << session_id << llendl; LLIMFloater::addToHost(session_id, true); } @@ -111,9 +109,7 @@ void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std: void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { - llinfos << "Merov debug : sessionVoiceOrIMStarted, adding conversation item, id = " << session_id << llendl; addConversationListItem(session_id, true); - llinfos << "Merov debug : sessionVoiceOrIMStarted, adding LLIMFloater, id = " << session_id << llendl; LLIMFloater::addToHost(session_id, true); } @@ -433,6 +429,7 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) return false; } LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); + LLIMFloater *conversation_floater = LLIMFloater::findInstance(session_id); if (type == "remove_participant") { @@ -446,20 +443,18 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) } else if (type == "add_participant") { - if (!participant_view) + LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,session_id)); + LLConversationItemParticipant* participant_model = (session_model ? session_model->findParticipant(participant_id) : NULL); + if (!participant_view && session_model && participant_model) { - LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,session_id)); - if (session_model) - { - LLConversationItemParticipant* participant_model = session_model->findParticipant(participant_id); - if (participant_model) - { - participant_view = createConversationViewParticipant(participant_model); - participant_view->addToFolder(session_view); - participant_view->setVisible(TRUE); - } - } - + participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(session_view); + participant_view->setVisible(TRUE); + } + // CHUI-441 : + if (conversation_floater && participant_model) + { + conversation_floater->addConversationViewParticipant(participant_model); } } else if (type == "update_participant") -- cgit v1.2.3 From 8f1049b2f8659b039752ee23017c1f30fa6d2725 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Fri, 26 Oct 2012 15:22:31 +0300 Subject: CHUI-457 FIXED Check that selected participant is not self before performing actions. --- indra/newview/llimfloatercontainer.cpp | 112 +++++++++++++++++---------------- 1 file changed, 57 insertions(+), 55 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index bd7d570154..b98558c47b 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -825,62 +825,64 @@ void LLIMFloaterContainer::doToParticipants(const std::string& command, uuid_vec if(selectedIDS.size() > 0) { const LLUUID& userID = selectedIDS.front(); - - if ("view_profile" == command) - { - LLAvatarActions::showProfile(userID); - } - else if("im" == command) - { - LLAvatarActions::startIM(userID); - } - else if("offer_teleport" == command) - { - LLAvatarActions::offerTeleport(selectedIDS); - } - else if("voice_call" == command) - { - LLAvatarActions::startCall(userID); - } - else if("chat_history" == command) - { - LLAvatarActions::viewChatHistory(userID); - } - else if("add_friend" == command) - { - LLAvatarActions::requestFriendshipDialog(userID); - } - else if("remove_friend" == command) - { - LLAvatarActions::removeFriendDialog(userID); - } - else if("invite_to_group" == command) - { - LLAvatarActions::inviteToGroup(userID); - } - else if("map" == command) - { - LLAvatarActions::showOnMap(userID); - } - else if("share" == command) - { - LLAvatarActions::share(userID); - } - else if("pay" == command) + if(gAgent.getID() != userID) { - LLAvatarActions::pay(userID); - } - else if("block_unblock" == command) - { - LLAvatarActions::toggleBlock(userID); - } - else if("selected" == command || "mute_all" == command || "unmute_all" == command) - { - moderateVoice(command, userID); - } - else if ("toggle_allow_text_chat" == command) - { - toggleAllowTextChat(userID); + if ("view_profile" == command) + { + LLAvatarActions::showProfile(userID); + } + else if("im" == command) + { + LLAvatarActions::startIM(userID); + } + else if("offer_teleport" == command) + { + LLAvatarActions::offerTeleport(selectedIDS); + } + else if("voice_call" == command) + { + LLAvatarActions::startCall(userID); + } + else if("chat_history" == command) + { + LLAvatarActions::viewChatHistory(userID); + } + else if("add_friend" == command) + { + LLAvatarActions::requestFriendshipDialog(userID); + } + else if("remove_friend" == command) + { + LLAvatarActions::removeFriendDialog(userID); + } + else if("invite_to_group" == command) + { + LLAvatarActions::inviteToGroup(userID); + } + else if("map" == command) + { + LLAvatarActions::showOnMap(userID); + } + else if("share" == command) + { + LLAvatarActions::share(userID); + } + else if("pay" == command) + { + LLAvatarActions::pay(userID); + } + else if("block_unblock" == command) + { + LLAvatarActions::toggleBlock(userID); + } + else if("selected" == command || "mute_all" == command || "unmute_all" == command) + { + moderateVoice(command, userID); + } + else if ("toggle_allow_text_chat" == command) + { + toggleAllowTextChat(userID); + } } } } -- cgit v1.2.3 From a815585fd7de0f5aba60739127f473fd9d22ccfc Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Fri, 26 Oct 2012 19:33:31 +0300 Subject: CHUI-439 (Conversation floater is automatically unminimized when a selected user is removed from nearby chat participant list after teleport) CHUI-438 (Conversation remains transparent after teleport with a participant selected in nearby chat) --- indra/llui/llfolderviewitem.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 0b04288950..4825fc613c 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1473,6 +1473,8 @@ void LLFolderViewFolder::destroyView() // doesn't delete it. void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) { + if (item->isSelected()) + getRoot()->clearSelection(); items_t::iterator it = std::find(mItems.begin(), mItems.end(), item); if(it == mItems.end()) { -- cgit v1.2.3 From 83562e059fdcf9f732bc8effba99d1e95d39cd36 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 26 Oct 2012 11:36:14 -0700 Subject: CHUI-383: Now a new conversation will not take focus. Instead a toast will appear. Problem: Each time a conversation was added, code would execute to add the conversation floater AND select the conversation. Resolution: This is no longer the expected behavior so adjusted LLIMFloater::addToHost() to only add a floater and not select/show the floater. If selection and/or showing is needed it seems to make sense that this is done outside LLIMFloater:addToHost(). --- indra/newview/llimfloater.cpp | 17 ++--------------- indra/newview/llimfloater.h | 2 +- indra/newview/llimfloatercontainer.cpp | 21 ++++++++++----------- 3 files changed, 13 insertions(+), 27 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index e4032738a7..1af5def5f0 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -582,7 +582,7 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) } } -void LLIMFloater::addToHost(const LLUUID& session_id, const bool force) +void LLIMFloater::addToHost(const LLUUID& session_id) { if (!LLIMConversation::isChatMultiTab() || !gIMMgr->hasSession(session_id)) { @@ -607,20 +607,7 @@ void LLIMFloater::addToHost(const LLUUID& session_id, const bool force) LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END; if (floater_container) { - floater_container->addFloater(floater, TRUE, i_pt); - } - } - - if (force) - { - if (floater_container && floater_container->getVisible()) - { - floater->openFloater(floater->getKey()); - floater->setVisible(TRUE); - } - else - { - floater->setVisible(FALSE); + floater_container->addFloater(floater, FALSE, i_pt); } } } diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 26daf00afd..8a0d6f10e0 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -72,7 +72,7 @@ public: static LLIMFloater* findInstance(const LLUUID& session_id); static LLIMFloater* getInstance(const LLUUID& session_id); - static void addToHost(const LLUUID& session_id, const bool force = false); + static void addToHost(const LLUUID& session_id); // LLFloater overrides /*virtual*/ void onClose(bool app_quitting); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index bd7d570154..71487eb382 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -98,8 +98,8 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - LLIMFloater::addToHost(session_id, true); - addConversationListItem(session_id, true); + LLIMFloater::addToHost(session_id); + addConversationListItem(session_id); } void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) @@ -109,8 +109,8 @@ void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std: void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { - LLIMFloater::addToHost(session_id, true); - addConversationListItem(session_id, true); + LLIMFloater::addToHost(session_id); + addConversationListItem(session_id); } void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) @@ -1208,16 +1208,15 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWi current_participant_model++; } - if (isWidgetSelected) - { - selectConversation(uuid); - } - // set the widget to minimized mode if conversations pane is collapsed widget->toggleMinimizedMode(mConversationsPane->isCollapsed()); - // scroll to newly added item - mConversationsRoot->scrollToShowSelection(); + if (isWidgetSelected) + { + selectConversation(uuid); + // scroll to newly added item + mConversationsRoot->scrollToShowSelection(); + } return; } -- cgit v1.2.3 From 1a1a0b91c0c4400ec3febac183124314f9226127 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 26 Oct 2012 16:49:22 -0700 Subject: CHUI-383: Realized that prior changes for this bug caused a regress. The regress was using the people panel or a notecard to start a im/call with a user. When doing this the conversation line item would not be focused. Resolution: Changed all calls to LLIMFloater::show() to LLIMFloaterContainer::showConversation(), which will first select the conversation line item and then show the corresponding conversation floater. --- indra/newview/llavataractions.cpp | 6 +++--- indra/newview/llchiclet.cpp | 3 ++- indra/newview/llgroupactions.cpp | 4 ++-- indra/newview/llimfloatercontainer.cpp | 2 +- indra/newview/llinventorybridge.cpp | 4 ++-- indra/newview/llinventorypanel.cpp | 4 ++-- 6 files changed, 12 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 7322b3bb0b..13262efb3b 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -56,6 +56,7 @@ #include "llinventorybridge.h" #include "llinventorymodel.h" // for gInventory.findCategoryUUIDForType #include "llinventorypanel.h" +#include "llimfloatercontainer.h" #include "llimview.h" // for gIMMgr #include "llmutelist.h" #include "llnotificationsutil.h" // for LLNotificationsUtil @@ -67,7 +68,6 @@ #include "llviewerobjectlist.h" #include "llviewermessage.h" // for handle_lure #include "llviewerregion.h" -#include "llimfloater.h" #include "lltrans.h" #include "llcallingcard.h" #include "llslurl.h" // IDEVO @@ -184,7 +184,7 @@ static void on_avatar_name_cache_start_im(const LLUUID& agent_id, LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id); if (session_id != LLUUID::null) { - LLIMFloater::show(session_id); + LLIMFloaterContainer::getInstance()->showConversation(session_id); } make_ui_sound("UISndStartIM"); } @@ -302,7 +302,7 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids, const LLUUID& float return; } - LLIMFloater::show(session_id); + LLIMFloaterContainer::getInstance()->showConversation(session_id); make_ui_sound("UISndStartIM"); } diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 17181edffc..e328186fd6 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -34,6 +34,7 @@ #include "llgroupactions.h" #include "lliconctrl.h" #include "llimfloater.h" +#include "llimfloatercontainer.h" #include "llimview.h" #include "llfloaterreg.h" #include "lllocalcliprect.h" @@ -1196,7 +1197,7 @@ void LLChicletPanel::onCurrentVoiceChannelChanged(const LLUUID& session_id) chiclet->setShowSpeaker(true); if (gSavedSettings.getBOOL("OpenIMOnVoice")) { - LLIMFloater::show(chiclet->getSessionId()); + LLIMFloaterContainer::getInstance()->showConversation(session_id); } } } diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index 623ebb76f2..15eca39bce 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -36,10 +36,10 @@ #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" #include "llgroupmgr.h" +#include "llimfloatercontainer.h" #include "llimview.h" // for gIMMgr #include "llnotificationsutil.h" #include "llstatusbar.h" // can_afford_transaction() -#include "llimfloater.h" #include "groupchatlistener.h" // @@ -335,7 +335,7 @@ LLUUID LLGroupActions::startIM(const LLUUID& group_id) group_id); if (session_id != LLUUID::null) { - LLIMFloater::show(session_id); + LLIMFloaterContainer::getInstance()->showConversation(session_id); } make_ui_sound("UISndStartIM"); return session_id; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 6377ffeecf..4d2201ebb9 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -128,7 +128,7 @@ void LLIMFloaterContainer::onCurrentChannelChanged(const LLUUID& session_id) { if (session_id != LLUUID::null) { - LLIMFloater::show(session_id); + LLIMFloaterContainer::getInstance()->showConversation(session_id); } } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 28c2edbe84..5d8d82b226 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -46,7 +46,7 @@ #include "llfriendcard.h" #include "llgesturemgr.h" #include "llgiveinventory.h" -#include "llimfloater.h" +#include "llimfloatercontainer.h" #include "llimview.h" #include "llclipboard.h" #include "llinventorydefines.h" @@ -4704,7 +4704,7 @@ void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string act LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID()); if (session_id != LLUUID::null) { - LLIMFloater::show(session_id); + LLIMFloaterContainer::getInstance()->showConversation(session_id); } } } diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index a8d99ad7de..dafc71b59c 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -39,7 +39,7 @@ #include "llfloatersidepanelcontainer.h" #include "llfolderview.h" #include "llfolderviewitem.h" -#include "llimfloater.h" +#include "llimfloatercontainer.h" #include "llimview.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" @@ -1087,7 +1087,7 @@ bool LLInventoryPanel::beginIMSession() LLUUID session_id = gIMMgr->addSession(name, type, members[0], members); if (session_id != LLUUID::null) { - LLIMFloater::show(session_id); + LLIMFloaterContainer::getInstance()->showConversation(session_id); } return true; -- cgit v1.2.3 From 36b1b4c4b6bbae641271b6b1668e1fea4629d899 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 26 Oct 2012 17:04:17 -0700 Subject: CHUI-465 : Add event handling for LLIMConversation participant list --- indra/newview/llimconversation.cpp | 96 +++++++++++++++++++--------------- indra/newview/llimconversation.h | 4 ++ indra/newview/llimfloatercontainer.cpp | 23 ++++++-- 3 files changed, 78 insertions(+), 45 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 532f1be6a8..cc5adfc2e8 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -137,16 +137,12 @@ BOOL LLIMConversation::postBuild() // Create a root view folder for all participants LLConversationItem* base_item = new LLConversationItem(mConversationViewModel); LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); - //p.name = getName(); - //p.title = getLabel(); p.rect = LLRect(0, 0, getRect().getWidth(), 0); p.parent_panel = mParticipantListPanel; - //p.tool_tip = p.name; p.listener = base_item; p.view_model = &mConversationViewModel; p.root = NULL; p.use_ellipses = true; - //p.options_menu = "menu_conversation.xml"; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); @@ -157,6 +153,8 @@ BOOL LLIMConversation::postBuild() scroller_params.rect(scroller_view_rect); LLScrollContainer* scroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); scroller->setFollowsAll(); + + // Insert that scroller into the panel widgets hierarchy and folder view mParticipantListPanel->addChild(scroller); scroller->addChild(mConversationsRoot); mConversationsRoot->setScrollContainer(scroller); @@ -311,72 +309,86 @@ void LLIMConversation::appendMessage(const LLChat& chat, const LLSD &args) void LLIMConversation::buildParticipantList() { - /* - if (mIsNearbyChat) - { - LLLocalSpeakerMgr* speaker_manager = LLLocalSpeakerMgr::getInstance(); - mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), mConversationViewModel, true, false); - } - else - { - LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - // for group and ad-hoc chat we need to include agent into list - if(!mIsP2PChat && mSessionID.notNull() && speaker_manager) - { - delete mParticipantList; // remove the old list and create a new one if the session id has changed - mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), mConversationViewModel, true, false); - } - } - */ - - // Create the participants widgets now - // Note: inspired from LLIMFloaterContainer::addConversationListItem() + // Get the model list LLParticipantList* item = getParticipantList(); if (!item) { - llinfos << "Merov debug : buildParticipantList, no list!" << llendl; + // Nothing to do if the model list is empty return; } + + // Create the participants widgets now LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); while (current_participant_model != end_participant_model) { LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); - LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); - participant_view->addToFolder(mConversationsRoot); // ! Not sure about that. TBC... - participant_view->setVisible(TRUE); + addConversationViewParticipant(participant_model); current_participant_model++; } - - //updateHeaderAndToolbar(); } void LLIMConversation::addConversationViewParticipant(LLConversationItem* participant_model) { // Check if the model already has an associated view - llinfos << "Merov debug : addConversationViewParticipant(). We need to check the existence!!!" << llendl; + LLUUID uuid = participant_model->getUUID(); + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); - // Create the participant view and attach it to the root - LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); - participant_view->addToFolder(mConversationsRoot); // ! Not sure about that. TBC... - participant_view->setVisible(TRUE); + // If not already present, create the participant view and attach it to the root, otherwise, just refresh it + if (widget) + { + updateConversationViewParticipant(uuid); // overkill? + } + else + { + LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); + mConversationsWidgets[uuid] = widget; + participant_view->addToFolder(mConversationsRoot); + participant_view->setVisible(TRUE); + refreshConversation(); + } +} + +void LLIMConversation::removeConversationViewParticipant(const LLUUID& participant_id) +{ + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); + if (widget) + { + mConversationsRoot->extractItem(widget); + delete widget; + mConversationsWidgets.erase(participant_id); + refreshConversation(); + } +} + +void LLIMConversation::updateConversationViewParticipant(const LLUUID& participant_id) +{ + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); + if (widget) + { + widget->refresh(); + refreshConversation(); + } +} + +void LLIMConversation::refreshConversation() +{ + // *TODO: update the conversation name + // *TODO: check that all participant models do have a view (this is a consistency check) + mConversationViewModel.requestSortAll(); + mConversationsRoot->arrangeAll(); } // Copied from LLIMFloaterContainer::createConversationViewParticipant(). Refactor opportunity! LLConversationViewParticipant* LLIMConversation::createConversationViewParticipant(LLConversationItem* item) { - LLConversationViewParticipant::Params params; LLRect panel_rect = mParticipantListPanel->getRect(); + LLConversationViewParticipant::Params params; params.name = item->getDisplayName(); - //params.icon = bridge->getIcon(); - //params.icon_open = bridge->getOpenIcon(); - //params.creation_date = bridge->getCreationDate(); params.root = mConversationsRoot; params.listener = item; - - //24 is the the current hight of an item (itemHeight) loaded from conversation_view_participant.xml. - params.rect = LLRect (0, 24, panel_rect.getWidth(), 0); + params.rect = LLRect (0, 24, panel_rect.getWidth(), 0); // *TODO: use conversation_view_participant.xml itemHeight value in lieu of 24 params.tool_tip = params.name; params.participant_id = item->getUUID(); diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 09d0016946..a2e56bb2ef 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -72,7 +72,11 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void draw(); + // Handle the left hand participant list widgets void addConversationViewParticipant(LLConversationItem* item); + void removeConversationViewParticipant(const LLUUID& participant_id); + void updateConversationViewParticipant(const LLUUID& participant_id); + void refreshConversation(); protected: diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 0d62630b31..7159b13c8c 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -408,7 +408,7 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) // For debug only //std::ostringstream llsd_value; //llsd_value << LLSDOStreamer<LLSDNotationFormatter>(event) << std::endl; - //llinfos << "Merov debug : onConversationModelEvent, event = " << llsd_value.str() << llendl; + //llinfos << "LLIMFloaterContainer::onConversationModelEvent, event = " << llsd_value.str() << llendl; // end debug // Note: In conversations, the model is not responsible for creating the view, which is a good thing. This means that @@ -425,7 +425,7 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,session_id)); if (!session_view) { - // We skip events that are not associated to a session + // We skip events that are not associated with a session return false; } LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); @@ -433,6 +433,7 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) if (type == "remove_participant") { + // Remove a participant view from the hierarchical conversation list if (participant_view) { session_view->extractItem(participant_view); @@ -440,18 +441,24 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) session_view->refresh(); mConversationsRoot->arrangeAll(); } + // Remove a participant view from the conversation floater + if (conversation_floater) + { + conversation_floater->removeConversationViewParticipant(participant_id); + } } else if (type == "add_participant") { LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,session_id)); LLConversationItemParticipant* participant_model = (session_model ? session_model->findParticipant(participant_id) : NULL); + // Add a participant view to the hierarchical conversation list if (!participant_view && session_model && participant_model) { participant_view = createConversationViewParticipant(participant_model); participant_view->addToFolder(session_view); participant_view->setVisible(TRUE); } - // CHUI-441 : + // Add a participant view to the conversation floater if (conversation_floater && participant_model) { conversation_floater->addConversationViewParticipant(participant_model); @@ -459,14 +466,24 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) } else if (type == "update_participant") { + // Update the participant view in the hierarchical conversation list if (participant_view) { participant_view->refresh(); } + // Update the participant view in the conversation floater + if (conversation_floater) + { + conversation_floater->updateConversationViewParticipant(participant_id); + } } else if (type == "update_session") { session_view->refresh(); + if (conversation_floater) + { + conversation_floater->refreshConversation(); + } } mConversationViewModel.requestSortAll(); -- cgit v1.2.3 From 09282019ef4d068fe95a94931bf341d8e84f29ea Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 26 Oct 2012 19:12:19 -0700 Subject: CHUI-469 : WIP : Add participants to the nearby chat torn off panel --- indra/newview/llimconversation.cpp | 4 ++-- indra/newview/llimconversation.h | 2 +- indra/newview/llimfloater.cpp | 3 +-- indra/newview/llimfloatercontainer.cpp | 10 +++++++--- 4 files changed, 11 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index cc5adfc2e8..ad34acd941 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -174,7 +174,7 @@ BOOL LLIMConversation::postBuild() setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); - buildParticipantList(); + buildConversationViewParticipant(); updateHeaderAndToolbar(); @@ -307,7 +307,7 @@ void LLIMConversation::appendMessage(const LLChat& chat, const LLSD &args) } -void LLIMConversation::buildParticipantList() +void LLIMConversation::buildConversationViewParticipant() { // Get the model list LLParticipantList* item = getParticipantList(); diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index a2e56bb2ef..4e66d000e6 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -77,6 +77,7 @@ public: void removeConversationViewParticipant(const LLUUID& participant_id); void updateConversationViewParticipant(const LLUUID& participant_id); void refreshConversation(); + void buildConversationViewParticipant(); protected: @@ -95,7 +96,6 @@ protected: // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); - void buildParticipantList(); void onSortMenuItemClicked(const LLSD& userdata); void hideOrShowTitle(); // toggle the floater's drag handle diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 8fbf691897..560b3fa60a 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -825,8 +825,7 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) if (mSessionID != im_session_id) { initIMSession(im_session_id); - - buildParticipantList(); + buildConversationViewParticipant(); } initIMFloater(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 7159b13c8c..89dfd2e149 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -429,7 +429,7 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) return false; } LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); - LLIMFloater *conversation_floater = LLIMFloater::findInstance(session_id); + LLIMConversation *conversation_floater = (session_id.isNull() ? (LLIMConversation*)(LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")) : (LLIMConversation*)(LLIMFloater::findInstance(session_id))); if (type == "remove_participant") { @@ -830,7 +830,6 @@ void LLIMFloaterContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) //When a one-on-one conversation exists, retrieve the participant id from the conversation floater else if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) { - llinfos << "Merov debug : getParticipantUUIDs, LLIMFloater::findInstance, id = " << conversationItem->getUUID() << llendl; LLIMFloater *conversationFloater = LLIMFloater::findInstance(conversationItem->getUUID()); LLUUID participantID = conversationFloater->getOtherParticipantUUID(); selected_uuids.push_back(participantID); @@ -906,7 +905,6 @@ void LLIMFloaterContainer::doToSelectedConversation(const std::string& command, { //Find the conversation floater associated with the selected id const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); - llinfos << "Merov debug : doToSelectedConversation, LLIMFloater::findInstance, id = " << conversationItem->getUUID() << llendl; LLIMFloater *conversationFloater = LLIMFloater::findInstance(conversationItem->getUUID()); if(conversationFloater) @@ -1234,6 +1232,12 @@ LLConversationItem* LLIMFloaterContainer::addConversationListItem(const LLUUID& participant_view->addToFolder(widget); current_participant_model++; } + // Do that too for the conversation dialog + LLIMConversation *conversation_floater = (uuid.isNull() ? (LLIMConversation*)(LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")) : (LLIMConversation*)(LLIMFloater::findInstance(uuid))); + if (conversation_floater) + { + conversation_floater->buildConversationViewParticipant(); + } if (isWidgetSelected) { -- cgit v1.2.3 From 480c3a1acb32e98d0d64aaf7bb70e4d61e6882f6 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 29 Oct 2012 16:59:53 -0700 Subject: CHUI-469 : Fixed. Add the widget to its map, init the widget map consistently and correctly. --- indra/newview/llimconversation.cpp | 18 +++++++++++++----- indra/newview/llimfloatercontainer.cpp | 1 - 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index ad34acd941..f2421dd78f 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -50,6 +50,7 @@ LLIMConversation::LLIMConversation(const LLSD& session_id) , mCloseBtn(NULL) , mSessionID(session_id.asUUID()) // , mParticipantList(NULL) + , mConversationsRoot(NULL) , mChatHistory(NULL) , mInputEditor(NULL) , mInputEditorTopPad(0) @@ -309,6 +310,15 @@ void LLIMConversation::appendMessage(const LLChat& chat, const LLSD &args) void LLIMConversation::buildConversationViewParticipant() { + // Clear the widget list since we are rebuilding afresh from the model + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + while (widget_it != mConversationsWidgets.end()) + { + removeConversationViewParticipant(widget_it->first); + // Iterators are invalidated by erase so we need to pick begin again + widget_it = mConversationsWidgets.begin(); + } + // Get the model list LLParticipantList* item = getParticipantList(); if (!item) @@ -342,7 +352,7 @@ void LLIMConversation::addConversationViewParticipant(LLConversationItem* partic else { LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); - mConversationsWidgets[uuid] = widget; + mConversationsWidgets[uuid] = participant_view; participant_view->addToFolder(mConversationsRoot); participant_view->setVisible(TRUE); refreshConversation(); @@ -373,10 +383,10 @@ void LLIMConversation::updateConversationViewParticipant(const LLUUID& participa void LLIMConversation::refreshConversation() { - // *TODO: update the conversation name - // *TODO: check that all participant models do have a view (this is a consistency check) + // *TODO: check that all participant models do have a view (debug consistency check) mConversationViewModel.requestSortAll(); mConversationsRoot->arrangeAll(); + mConversationsRoot->update(); } // Copied from LLIMFloaterContainer::createConversationViewParticipant(). Refactor opportunity! @@ -392,8 +402,6 @@ LLConversationViewParticipant* LLIMConversation::createConversationViewParticipa params.tool_tip = params.name; params.participant_id = item->getUUID(); - llinfos << "Merov debug : LLIMConversation, create participant, name = " << item->getDisplayName() << llendl; - return LLUICtrlFactory::create<LLConversationViewParticipant>(params); } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 89dfd2e149..297db96c83 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -129,7 +129,6 @@ void LLIMFloaterContainer::onCurrentChannelChanged(const LLUUID& session_id) { if (session_id != LLUUID::null) { - llinfos << "Merov debug : onCurrentChannelChanged, LLIMFloater::show, id = " << session_id << llendl; LLIMFloater::show(session_id); } } -- cgit v1.2.3 From c0b1ae6d976a94918ea8adc0908eb7c1e3d11459 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Tue, 30 Oct 2012 17:28:39 +0200 Subject: CHUI-446 FIXED Check that parent_session is not null --- indra/newview/llconversationmodel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index f0c8658cfe..67a1aed675 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -401,12 +401,13 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam mDisplayName = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); mNeedsRefresh = true; LLConversationItemSession* parent_session = dynamic_cast<LLConversationItemSession*>(mParent); - if (parent_session) + if (parent_session != NULL) { parent_session->requestSort(); parent_session->updateParticipantName(this); + postEvent("update_participant", parent_session, this); } - postEvent("update_participant", parent_session, this); + } void LLConversationItemParticipant::dumpDebugData() -- cgit v1.2.3 From d2087bdd8a6591cafc6c8d8de7582a9dda6ea352 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Tue, 30 Oct 2012 18:16:56 +0200 Subject: CHUI-437 (Conversation floater shows as transparent after being minimized and unminimized) --- indra/newview/llimfloatercontainer.cpp | 14 -------------- indra/newview/llimfloatercontainer.h | 2 -- 2 files changed, 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index b98558c47b..83233cdd13 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -343,20 +343,6 @@ LLIMFloaterContainer* LLIMFloaterContainer::getInstance() return LLFloaterReg::getTypedInstance<LLIMFloaterContainer>("im_container"); } -void LLIMFloaterContainer::setMinimized(BOOL b) -{ - if (isMinimized() == b) return; - - LLMultiFloater::setMinimized(b); - - if (isMinimized()) return; - - if (getActiveFloater()) - { - getActiveFloater()->setVisible(TRUE); - } -} - // Update all participants in the conversation lists void LLIMFloaterContainer::processParticipantsStyleUpdate() { diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 7d13b37b31..05ea94019b 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -76,8 +76,6 @@ public: static void onCurrentChannelChanged(const LLUUID& session_id); - virtual void setMinimized(BOOL b); - void collapseMessagesPane(bool collapse); // Callbacks -- cgit v1.2.3 From 5215bf6edef283cb6c570d3e7aea11f0ecf8313f Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Tue, 30 Oct 2012 18:38:59 +0200 Subject: CHUI-415 FIXED Set focus to dependee floater before removing dependent floater from it --- indra/llui/llfloater.cpp | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 58b17f74a8..8f7d4afb1b 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -725,7 +725,27 @@ void LLFloater::closeFloater(bool app_quitting) make_ui_sound("UISndWindowClose"); } - //If floater is a dependent, remove it from parent (dependee) + gFocusMgr.clearLastFocusForGroup(this); + + if (hasFocus()) + { + // Do this early, so UI controls will commit before the + // window is taken down. + releaseFocus(); + + // give focus to dependee floater if it exists, and we had focus first + if (isDependent()) + { + LLFloater* dependee = mDependeeHandle.get(); + if (dependee && !dependee->isDead()) + { + dependee->setFocus(TRUE); + } + } + } + + + //If floater is a dependent, remove it from parent (dependee) LLFloater* dependee = mDependeeHandle.get(); if (dependee) { @@ -750,24 +770,6 @@ void LLFloater::closeFloater(bool app_quitting) } cleanupHandles(); - gFocusMgr.clearLastFocusForGroup(this); - - if (hasFocus()) - { - // Do this early, so UI controls will commit before the - // window is taken down. - releaseFocus(); - - // give focus to dependee floater if it exists, and we had focus first - if (isDependent()) - { - LLFloater* dependee = mDependeeHandle.get(); - if (dependee && !dependee->isDead()) - { - dependee->setFocus(TRUE); - } - } - } dirtyRect(); -- cgit v1.2.3 From fb3df4790e27345a1e45f4a4675e756c1e551f21 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Tue, 30 Oct 2012 15:59:42 -0700 Subject: CHUI-459: Creating a fetchAvatarName() method for the LLConversationItemParticipant class to allow the class to query for the avatar display name directly. Also, added a field to store the avatar name cache callback connection so that we can disconnect properly on object destruction to avoid a crash with the callback attempting to access recently freed memory. --- indra/newview/llconversationmodel.cpp | 32 ++++++++++++++++++++++++++++++-- indra/newview/llconversationmodel.h | 12 +++++++++--- indra/newview/llimfloatercontainer.cpp | 11 +---------- indra/newview/llparticipantlist.cpp | 3 +-- 4 files changed, 41 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 67a1aed675..33631a027b 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -369,7 +369,8 @@ LLConversationItemParticipant::LLConversationItemParticipant(std::string display LLConversationItem(display_name,uuid,root_view_model), mIsMuted(false), mIsModerator(false), - mDistToAgent(-1.0) + mDistToAgent(-1.0), + mAvatarNameCacheConnection() { mConvType = CONV_PARTICIPANT; } @@ -378,11 +379,38 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, LLConversationItem(uuid,root_view_model), mIsMuted(false), mIsModerator(false), - mDistToAgent(-1.0) + mDistToAgent(-1.0), + mAvatarNameCacheConnection() { mConvType = CONV_PARTICIPANT; } +LLConversationItemParticipant::~LLConversationItemParticipant() +{ + // Disconnect any previous avatar name cache connection to ensure + // that the callback method is not called after destruction + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } +} + +void LLConversationItemParticipant::fetchAvatarName() +{ + // Disconnect any previous avatar name cache connection + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + + // Request the avatar name from the cache + llassert(getUUID().notNull()); + if (getUUID().notNull()) + { + mAvatarNameCacheConnection = LLAvatarNameCache::get(getUUID(), boost::bind(&LLConversationItemParticipant::onAvatarNameCache, this, _2)); + } +} + void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) { menuentry_vec_t items; diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 1d082852f5..481d46af58 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -27,9 +27,11 @@ #ifndef LL_LLCONVERSATIONMODEL_H #define LL_LLCONVERSATIONMODEL_H +#include <boost/signals2.hpp> + +#include "llavatarname.h" #include "llfolderviewitem.h" #include "llfolderviewmodel.h" -#include "llavatarname.h" #include "llviewerfoldertype.h" // Implementation of conversations list @@ -177,7 +179,7 @@ class LLConversationItemParticipant : public LLConversationItem public: LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); - virtual ~LLConversationItemParticipant() {} + virtual ~LLConversationItemParticipant(); virtual const std::string& getDisplayName() const { return mDisplayName; } @@ -189,17 +191,21 @@ public: void setDistance(F64 dist) { mDistToAgent = dist; mNeedsRefresh = true; } void buildContextMenu(LLMenuGL& menu, U32 flags); - void onAvatarNameCache(const LLAvatarName& av_name); virtual const bool getDistanceToAgent(F64& dist) const { dist = mDistToAgent; return (dist >= 0.0); } + void fetchAvatarName(); + void dumpDebugData(); private: + void onAvatarNameCache(const LLAvatarName& av_name); + bool mIsMuted; // default is false bool mIsModerator; // default is false std::string mDisplayName; F64 mDistToAgent; // Distance to the agent. A negative (meaningless) value means the distance has not been set. + boost::signals2::connection mAvatarNameCacheConnection; }; // We don't want to ever filter conversations but we need to declare that class to create a conversation view model. diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index f46ecd905a..00ae0b8fd8 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -358,16 +358,7 @@ void LLIMFloaterContainer::processParticipantsStyleUpdate() { LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); // Get the avatar name for this participant id from the cache and update the model - LLUUID participant_id = participant_model->getUUID(); - LLAvatarName av_name; - LLAvatarNameCache::get(participant_id,&av_name); - // Avoid updating the model though if the cache is still waiting for its first update - if (!av_name.mDisplayName.empty()) - { - participant_model->onAvatarNameCache(av_name); - } - // Bind update to the next cache name signal - LLAvatarNameCache::get(participant_id, boost::bind(&LLConversationItemParticipant::onAvatarNameCache, participant_model, _2)); + participant_model->fetchAvatarName(); // Next participant current_participant_model++; } diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index b263143bd1..e199cb5776 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -676,8 +676,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) LLAvatarName avatar_name; bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name); participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.mDisplayName , avatar_id, mRootViewModel); - // Binds avatar's name update callback - LLAvatarNameCache::get(avatar_id, boost::bind(&LLConversationItemParticipant::onAvatarNameCache, participant, _2)); + participant->fetchAvatarName(); if (mAvatarList) { mAvatarList->getIDs().push_back(avatar_id); -- cgit v1.2.3 From ec57bd2f8e2859787b274c118fabbc19f76e04b1 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Tue, 30 Oct 2012 16:28:57 -0700 Subject: CHUI-461: Changing the default floater opacities according to Leo's guidelines. --- indra/newview/app_settings/settings.xml | 4 ++-- indra/newview/skins/default/xui/en/panel_preferences_colors.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 9ada5e5918..0537487ca3 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -69,7 +69,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>0.95</real> + <real>1</real> </map> <key>AdvanceSnapshot</key> <map> @@ -4302,7 +4302,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>0.65</real> + <real>0.95</real> </map> <key>InBandwidth</key> <map> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_colors.xml b/indra/newview/skins/default/xui/en/panel_preferences_colors.xml index 2b22f0d6e3..9e825fe516 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_colors.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_colors.xml @@ -362,7 +362,7 @@ follows="left|top" height="16" increment="0.01" - initial_value="0.8" + initial_value="1.0" layout="topleft" label_width="115" label="Active:" @@ -380,7 +380,7 @@ follows="left|top" height="16" increment="0.01" - initial_value="0.5" + initial_value="0.95" layout="topleft" label_width="115" label="Inactive:" -- cgit v1.2.3 From 9d9853082361b35987a70574b422c40e8ee04d93 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 30 Oct 2012 18:20:28 -0700 Subject: CHUI-471: Adjusted conversationview so that indentation of the avatar icon is dependent upon getIndentation() instead of modifying avatar icon's left value. --- indra/newview/llconversationview.cpp | 18 +++++++++++++++++- indra/newview/llconversationview.h | 1 + indra/newview/llimfloatercontainer.cpp | 6 ++---- .../xui/en/widgets/conversation_view_participant.xml | 2 -- 4 files changed, 20 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 3082284991..81212a9141 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -432,6 +432,22 @@ void LLConversationViewParticipant::draw() LLView::draw(); } +// virtual +S32 LLConversationViewParticipant::arrange(S32* width, S32* height) +{ + //Need to call arrange first since it computes value used in getIndentation() + S32 arranged = LLFolderViewItem::arrange(width, height); + + //Adjusts the avatar icon based upon the indentation + LLRect avatarRect(getIndentation(), + mAvatarIcon->getRect().mTop, + getIndentation() + mAvatarIcon->getRect().getWidth(), + mAvatarIcon->getRect().mBottom); + mAvatarIcon->setShape(avatarRect); + + return arranged; +} + void LLConversationViewParticipant::selectItem() { LLConversationItem* vmi = this->getParentFolder() ? static_cast<LLConversationItem*>(this->getParentFolder()->getViewModelItem()) : NULL; @@ -507,7 +523,7 @@ void LLConversationViewParticipant::onMouseLeave(S32 x, S32 y, MASK mask) S32 LLConversationViewParticipant::getLabelXPos() { - return mAvatarIcon->getRect().mRight + mIconPad; + return getIndentation() + mAvatarIcon->getRect().getWidth() + mIconPad; } // static diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index bd95387bbe..18cb9bdb27 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -129,6 +129,7 @@ protected: void initFromParams(const Params& params); BOOL postBuild(); /*virtual*/ void draw(); + /*virtual*/ S32 arrange(S32* width, S32* height); void onInfoBtnClick(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 01456fee3b..298a6055bf 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -1289,9 +1289,6 @@ LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParti LLRect panel_rect = mConversationsListPanel->getRect(); params.name = item->getDisplayName(); - //params.icon = bridge->getIcon(); - //params.icon_open = bridge->getOpenIcon(); - //params.creation_date = bridge->getCreationDate(); params.root = mConversationsRoot; params.listener = item; @@ -1299,7 +1296,8 @@ LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParti params.rect = LLRect (0, 24, panel_rect.getWidth(), 0); params.tool_tip = params.name; params.participant_id = item->getUUID(); - + params.folder_indentation = 42; + return LLUICtrlFactory::create<LLConversationViewParticipant>(params); } diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml index 0024decd4c..b83d9122f7 100755 --- a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml +++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <conversation_view_participant folder_arrow_image="Folder_Arrow" - folder_indentation="0" item_height="24" item_top_pad="0" selection_image="Rounded_Square" @@ -20,7 +19,6 @@ height="20" default_icon_name="Generic_Person" layout="topleft" - left="50" top="2" width="20" /> <info_button -- cgit v1.2.3 From f9b1b440710668a9979e33c7582d79d14cae8d0d Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 30 Oct 2012 18:27:56 -0700 Subject: CHUI-463 : Fixed. Allowed a model to be shared by several views. --- indra/llui/llfolderviewitem.cpp | 26 +++++++++++++++++++------- indra/llui/llfolderviewmodel.h | 2 ++ indra/newview/llconversationmodel.cpp | 2 +- 3 files changed, 22 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 5d4c27ee6c..b289581dc2 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1563,7 +1563,7 @@ BOOL LLFolderViewFolder::isRemovable() void LLFolderViewFolder::addItem(LLFolderViewItem* item) { if (item->getParentFolder()) -{ + { item->getParentFolder()->extractItem(item); } item->setParentFolder(this); @@ -1574,7 +1574,13 @@ void LLFolderViewFolder::addItem(LLFolderViewItem* item) item->setVisible(FALSE); addChild(item); - getViewModelItem()->addChild(item->getViewModelItem()); + + // When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it + // Note: this happens when models are created before views or shared between views + if (!item->getViewModelItem()->hasParent()) + { + getViewModelItem()->addChild(item->getViewModelItem()); + } //TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria //// Traverse parent folders and update creation date and resort, if necessary @@ -1593,11 +1599,11 @@ void LLFolderViewFolder::addItem(LLFolderViewItem* item) // this is an internal method used for adding items to folders. void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) - { +{ if (folder->mParentFolder) - { + { folder->mParentFolder->extractItem(folder); - } + } folder->mParentFolder = this; mFolders.push_back(folder); folder->setOrigin(0, 0); @@ -1607,9 +1613,15 @@ void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) //folder->requestArrange(); //requestSort(); - addChild( folder ); - getViewModelItem()->addChild(folder->getViewModelItem()); + addChild(folder); + + // When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it + // Note: this happens when models are created before views or shared between views + if (!folder->getViewModelItem()->hasParent()) + { + getViewModelItem()->addChild(folder->getViewModelItem()); } +} void LLFolderViewFolder::requestArrange() { diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 5ec08ae211..7019857c0f 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -202,6 +202,7 @@ public: virtual S32 getSortVersion() = 0; virtual void setSortVersion(S32 version) = 0; virtual void setParent(LLFolderViewModelItem* parent) = 0; + virtual bool hasParent() = 0; protected: @@ -332,6 +333,7 @@ public: protected: virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } + virtual bool hasParent() { return mParent != NULL; } S32 mSortVersion; bool mPassedFilter; diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index f0c8658cfe..74188195f6 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -405,8 +405,8 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam { parent_session->requestSort(); parent_session->updateParticipantName(this); + postEvent("update_participant", parent_session, this); } - postEvent("update_participant", parent_session, this); } void LLConversationItemParticipant::dumpDebugData() -- cgit v1.2.3 From a8ca9dc5a98d0bd99581d17be45a36c602ce87fd Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 31 Oct 2012 17:51:55 +0200 Subject: CHUI-374 ADD. FIX, CHUI-442 FIXED (Nearby chat is torn off and cannot be docked if nearby chat is received while conversation floater is closed) - implement. lazy creating of container --- indra/newview/llchicletbar.cpp | 2 +- indra/newview/llimconversation.cpp | 49 ++++++++++++++++++++++++++++++++++ indra/newview/llimconversation.h | 11 ++++++++ indra/newview/llimfloater.cpp | 34 ++--------------------- indra/newview/llimfloater.h | 1 - indra/newview/llimfloatercontainer.cpp | 8 +++--- indra/newview/llnearbychat.cpp | 34 ++--------------------- indra/newview/llnearbychat.h | 5 +--- 8 files changed, 70 insertions(+), 74 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index 39f5d0b8f6..3ebb83b336 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -97,7 +97,7 @@ void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& nam // Do not spawn chiclet when using the new multitab conversation UI if (LLIMConversation::isChatMultiTab()) { - LLIMFloater::addToHost(session_id); + LLIMConversation::addToHost(session_id); return; } diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 74bf8cb6fe..b687e18cae 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -116,6 +116,55 @@ LLIMConversation* LLIMConversation::getConversation(const LLUUID& uuid) return conv; }; +void LLIMConversation::setVisible(BOOL visible) +{ + LLTransientDockableFloater::setVisible(visible); + + if(visible) + { + LLIMConversation::addToHost(mSessionID); + } + setFocus(visible); +} + + + +void LLIMConversation::addToHost(const LLUUID& session_id) +{ + if ((session_id.notNull() && !gIMMgr->hasSession(session_id)) + || !LLIMConversation::isChatMultiTab()) + { + return; + } + + // Get the floater: this will create the instance if it didn't exist + LLIMConversation* conversp = LLIMConversation::getConversation(session_id); + if (conversp) + { + LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); + + // Do not add again existing floaters + if (floater_container && !conversp->isHostAttached()) + { + conversp->setHostAttached(true); + + if (!conversp->isNearbyChat() + || gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) + { + floater_container->addFloater(conversp, TRUE, LLTabContainer::END); + } + else + { + // setting of the "potential" host for Nearby Chat: this sequence sets + // LLFloater::mHostHandle = NULL (a current host), but + // LLFloater::mLastHostHandle = floater_container (a "future" host) + conversp->setHost(floater_container); + conversp->setHost(NULL); + } + + } + } +} BOOL LLIMConversation::postBuild() { diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 603e0d0197..bff4cb4a31 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -59,17 +59,27 @@ public: */ static bool isChatMultiTab(); + // add conversation to container + static void addToHost(const LLUUID& session_id); + + bool isHostAttached() {return mIsHostAttached;} + void setHostAttached(bool is_attached) {mIsHostAttached = is_attached;} + static LLIMConversation* findConversation(const LLUUID& uuid); static LLIMConversation* getConversation(const LLUUID& uuid); // show/hide the translation check box void showTranslationCheckbox(const BOOL visible = FALSE); + bool isNearbyChat() {return mIsNearbyChat;} + // LLFloater overrides /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ BOOL postBuild(); /*virtual*/ void draw(); + /*virtual*/ void setVisible(BOOL visible); + protected: @@ -139,6 +149,7 @@ private: void reshapeChatHistory(); bool checkIfTornOff(); + bool mIsHostAttached; LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. }; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 1af5def5f0..3545b8ff18 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -582,37 +582,6 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) } } -void LLIMFloater::addToHost(const LLUUID& session_id) -{ - if (!LLIMConversation::isChatMultiTab() || !gIMMgr->hasSession(session_id)) - { - return; - } - - // Test the existence of the floater before we try to create it - bool exist = findInstance(session_id); - - // Get the floater: this will create the instance if it didn't exist - LLIMFloater* floater = getInstance(session_id); - if (floater) - { - - LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); - - // Do not add again existing floaters - if (!exist) - { - // LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; - // TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists - LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END; - if (floater_container) - { - floater_container->addFloater(floater, FALSE, i_pt); - } - } - } -} - //static LLIMFloater* LLIMFloater::show(const LLUUID& session_id) @@ -721,7 +690,7 @@ void LLIMFloater::setVisible(BOOL visible) (LLNotificationsUI::LLChannelManager::getInstance()-> findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); - LLTransientDockableFloater::setVisible(visible); + LLIMConversation::setVisible(visible); // update notification channel state if(channel) @@ -1309,6 +1278,7 @@ void LLIMFloater::sRemoveTypingIndicator(const LLSD& data) floater->removeTypingIndicator(); } +// static void LLIMFloater::onIMChicletCreated( const LLUUID& session_id ) { LLIMFloater::addToHost(session_id); diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 8a0d6f10e0..6c69ed3462 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -72,7 +72,6 @@ public: static LLIMFloater* findInstance(const LLUUID& session_id); static LLIMFloater* getInstance(const LLUUID& session_id); - static void addToHost(const LLUUID& session_id); // LLFloater overrides /*virtual*/ void onClose(bool app_quitting); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 00ae0b8fd8..65dc024aea 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -98,7 +98,7 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - LLIMFloater::addToHost(session_id); + LLIMConversation::addToHost(session_id); addConversationListItem(session_id); } @@ -109,7 +109,7 @@ void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std: void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { - LLIMFloater::addToHost(session_id); + LLIMConversation::addToHost(session_id); addConversationListItem(session_id); } @@ -490,9 +490,9 @@ void LLIMFloaterContainer::setVisible(BOOL visible) } nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); - if (nearby_chat && !nearby_chat->isHostSet()) + if (nearby_chat) { - nearby_chat->addToHost(); + LLIMConversation::addToHost(LLUUID()); } // We need to show/hide all the associated conversations that have been torn off diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 5b274dd389..d1c7c6bfd7 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -91,8 +91,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd) : LLIMConversation(llsd), //mOutputMonitor(NULL), mSpeakerMgr(NULL), - mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT), - mIsHostSet(false) + mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) { mIsP2PChat = false; mIsNearbyChat = true; @@ -283,7 +282,7 @@ void LLNearbyChat::setFocus(BOOL focusFlag) } -void LLNearbyChat::setVisible(BOOL visible) +void LLNearbyChat::setVisible(BOOL visible) { LLIMConversation::setVisible(visible); @@ -304,35 +303,6 @@ void LLNearbyChat::onTearOffClicked() gSavedSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater); } -void LLNearbyChat::addToHost() -{ - if ( LLIMConversation::isChatMultiTab()) - { - LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); - if (im_box) - { - if (gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) - { - im_box->addFloater(this, TRUE, LLTabContainer::END); - } - else - { - // setting of the "potential" host: this sequence sets - // LLFloater::mHostHandle = NULL (a current host), but - // LLFloater::mLastHostHandle = im_box (a "future" host) - setHost(im_box); - setHost(NULL); - } - } - - mIsHostSet = true; - } - } - -bool LLNearbyChat::isHostSet() -{ - return mIsHostSet; -} // virtual void LLNearbyChat::onOpen(const LLSD& key) diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 7ada4daea8..b155fd3c26 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -53,7 +53,7 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void setFocus(BOOL focusFlag); - /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ void setVisible(BOOL visible); void loadHistory(); void reloadMessages(); @@ -78,8 +78,6 @@ public: static void startChat(const char* line); static void stopChat(); - bool isHostSet(); - static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate); static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); @@ -121,7 +119,6 @@ private: LLHandle<LLView> mPopupMenuHandle; std::vector<LLChat> mMessageArchive; - bool mIsHostSet; }; #endif -- cgit v1.2.3 From 7f2ea292e10b10958b3e00a641b50b194f131e41 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 31 Oct 2012 19:27:41 -0700 Subject: CHUI-474 : Fixed. Refresh the participants list in torn off dialog more often. --- indra/llui/llfolderview.cpp | 2 +- indra/newview/llimconversation.cpp | 40 +++++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index c31a832141..a33ffc4240 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -566,7 +566,7 @@ void LLFolderView::sanitizeSelection() parent_folder; parent_folder = parent_folder->getParentFolder()) { - if (parent_folder->getViewModelItem()->potentiallyVisible()) + if (parent_folder->getViewModelItem() && parent_folder->getViewModelItem()->potentiallyVisible()) { // give initial selection to first ancestor folder that potentially passes the filter if (!new_selection) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 3b6294f43b..aee6642150 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -376,7 +376,44 @@ void LLIMConversation::updateConversationViewParticipant(const LLUUID& participa void LLIMConversation::refreshConversation() { - // *TODO: check that all participant models do have a view (debug consistency check) + // Debug : Check that all participant models do have a view (debug consistency check) + /* + LLParticipantList* item = getParticipantList(); + llinfos << "Merov debug : Start consistency check" << llendl; + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); + while (current_participant_model != end_participant_model) + { + LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); + if (participant_model != NULL) + { + LLUUID uuid = participant_model->getUUID(); + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); + if (!widget) + { + llinfos << "Merov debug : Consistency error! Couldn't find widget for " << participant_model->getName() << llendl; + } + else + { + llinfos << "Merov debug : Consistency check pass for " << participant_model->getName() << llendl; + } + } + else + { + llinfos << "Merov debug : Consistency check, skip non participant child" << llendl; + } + current_participant_model++; + } + llinfos << "Merov debug : End consistency check" << llendl; + */ + + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + while (widget_it != mConversationsWidgets.end()) + { + widget_it->second->refresh(); + widget_it->second->setVisible(TRUE); + ++widget_it; + } mConversationViewModel.requestSortAll(); mConversationsRoot->arrangeAll(); mConversationsRoot->update(); @@ -629,6 +666,7 @@ void LLIMConversation::onTearOffClicked() initRectControl(); LLFloater::onClickTearOff(this); updateHeaderAndToolbar(); + refreshConversation(); } // static -- cgit v1.2.3 From 51cabb2089244f170b307b436e0014a872a145ed Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Thu, 1 Nov 2012 13:56:25 +0200 Subject: CHUI-444 (Click target off when conversation list is minimized to icons) --- indra/llui/llfolderviewitem.cpp | 4 ++-- indra/llui/llfolderviewitem.h | 1 + indra/newview/llconversationview.h | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 4825fc613c..7c63cad1b7 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1826,7 +1826,7 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) } if( !handled ) { - if(mIndentation < x && x < mIndentation + mArrowSize + mTextPad) + if(mIndentation < x && x < mIndentation + (isMinimized() ? 0 : mArrowSize) + mTextPad) { toggleOpen(); handled = TRUE; @@ -1850,7 +1850,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) } if( !handled ) { - if(mIndentation < x && x < mIndentation + mArrowSize + mTextPad) + if(mIndentation < x && x < mIndentation + (isMinimized() ? 0 : mArrowSize) + mTextPad) { // don't select when user double-clicks plus sign // so as not to contradict single-click behavior diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index d4002c3184..7cbe70fb8b 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -289,6 +289,7 @@ protected: friend class LLUICtrlFactory; void updateLabelRotation(); + virtual bool isMinimized() { return FALSE; } public: typedef std::list<LLFolderViewItem*> items_t; diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index bd95387bbe..4d77a4ade0 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -69,6 +69,8 @@ public: /*virtual*/ void toggleOpen(); + /*virtual*/ bool isMinimized() { return mMinimizedMode; } + void toggleMinimizedMode(bool is_minimized); void setVisibleIfDetached(BOOL visible); -- cgit v1.2.3 From d886d89f53267d9a9a02c775fcb16e667278b904 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Thu, 1 Nov 2012 15:00:50 +0200 Subject: CHUI-446 FIXED Checkm mParent before using dynamic_cast --- indra/newview/llconversationmodel.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 33631a027b..47a82bfe17 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -428,14 +428,16 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam mName = (av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername); mDisplayName = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); mNeedsRefresh = true; - LLConversationItemSession* parent_session = dynamic_cast<LLConversationItemSession*>(mParent); - if (parent_session != NULL) + if(mParent != NULL) { - parent_session->requestSort(); - parent_session->updateParticipantName(this); - postEvent("update_participant", parent_session, this); + LLConversationItemSession* parent_session = dynamic_cast<LLConversationItemSession*>(mParent); + if (parent_session != NULL) + { + parent_session->requestSort(); + parent_session->updateParticipantName(this); + postEvent("update_participant", parent_session, this); + } } - } void LLConversationItemParticipant::dumpDebugData() -- cgit v1.2.3 From 424a80155ac755bc0191ddd44ef125bdbda39fa5 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Thu, 1 Nov 2012 16:58:55 +0200 Subject: CHUI-445 FIXED Select the next conversation in the list when current conversation is deleted --- indra/newview/llimfloatercontainer.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 65dc024aea..f85aa9a353 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -1206,6 +1206,7 @@ bool LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener bool isWidgetSelected = false; + LLFolderViewItem* new_selection = NULL; conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(uuid); if (widget_it != mConversationsWidgets.end()) { @@ -1213,6 +1214,11 @@ bool LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c if (widget) { isWidgetSelected = widget->isSelected(); + new_selection = mConversationsRoot->getNextFromChild(widget); + if(new_selection == NULL) + { + new_selection = mConversationsRoot->getPreviousFromChild(widget); + } widget->destroyView(); } } @@ -1225,12 +1231,13 @@ bool LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c if (change_focus) { setFocus(TRUE); - conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); - if (widget_it != mConversationsWidgets.end()) + if(new_selection != NULL) { - mSelectedSession = widget_it->first; - LLFolderViewItem* widget = widget_it->second; - widget->selectItem(); + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem()); + if(vmi != NULL) + { + selectConversation(vmi->getUUID()); + } } } return isWidgetSelected; -- cgit v1.2.3 From 0f1c2f8aba148aa7e594d4c9e1bc6a95d34bd99b Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 1 Nov 2012 14:55:47 -0700 Subject: CHUI-472: Problem: Only the converation panel was user/auto resizeable but the participants panel was not. By one have only resizable this prevented both panels from being resized. Solution: Now set the participants panel to be user/auto resizable as well. --- indra/newview/skins/default/xui/en/floater_im_session.xml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 84fba0a3b3..a889eb7933 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -14,7 +14,7 @@ width="394" can_resize="true" can_tear_off="false" - min_width="250" + min_width="340" min_height="190" positioning="relative"> <floater.string name="call_btn_start">Conv_toolbar_open_call</floater.string> @@ -157,7 +157,8 @@ min_width="115" width="150" height="310" - auto_resize="false"> + user_resize="true" + auto_resize="true"> </layout_panel> <layout_panel default_tab_group="3" @@ -171,7 +172,8 @@ user_resize="true" auto_resize="true" visible="true" - name="left_part_holder"> + name="left_part_holder" + min_width="225"> <panel name="trnsAndChat_panel" follows="all" -- cgit v1.2.3 From ef5121ffb309c0317a4eb478e9527d33441377c2 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 2 Nov 2012 11:01:08 -0700 Subject: CHUI-481 : WIP : Make updateSessionName() a virtual method of LLIMConversation so we can eventually call it on events --- indra/newview/llimconversation.cpp | 6 +++++ indra/newview/llimconversation.h | 3 +++ indra/newview/llimfloater.cpp | 54 +++++++++++++++++++++++--------------- indra/newview/llimfloater.h | 4 +-- 4 files changed, 44 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index aee6642150..a6a246a01e 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -508,6 +508,12 @@ void LLIMConversation::hideOrShowTitle() floater_contents->setShape(contents_rect); } +void LLIMConversation::updateSessionName(const std::string& name) +{ + llinfos << "Merov debug : updateSessionName, name = " << name << llendl; + mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + name); +} + void LLIMConversation::hideAllStandardButtons() { for (S32 i = 0; i < BUTTON_COUNT; i++) diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 4e66d000e6..2bd1582e87 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -104,6 +104,9 @@ protected: /// Update floater header and toolbar buttons when hosted/torn off state is toggled. void updateHeaderAndToolbar(); + // Update the input field help text and other places that need the session name + virtual void updateSessionName(const std::string& name); + // set the enable/disable state for the Call button virtual void enableDisableCallBtn(); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 6d90b6a0b2..4e1bfb4e77 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -243,7 +243,6 @@ void LLIMFloater::initIMSession(const LLUUID& session_id) { mIsP2PChat = mSession->isP2PSessionType(); mSessionInitialized = mSession->mSessionInitialized; - mDialog = mSession->mType; } } @@ -281,7 +280,7 @@ void LLIMFloater::initIMFloater() else { std::string session_name(LLIMModel::instance().getName(mSessionID)); - updateSessionName(session_name, session_name); + updateSessionName(session_name); // For ad hoc conferences we should update the title with participants names. if ((IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) @@ -292,6 +291,8 @@ void LLIMFloater::initIMFloater() mParticipantsListRefreshConnection.disconnect(); } + // CHUI-441: We shouldn't have any avatar_list anymore... see floater_im_session.xml + // *TODO: Track and delete if not necessary anymore LLAvatarList* avatar_list = getChild<LLAvatarList>("speakers_list"); mParticipantsListRefreshConnection = avatar_list->setRefreshCompleteCallback( boost::bind(&LLIMFloater::onParticipantsListChanged, this, _1)); @@ -525,20 +526,21 @@ void LLIMFloater::onVoiceChannelStateChanged( updateCallBtnState(callIsActive); } -void LLIMFloater::updateSessionName(const std::string& ui_title, - const std::string& ui_label) +void LLIMFloater::updateSessionName(const std::string& name) { - mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + ui_label); - setTitle(ui_title); + LLIMConversation::updateSessionName(name); + setTitle(name); } void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) { - // Use display name only for labels, as the extended name will be in the - // floater title + // Use display name for label + updateSessionName(av_name.mDisplayName); + + // Overwrite the floater title with the extended name std::string ui_title = av_name.getCompleteName(); - updateSessionName(ui_title, av_name.mDisplayName); + setTitle(ui_title); mTypingStart.setArg("[NAME]", ui_title); } @@ -550,35 +552,45 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) return; } - bool all_names_resolved = true; std::vector<LLSD> participants_uuids; uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string + LLUUID unfound_id; avatar_list->getValues(participants_uuids); - // Check whether we have all participants names in LLAvatarNameCache + // Check participants names in LLAvatarNameCache for (std::vector<LLSD>::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it) { const LLUUID& id = it->asUUID(); - temp_uuids.push_back(id); LLAvatarName av_name; if (!LLAvatarNameCache::get(id, &av_name)) { - all_names_resolved = false; - - // If a name is not found in cache, request it and continue the process recursively - // until all ids are resolved into names. - LLAvatarNameCache::get(id, - boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list)); - break; + // Keep the first not found avatar id + if (unfound_id.isNull()) + { + unfound_id = id; + } } + else + { + // Add the participant to the list of existing names + temp_uuids.push_back(id); + } } - if (all_names_resolved) + if (temp_uuids.size() != 0) { + // Build the session name and update it std::string ui_title; LLAvatarActions::buildResidentsString(temp_uuids, ui_title); - updateSessionName(ui_title, ui_title); + updateSessionName(ui_title); + } + + if (unfound_id.notNull()) + { + // If a name is not found in cache, request it and continue the process recursively + // until all ids are resolved into names. + LLAvatarNameCache::get(unfound_id, boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list)); } } diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 8a0d6f10e0..ec3a96f694 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -139,8 +139,8 @@ private: /*virtual*/ void onClickCloseBtn(); - // Update the window title, input field help text, etc. - void updateSessionName(const std::string& ui_title, const std::string& ui_label); + // Update the window title and input field help text + /*virtual*/ void updateSessionName(const std::string& name); // For display name lookups for IM window titles void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); -- cgit v1.2.3 From 6e2b3527cc95b92bf136b65fd2ee344d4c879faa Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Fri, 2 Nov 2012 13:22:48 -0700 Subject: CHUI-475: Ensuring that objects that query the avatar name cache with a callback store the connection and disconnect on object destruction. This should help resolve some of the heap corruption we are seeing. --- indra/llui/llnotifications.cpp | 24 ++++++++---- indra/llui/llnotifications.h | 22 +++++++++-- indra/newview/llavatariconctrl.cpp | 29 ++++++++++++-- indra/newview/llavatariconctrl.h | 18 ++++++--- indra/newview/llavatarlistitem.cpp | 34 +++++++++++++--- indra/newview/llavatarlistitem.h | 5 +++ indra/newview/llchathistory.cpp | 80 +++++++++++++++++++++++++------------- 7 files changed, 157 insertions(+), 55 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index fdd45bd76f..929b7da081 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1787,22 +1787,18 @@ std::ostream& operator<<(std::ostream& s, const LLNotification& notification) return s; } -//static -void LLPostponedNotification::lookupName(LLPostponedNotification* thiz, - const LLUUID& id, +void LLPostponedNotification::lookupName(const LLUUID& id, bool is_group) { if (is_group) { gCacheName->getGroup(id, boost::bind(&LLPostponedNotification::onGroupNameCache, - thiz, _1, _2, _3)); + this, _1, _2, _3)); } else { - LLAvatarNameCache::get(id, - boost::bind(&LLPostponedNotification::onAvatarNameCache, - thiz, _1, _2)); + fetchAvatarName(id); } } @@ -1813,6 +1809,20 @@ void LLPostponedNotification::onGroupNameCache(const LLUUID& id, finalizeName(full_name); } +void LLPostponedNotification::fetchAvatarName(const LLUUID& id) +{ + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + + if (id.notNull()) + { + mAvatarNameCacheConnection = LLAvatarNameCache::get(id, + boost::bind(&LLPostponedNotification::onAvatarNameCache, this, _1, _2)); + } +} + void LLPostponedNotification::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) { diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 19b30b8973..c677dfe298 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -87,6 +87,7 @@ #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> #include <boost/type_traits.hpp> +#include <boost/signals2.hpp> #include "llevents.h" #include "llfunctorregistry.h" @@ -972,14 +973,15 @@ public: thiz->mParams = params; // Avoid header file dependency on llcachename.h - lookupName(thiz, id, is_group); + thiz->lookupName(id, is_group); } private: - static void lookupName(LLPostponedNotification* thiz, const LLUUID& id, bool is_group); + void lookupName(const LLUUID& id, bool is_group); // only used for groups void onGroupNameCache(const LLUUID& id, const std::string& full_name, bool is_group); // only used for avatars + void fetchAvatarName(const LLUUID& id); void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); // used for both group and avatar names void finalizeName(const std::string& name); @@ -990,8 +992,19 @@ private: } protected: - LLPostponedNotification() {} - virtual ~LLPostponedNotification() {} + LLPostponedNotification() + : mParams(), + mName(), + mAvatarNameCacheConnection() + {} + + virtual ~LLPostponedNotification() + { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + } /** * Abstract method provides possibility to modify notification parameters and @@ -1002,6 +1015,7 @@ protected: LLNotification::Params mParams; std::string mName; + boost::signals2::connection mAvatarNameCacheConnection; }; // Stores only persistent notifications. diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 62c6c6763b..6355f0db56 100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -28,6 +28,8 @@ #include "llavatariconctrl.h" +#include <boost/signals2.hpp> + // viewer includes #include "llagent.h" #include "llavatarconstants.h" @@ -148,9 +150,13 @@ LLAvatarIconCtrl::Params::Params() LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p) -: LLIconCtrl(p), + : LLIconCtrl(p), + LLAvatarPropertiesObserver(), + mAvatarId(), + mFullName(), mDrawTooltip(p.draw_tooltip), - mDefaultIconName(p.default_icon_name) + mDefaultIconName(p.default_icon_name), + mAvatarNameCacheConnection() { mPriority = LLViewerFetchedTexture::BOOST_ICON; @@ -203,6 +209,11 @@ LLAvatarIconCtrl::~LLAvatarIconCtrl() LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarId, this); // Name callbacks will be automatically disconnected since LLUICtrl is trackable } + + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } } //virtual @@ -245,9 +256,19 @@ void LLAvatarIconCtrl::setValue(const LLSD& value) LLIconCtrl::setValue(value); } - if (mAvatarId != LLUUID::null) + fetchAvatarName(); +} + +void LLAvatarIconCtrl::fetchAvatarName() +{ + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + + if (mAvatarId.notNull()) { - LLAvatarNameCache::get(mAvatarId, boost::bind(&LLAvatarIconCtrl::onAvatarNameCache, this, _1, _2)); + mAvatarNameCacheConnection = LLAvatarNameCache::get(mAvatarId, boost::bind(&LLAvatarIconCtrl::onAvatarNameCache, this, _1, _2)); } } diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h index 7f568fc5b8..f55967926a 100644 --- a/indra/newview/llavatariconctrl.h +++ b/indra/newview/llavatariconctrl.h @@ -27,6 +27,8 @@ #ifndef LL_LLAVATARICONCTRL_H #define LL_LLAVATARICONCTRL_H +#include <boost/signals2.hpp> + #include "lliconctrl.h" #include "llavatarpropertiesprocessor.h" #include "llviewermenu.h" @@ -86,20 +88,24 @@ public: // LLAvatarPropertiesProcessor observer trigger virtual void processProperties(void* data, EAvatarProcessorType type); - void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); - const LLUUID& getAvatarId() const { return mAvatarId; } const std::string& getFullName() const { return mFullName; } void setDrawTooltip(bool value) { mDrawTooltip = value;} protected: - LLUUID mAvatarId; - std::string mFullName; - bool mDrawTooltip; - std::string mDefaultIconName; + LLUUID mAvatarId; + std::string mFullName; + bool mDrawTooltip; + std::string mDefaultIconName; bool updateFromCache(); + +private: + void fetchAvatarName(); + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + + boost::signals2::connection mAvatarNameCacheConnection; }; #endif // LL_LLAVATARICONCTRL_H diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 7b5229b5e6..7ff1b39573 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -27,6 +27,8 @@ #include "llviewerprecompiledheaders.h" +#include <boost/signals2.hpp> + #include "llavataractions.h" #include "llavatarlistitem.h" @@ -59,7 +61,8 @@ LLAvatarListItem::Params::Params() LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/) -: LLPanel(), + : LLPanel(), + LLFriendObserver(), mAvatarIcon(NULL), mAvatarName(NULL), mLastInteractionTime(NULL), @@ -74,7 +77,8 @@ LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/) mShowInfoBtn(true), mShowProfileBtn(true), mShowPermissions(false), - mHovered(false) + mHovered(false), + mAvatarNameCacheConnection() { if (not_from_ui_factory) { @@ -87,7 +91,14 @@ LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/) LLAvatarListItem::~LLAvatarListItem() { if (mAvatarId.notNull()) + { LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarId, this); + } + + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } } BOOL LLAvatarListItem::postBuild() @@ -130,6 +141,19 @@ BOOL LLAvatarListItem::postBuild() return TRUE; } +void LLAvatarListItem::fetchAvatarName() +{ + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + + if (mAvatarId.notNull()) + { + mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLAvatarListItem::onAvatarNameCache, this, _2)); + } +} + S32 LLAvatarListItem::notifyParent(const LLSD& info) { if (info.has("visibility_changed")) @@ -260,8 +284,7 @@ void LLAvatarListItem::setAvatarId(const LLUUID& id, const LLUUID& session_id, b mAvatarIcon->setValue(id); // Set avatar name. - LLAvatarNameCache::get(id, - boost::bind(&LLAvatarListItem::onAvatarNameCache, this, _2)); + fetchAvatarName(); } } @@ -414,8 +437,7 @@ std::string LLAvatarListItem::getAvatarToolTip() const void LLAvatarListItem::updateAvatarName() { - LLAvatarNameCache::get(getAvatarId(), - boost::bind(&LLAvatarListItem::onAvatarNameCache, this, _2)); + fetchAvatarName(); } //== PRIVATE SECITON ========================================================== diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 28a50870d4..41853b6b51 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -27,6 +27,8 @@ #ifndef LL_LLAVATARLISTITEM_H #define LL_LLAVATARLISTITEM_H +#include <boost/signals2.hpp> + #include "llpanel.h" #include "lloutputmonitorctrl.h" #include "llbutton.h" @@ -217,6 +219,9 @@ private: /// true when the mouse pointer is hovering over this item bool mHovered; + + void fetchAvatarName(); + boost::signals2::connection mAvatarNameCacheConnection; static bool sStaticInitialized; // this variable is introduced to improve code readability static S32 sLeftPadding; // padding to first left visible child (icon or name) diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index c61a8c8562..605e3ece51 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -28,6 +28,8 @@ #include "llchathistory.h" +#include <boost/signals2.hpp> + #include "llavatarnamecache.h" #include "llinstantmessage.h" @@ -110,7 +112,8 @@ public: mFrom(), mSessionID(), mMinUserNameWidth(0), - mUserNameFont(NULL) + mUserNameFont(NULL), + mAvatarNameCacheConnection() {} static LLChatHistoryHeader* createInstance(const std::string& file_name) @@ -124,6 +127,11 @@ public: { // Detach the info button so that it doesn't get destroyed (EXT-8463). hideInfoCtrl(); + + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } } BOOL handleMouseUp(S32 x, S32 y, MASK mask) @@ -283,8 +291,7 @@ public: // Start with blank so sample data from XUI XML doesn't // flash on the screen user_name->setValue( LLSD() ); - LLAvatarNameCache::get(mAvatarID, - boost::bind(&LLChatHistoryHeader::onAvatarNameCache, this, _1, _2)); + fetchAvatarName(); } else if (chat.mChatStyle == CHAT_STYLE_HISTORY || mSourceType == CHAT_SOURCE_AGENT) @@ -416,31 +423,6 @@ public: } } - void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) - { - mFrom = av_name.mDisplayName; - - LLTextBox* user_name = getChild<LLTextBox>("user_name"); - user_name->setValue( LLSD(av_name.mDisplayName ) ); - user_name->setToolTip( av_name.mUsername ); - - if (gSavedSettings.getBOOL("NameTagShowUsernames") && - LLAvatarNameCache::useDisplayNames() && - !av_name.mIsDisplayNameDefault) - { - LLStyle::Params style_params_name; - LLColor4 userNameColor = LLUIColorTable::instance().getColor("EmphasisColor"); - style_params_name.color(userNameColor); - style_params_name.font.name("SansSerifSmall"); - style_params_name.font.style("NORMAL"); - style_params_name.readonly_color(userNameColor); - user_name->appendText(" - " + av_name.mUsername, FALSE, style_params_name); - } - setToolTip( av_name.mUsername ); - // name might have changed, update width - updateMinUserNameWidth(); - } - protected: static const S32 PADDING = 20; @@ -555,6 +537,45 @@ private: user_name->reshape(user_rect.getWidth() + delta_pos_x, user_rect.getHeight()); } + void fetchAvatarName() + { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + + if (mAvatarID.notNull()) + { + mAvatarNameCacheConnection = LLAvatarNameCache::get(mAvatarID, + boost::bind(&LLChatHistoryHeader::onAvatarNameCache, this, _1, _2)); + } + } + + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) + { + mFrom = av_name.mDisplayName; + + LLTextBox* user_name = getChild<LLTextBox>("user_name"); + user_name->setValue( LLSD(av_name.mDisplayName ) ); + user_name->setToolTip( av_name.mUsername ); + + if (gSavedSettings.getBOOL("NameTagShowUsernames") && + LLAvatarNameCache::useDisplayNames() && + !av_name.mIsDisplayNameDefault) + { + LLStyle::Params style_params_name; + LLColor4 userNameColor = LLUIColorTable::instance().getColor("EmphasisColor"); + style_params_name.color(userNameColor); + style_params_name.font.name("SansSerifSmall"); + style_params_name.font.style("NORMAL"); + style_params_name.readonly_color(userNameColor); + user_name->appendText(" - " + av_name.mUsername, FALSE, style_params_name); + } + setToolTip( av_name.mUsername ); + // name might have changed, update width + updateMinUserNameWidth(); + } + protected: LLHandle<LLView> mPopupMenuHandleAvatar; LLHandle<LLView> mPopupMenuHandleObject; @@ -569,6 +590,9 @@ protected: S32 mMinUserNameWidth; const LLFontGL* mUserNameFont; + +private: + boost::signals2::connection mAvatarNameCacheConnection; }; LLUICtrl* LLChatHistoryHeader::sInfoCtrl = NULL; -- cgit v1.2.3 From 4f6afb08d7f4c5ae721bd343999715bc22dfca8b Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 2 Nov 2012 16:22:19 -0700 Subject: CHUI-472: This is a fix for the following case: When a torn off floater has its conversation reduced to the minimum width, once re-docked the conversation does not expand. Solution: Discussed problem with Richard, and I'm submitting the changes required to fix the problem. --- indra/llui/lllayoutstack.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 1f2496a8e7..260f0bc92e 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -36,7 +36,7 @@ #include "llcriticaldamp.h" #include "boost/foreach.hpp" -static const F32 MIN_FRACTIONAL_SIZE = 0.0f; +static const F32 MIN_FRACTIONAL_SIZE = 0.00001f; static const F32 MAX_FRACTIONAL_SIZE = 1.f; static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack"); @@ -71,7 +71,7 @@ LLLayoutPanel::LLLayoutPanel(const Params& p) mCollapseAmt(0.f), mVisibleAmt(1.f), // default to fully visible mResizeBar(NULL), - mFractionalSize(MIN_FRACTIONAL_SIZE), + mFractionalSize(0.f), mTargetDim(0), mIgnoreReshape(false), mOrientation(LLLayoutStack::HORIZONTAL) @@ -521,7 +521,7 @@ void LLLayoutStack::updateFractionalSizes() { if (panelp->mAutoResize) { - total_resizable_dim += llmax(0, panelp->getLayoutDim() - panelp->getRelevantMinDim()); + total_resizable_dim += llmax(MIN_FRACTIONAL_SIZE, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim())); } } @@ -767,7 +767,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& { // freeze new size as fraction F32 new_fractional_size = (updated_auto_resize_headroom == 0.f) ? MAX_FRACTIONAL_SIZE - : llclamp(total_visible_fraction * (F32)(new_dim - (panelp->getRelevantMinDim() - 1)) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); + : llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); fraction_given_up -= new_fractional_size - panelp->mFractionalSize; fraction_remaining -= panelp->mFractionalSize; panelp->mFractionalSize = new_fractional_size; -- cgit v1.2.3 From 7e74481f33d19f24bb596bab75298a720068a716 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 2 Nov 2012 18:00:19 -0700 Subject: This does not pertain to a CHUI bug fix but Richard took a look at the behavior of the layout stack test and found a mathematical bug that caused panels in a layout stack to jitter as they were resized. Submitting in this branch. --- indra/llui/lllayoutstack.cpp | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 260f0bc92e..0674275612 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -672,12 +672,12 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& S32 new_dim = (mOrientation == HORIZONTAL) ? new_rect.getWidth() : new_rect.getHeight(); - S32 delta_dim = new_dim - resized_panel->getVisibleDim(); - if (delta_dim == 0) return; + S32 delta_panel_dim = new_dim - resized_panel->getVisibleDim(); + if (delta_panel_dim == 0) return; F32 total_visible_fraction = 0.f; F32 delta_auto_resize_headroom = 0.f; - F32 original_auto_resize_headroom = 0.f; + F32 old_auto_resize_headroom = 0.f; LLLayoutPanel* other_resize_panel = NULL; LLLayoutPanel* following_panel = NULL; @@ -686,7 +686,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& { if (panelp->mAutoResize) { - original_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim()); + old_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim()); if (panelp->getVisible() && !panelp->mCollapsed) { total_visible_fraction += panelp->mFractionalSize; @@ -704,25 +704,24 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& } } - if (resized_panel->mAutoResize) { if (!other_resize_panel || !other_resize_panel->mAutoResize) { - delta_auto_resize_headroom += delta_dim; + delta_auto_resize_headroom += delta_panel_dim; } } else { if (!other_resize_panel || other_resize_panel->mAutoResize) { - delta_auto_resize_headroom -= delta_dim; + delta_auto_resize_headroom -= delta_panel_dim; } } F32 fraction_given_up = 0.f; F32 fraction_remaining = 1.f; - F32 updated_auto_resize_headroom = original_auto_resize_headroom + delta_auto_resize_headroom; + F32 new_auto_resize_headroom = old_auto_resize_headroom + delta_auto_resize_headroom; enum { @@ -734,7 +733,14 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) { - if (!panelp->getVisible() || panelp->mCollapsed) continue; + if (!panelp->getVisible() || panelp->mCollapsed) + { + if (panelp->mAutoResize) + { + fraction_remaining -= panelp->mFractionalSize; + } + continue; + } if (panelp == resized_panel) { @@ -746,9 +752,9 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& case BEFORE_RESIZED_PANEL: if (panelp->mAutoResize) { // freeze current size as fraction of overall auto_resize space - F32 fractional_adjustment_factor = updated_auto_resize_headroom == 0.f + F32 fractional_adjustment_factor = new_auto_resize_headroom == 0.f ? 1.f - : original_auto_resize_headroom / updated_auto_resize_headroom; + : old_auto_resize_headroom / new_auto_resize_headroom; F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); @@ -765,9 +771,9 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& case RESIZED_PANEL: if (panelp->mAutoResize) { // freeze new size as fraction - F32 new_fractional_size = (updated_auto_resize_headroom == 0.f) + F32 new_fractional_size = (new_auto_resize_headroom == 0.f) ? MAX_FRACTIONAL_SIZE - : llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); + : llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim()) / new_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); fraction_given_up -= new_fractional_size - panelp->mFractionalSize; fraction_remaining -= panelp->mFractionalSize; panelp->mFractionalSize = new_fractional_size; @@ -791,7 +797,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& else { F32 new_fractional_size = llclamp(total_visible_fraction * (F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom) - / updated_auto_resize_headroom, + / new_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); fraction_given_up -= new_fractional_size - panelp->mFractionalSize; @@ -800,7 +806,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& } else { - panelp->mTargetDim -= delta_dim; + panelp->mTargetDim -= delta_panel_dim; } which_panel = AFTER_RESIZED_PANEL; break; @@ -816,7 +822,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& } } updateLayout(); - normalizeFractionalSizes(); + //normalizeFractionalSizes(); } void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent) -- cgit v1.2.3 From 4da02c26e10fe59dfde762cdb3c0d20be7f6ebde Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 2 Nov 2012 19:36:46 -0700 Subject: CHUI-481, CHUI-404, CHUI-405, CHUI-406, CHUI-407, CHUI-408 : Fixed! Change the way Ad-hoc and P2P chats update their session name in a way which is consistent and honor display name. --- indra/newview/llimconversation.cpp | 60 ++++++++++++++++++-------------------- indra/newview/llimfloater.cpp | 22 ++------------ indra/newview/llimfloater.h | 3 -- 3 files changed, 31 insertions(+), 54 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index a6a246a01e..6272c75ccf 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -29,6 +29,8 @@ #include "llimconversation.h" +#include "llagent.h" +#include "llavataractions.h" #include "llchatentry.h" #include "llchathistory.h" #include "llchiclet.h" @@ -370,50 +372,47 @@ void LLIMConversation::updateConversationViewParticipant(const LLUUID& participa if (widget) { widget->refresh(); - refreshConversation(); } + refreshConversation(); } void LLIMConversation::refreshConversation() { - // Debug : Check that all participant models do have a view (debug consistency check) - /* - LLParticipantList* item = getParticipantList(); - llinfos << "Merov debug : Start consistency check" << llendl; - LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); - LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); - while (current_participant_model != end_participant_model) + // Note: We collect participants names to change the session name only in the case of ad-hoc conversations + bool is_ad_hoc = (mSession ? mSession->isAdHocSessionType() : false); + uuid_vec_t participants_uuids; // uuids vector for building the added participants name string + // For P2P chat, we still need to update the session name who may have changed (switch display name for instance) + if (mIsP2PChat && mSession) { - LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); - if (participant_model != NULL) - { - LLUUID uuid = participant_model->getUUID(); - LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); - if (!widget) - { - llinfos << "Merov debug : Consistency error! Couldn't find widget for " << participant_model->getName() << llendl; - } - else - { - llinfos << "Merov debug : Consistency check pass for " << participant_model->getName() << llendl; - } - } - else - { - llinfos << "Merov debug : Consistency check, skip non participant child" << llendl; - } - current_participant_model++; + participants_uuids.push_back(mSession->mOtherParticipantID); } - llinfos << "Merov debug : End consistency check" << llendl; - */ - + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); while (widget_it != mConversationsWidgets.end()) { + // Add the participant to the list except if it's the agent itself (redundant) + if (is_ad_hoc && (widget_it->first != gAgentID)) + { + participants_uuids.push_back(widget_it->first); + } widget_it->second->refresh(); widget_it->second->setVisible(TRUE); ++widget_it; } + if (is_ad_hoc || mIsP2PChat) + { + // Build the session name and update it + std::string session_name; + if (participants_uuids.size() != 0) + { + LLAvatarActions::buildResidentsString(participants_uuids, session_name); + } + else + { + session_name = LLIMModel::instance().getName(mSessionID); + } + updateSessionName(session_name); + } mConversationViewModel.requestSortAll(); mConversationsRoot->arrangeAll(); mConversationsRoot->update(); @@ -510,7 +509,6 @@ void LLIMConversation::hideOrShowTitle() void LLIMConversation::updateSessionName(const std::string& name) { - llinfos << "Merov debug : updateSessionName, name = " << name << llendl; mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + name); } diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 4e1bfb4e77..75be0a7edc 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -270,14 +270,7 @@ void LLIMFloater::initIMFloater() mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label")); } - if (mIsP2PChat) - { - // look up display name for window title - LLAvatarNameCache::get(mSession->mOtherParticipantID, - boost::bind(&LLIMFloater::onAvatarNameCache, - this, _1, _2)); - } - else + if (!mIsP2PChat) { std::string session_name(LLIMModel::instance().getName(mSessionID)); updateSessionName(session_name); @@ -530,18 +523,7 @@ void LLIMFloater::updateSessionName(const std::string& name) { LLIMConversation::updateSessionName(name); setTitle(name); -} - -void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id, - const LLAvatarName& av_name) -{ - // Use display name for label - updateSessionName(av_name.mDisplayName); - - // Overwrite the floater title with the extended name - std::string ui_title = av_name.getCompleteName(); - setTitle(ui_title); - mTypingStart.setArg("[NAME]", ui_title); + mTypingStart.setArg("[NAME]", name); } void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index ec3a96f694..bac21c27f0 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -142,9 +142,6 @@ private: // Update the window title and input field help text /*virtual*/ void updateSessionName(const std::string& name); - // For display name lookups for IM window titles - void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); - /// Updates the list of ad hoc conference participants /// in an IM floater title. void onParticipantsListChanged(LLUICtrl* ctrl); -- cgit v1.2.3 From 6220ce33700d011be5831b1bb480c81dec98665e Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Mon, 5 Nov 2012 15:18:53 +0200 Subject: CHUI-450 (Your own name does not appear in nearby chat participant list if voice chat disabled) --- indra/newview/llvoicevivox.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index f1bf4a6d75..f236123ef1 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -394,7 +394,15 @@ const LLVoiceVersionInfo& LLVivoxVoiceClient::getVersion() void LLVivoxVoiceClient::updateSettings() { - setVoiceEnabled(gSavedSettings.getBOOL("EnableVoiceChat")); + if(!mAudioSession) + { + // If audio module is not initialized, pretend that voice is enabled, thus letting state machine to take a full cycle + setVoiceEnabled(true); + } + else + { + setVoiceEnabled(gSavedSettings.getBOOL("EnableVoiceChat")); + } setEarLocation(gSavedSettings.getS32("VoiceEarLocation")); std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice"); @@ -1478,6 +1486,9 @@ void LLVivoxVoiceClient::stateMachine() mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS); sendPositionalUpdate(); } + + // Now that audio module is fully initialized, check for actual mVoiceEnabled value + updateSettings(); } break; -- cgit v1.2.3 From 622a697788e3cabb9e803226de72856e9189911f Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Tue, 6 Nov 2012 14:47:01 +0200 Subject: CHUI-460 FIXED Reselect current conversation on clicking expand/collapse button --- indra/newview/llimfloatercontainer.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index f85aa9a353..52deae445b 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -331,6 +331,7 @@ void LLIMFloaterContainer::onExpandCollapseButtonClicked() { collapseConversationsPane(!mConversationsPane->isCollapsed()); } + selectConversation(mSelectedSession); } LLIMFloaterContainer* LLIMFloaterContainer::findInstance() -- cgit v1.2.3 From 741fdfd3e6e6c5556c5bac7ec9cb5bed13975dda Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Tue, 6 Nov 2012 14:53:42 +0200 Subject: CHUI-502 FIXED deleted registering Call floater from FloaterReg --- indra/newview/llviewerfloaterreg.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index c751550523..a4d45e1fb8 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -322,7 +322,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("upload_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptPreview>, "upload"); LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload"); - LLFloaterReg::add("voice_controls", "floater_voice_controls.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLCallFloater>); LLFloaterReg::add("voice_effect", "floater_voice_effect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceEffect>); LLFloaterReg::add("web_content", "floater_web_content.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create); -- cgit v1.2.3 From 0a21efc7abc62511d1ea789bdb47309a6ed1d72e Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Mon, 5 Nov 2012 17:52:04 +0200 Subject: CHUI-374 FIXED Nearby chat is torn off and cannot be docked if nearby chat is received while conversation floater is closed --- indra/newview/llimconversation.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index b687e18cae..833feff3c4 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -54,6 +54,7 @@ LLIMConversation::LLIMConversation(const LLSD& session_id) , mInputEditor(NULL) , mInputEditorTopPad(0) , mRefreshTimer(new LLTimer()) + , mIsHostAttached(false) { mSession = LLIMModel::getInstance()->findIMSession(mSessionID); -- cgit v1.2.3 From 8d6aaf8e8e7c2d0f68bf79100f163803cbdd02bc Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 5 Nov 2012 13:47:49 -0800 Subject: CHUI-468 : Suppress LLIMFloater::onParticipantsListChanged(). Not useful anymore. --- indra/newview/llimfloater.cpp | 68 ------------------------------------------- indra/newview/llimfloater.h | 6 ---- 2 files changed, 74 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 8742460689..d9c201d856 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -220,7 +220,6 @@ void LLIMFloater::sendMsg(const std::string& msg) LLIMFloater::~LLIMFloater() { - mParticipantsListRefreshConnection.disconnect(); mVoiceChannelStateChangeConnection.disconnect(); if(LLVoiceClient::instanceExists()) { @@ -274,22 +273,6 @@ void LLIMFloater::initIMFloater() { std::string session_name(LLIMModel::instance().getName(mSessionID)); updateSessionName(session_name); - - // For ad hoc conferences we should update the title with participants names. - if ((IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) - || mDialog == IM_SESSION_CONFERENCE_START) - { - if (mParticipantsListRefreshConnection.connected()) - { - mParticipantsListRefreshConnection.disconnect(); - } - - // CHUI-441: We shouldn't have any avatar_list anymore... see floater_im_session.xml - // *TODO: Track and delete if not necessary anymore - LLAvatarList* avatar_list = getChild<LLAvatarList>("speakers_list"); - mParticipantsListRefreshConnection = avatar_list->setRefreshCompleteCallback( - boost::bind(&LLIMFloater::onParticipantsListChanged, this, _1)); - } } } @@ -526,57 +509,6 @@ void LLIMFloater::updateSessionName(const std::string& name) mTypingStart.setArg("[NAME]", name); } -void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) -{ - LLAvatarList* avatar_list = dynamic_cast<LLAvatarList*>(ctrl); - if (!avatar_list) - { - return; - } - - std::vector<LLSD> participants_uuids; - uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string - LLUUID unfound_id; - - avatar_list->getValues(participants_uuids); - - // Check participants names in LLAvatarNameCache - for (std::vector<LLSD>::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it) - { - const LLUUID& id = it->asUUID(); - LLAvatarName av_name; - if (!LLAvatarNameCache::get(id, &av_name)) - { - // Keep the first not found avatar id - if (unfound_id.isNull()) - { - unfound_id = id; - } - } - else - { - // Add the participant to the list of existing names - temp_uuids.push_back(id); - } - } - - if (temp_uuids.size() != 0) - { - // Build the session name and update it - std::string ui_title; - LLAvatarActions::buildResidentsString(temp_uuids, ui_title); - updateSessionName(ui_title); - } - - if (unfound_id.notNull()) - { - // If a name is not found in cache, request it and continue the process recursively - // until all ids are resolved into names. - LLAvatarNameCache::get(unfound_id, boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list)); - } -} - - //static LLIMFloater* LLIMFloater::show(const LLUUID& session_id) { diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index dba3a4bcbd..8a0a163678 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -141,10 +141,6 @@ private: // Update the window title and input field help text /*virtual*/ void updateSessionName(const std::string& name); - /// Updates the list of ad hoc conference participants - /// in an IM floater title. - void onParticipantsListChanged(LLUICtrl* ctrl); - bool dropPerson(LLUUID* person_id, bool drop); BOOL isInviteAllowed() const; @@ -196,8 +192,6 @@ private: // connection to voice channel state change signal boost::signals2::connection mVoiceChannelStateChangeConnection; - - boost::signals2::connection mParticipantsListRefreshConnection; }; #endif // LL_IMFLOATER_H -- cgit v1.2.3 From e3524a5fe159566edefb0bbc395e94ee3126adec Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 5 Nov 2012 15:53:31 -0800 Subject: CHUI-468 : Suppress LLCallFloater completely --- indra/newview/CMakeLists.txt | 2 - indra/newview/llappviewer.cpp | 1 - indra/newview/llcallfloater.cpp | 822 --------------------- indra/newview/llcallfloater.h | 275 ------- indra/newview/llviewerfloaterreg.cpp | 2 - indra/newview/llvoicevivox.cpp | 3 +- .../default/xui/en/floater_voice_controls.xml | 155 ---- 7 files changed, 1 insertion(+), 1259 deletions(-) delete mode 100644 indra/newview/llcallfloater.cpp delete mode 100644 indra/newview/llcallfloater.h delete mode 100644 indra/newview/skins/default/xui/en/floater_voice_controls.xml (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c6ba8a22bd..2c7e96f1e4 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -117,7 +117,6 @@ set(viewer_SOURCE_FILES llbrowsernotification.cpp llbuycurrencyhtml.cpp llcallbacklist.cpp - llcallfloater.cpp llcallingcard.cpp llcapabilitylistener.cpp llcaphttpsender.cpp @@ -701,7 +700,6 @@ set(viewer_HEADER_FILES llbreadcrumbview.h llbuycurrencyhtml.h llcallbacklist.h - llcallfloater.h llcallingcard.h llcapabilitylistener.h llcapabilityprovider.h diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index d6c781020d..b23e5866dc 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -95,7 +95,6 @@ #include "llweb.h" #include "llsecondlifeurls.h" #include "llupdaterservice.h" -#include "llcallfloater.h" #include "llfloatertexturefetchdebugger.h" #include "llspellcheck.h" diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp deleted file mode 100644 index e767609d74..0000000000 --- a/indra/newview/llcallfloater.cpp +++ /dev/null @@ -1,822 +0,0 @@ -/** - * @file llcallfloater.cpp - * @author Mike Antipov - * @brief Voice Control Panel in a Voice Chats (P2P, Group, Nearby...). - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llcallfloater.h" - -#include "llnotificationsutil.h" -#include "lltrans.h" - -#include "llagent.h" -#include "llagentdata.h" // for gAgentID -#include "llavatarnamecache.h" -#include "llavatariconctrl.h" -#include "llavatarlist.h" -#include "lldraghandle.h" -#include "llimfloater.h" -#include "llimview.h" -#include "llfloaterreg.h" -#include "llparticipantlist.h" -#include "llspeakers.h" -#include "lltextutil.h" -#include "lltransientfloatermgr.h" -#include "llviewercontrol.h" -#include "llviewerdisplayname.h" -#include "llviewerwindow.h" -#include "llvoicechannel.h" -#include "llviewerparcelmgr.h" -#include "llfirstuse.h" - -static void get_voice_participants_uuids(uuid_vec_t& speakers_uuids); -void reshape_floater(LLCallFloater* floater, S32 delta_height); - -class LLNonAvatarCaller : public LLAvatarListItem -{ -public: - LLNonAvatarCaller() : LLAvatarListItem(false) - { - - } - BOOL postBuild() - { - BOOL rv = LLAvatarListItem::postBuild(); - - if (rv) - { - setOnline(true); - showLastInteractionTime(false); - setShowProfileBtn(false); - setShowInfoBtn(false); - mAvatarIcon->setValue("Avaline_Icon"); - mAvatarIcon->setToolTip(std::string("")); - } - return rv; - } - - void setName(const std::string& name) - { - const std::string& formatted_phone = LLTextUtil::formatPhoneNumber(name); - LLAvatarListItem::setAvatarName(formatted_phone); - LLAvatarListItem::setAvatarToolTip(formatted_phone); - } - - void setSpeakerId(const LLUUID& id) { mSpeakingIndicator->setSpeakerId(id); } -}; - - -static void* create_non_avatar_caller(void*) -{ - return new LLNonAvatarCaller; -} - -LLVoiceChannel* LLCallFloater::sCurrentVoiceChannel = NULL; - -LLCallFloater::LLCallFloater(const LLSD& key) -: LLTransientDockableFloater(NULL, false, key) -, mSpeakerManager(NULL) -, mParticipants(NULL) -, mAvatarList(NULL) -, mNonAvatarCaller(NULL) -, mVoiceType(VC_LOCAL_CHAT) -, mAgentPanel(NULL) -, mSpeakingIndicator(NULL) -, mIsModeratorMutedVoice(false) -, mInitParticipantsVoiceState(false) -{ - static LLUICachedControl<S32> voice_left_remove_delay ("VoiceParticipantLeftRemoveDelay", 10); - mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), voice_left_remove_delay); - - mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL); - LLVoiceClient::instance().addObserver(this); - LLTransientFloaterMgr::getInstance()->addControlView(this); - - // update the agent's name if display name setting change - LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLCallFloater::updateAgentModeratorState, this)); - LLViewerDisplayName::addNameChangedCallback(boost::bind(&LLCallFloater::updateAgentModeratorState, this)); - -} - -LLCallFloater::~LLCallFloater() -{ - resetVoiceRemoveTimers(); - delete mSpeakerDelayRemover; - - delete mParticipants; - mParticipants = NULL; - - mAvatarListRefreshConnection.disconnect(); - mVoiceChannelStateChangeConnection.disconnect(); - - if(LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->removeObserver(this); - } - LLTransientFloaterMgr::getInstance()->removeControlView(this); -} - -// virtual -BOOL LLCallFloater::postBuild() -{ - mAvatarList = getChild<LLAvatarList>("speakers_list"); - mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLCallFloater::onAvatarListRefreshed, this)); - - childSetAction("leave_call_btn", boost::bind(&LLCallFloater::leaveCall, this)); - - mNonAvatarCaller = findChild<LLNonAvatarCaller>("non_avatar_caller"); - mNonAvatarCaller->setVisible(FALSE); - - initAgentData(); - - connectToChannel(LLVoiceChannel::getCurrentVoiceChannel()); - - updateTransparency(TT_ACTIVE); // force using active floater transparency (STORM-730) - - updateSession(); - return TRUE; -} - -// virtual -void LLCallFloater::onOpen(const LLSD& /*key*/) -{ - LLFirstUse::speak(false); -} - -// virtual -void LLCallFloater::draw() -{ - // we have to refresh participants to display ones not in voice as disabled. - // It should be done only when she joins or leaves voice chat. - // But seems that LLVoiceClientParticipantObserver is not enough to satisfy this requirement. - // *TODO: mantipov: remove from draw() - - // NOTE: it looks like calling onChange() here is not necessary, - // but sometime it is not called properly from the observable object. - // Seems this is a problem somewhere in Voice Client (LLVoiceClient::participantAddedEvent) -// onChange(); - - bool is_moderator_muted = LLVoiceClient::getInstance()->getIsModeratorMuted(gAgentID); - - if (mIsModeratorMutedVoice != is_moderator_muted) - { - setModeratorMutedVoice(is_moderator_muted); - } - - // Need to resort the participant list if it's in sort by recent speaker order. - if (mParticipants) - mParticipants->update(); - - LLFloater::draw(); -} - -// virtual -void LLCallFloater::setFocus( BOOL b ) -{ - LLFloater::setFocus(b); - - // Force using active floater transparency (STORM-730). - // We have to override setFocus() for LLCallFloater because selecting an item - // of the voice morphing combobox causes the floater to lose focus and thus become transparent. - updateTransparency(TT_ACTIVE); -} - -// virtual -void LLCallFloater::onParticipantsChanged() -{ - if (NULL == mParticipants) return; - updateParticipantsVoiceState(); - - // Add newly joined participants. - uuid_vec_t speakers_uuids; - get_voice_participants_uuids(speakers_uuids); - for (uuid_vec_t::const_iterator it = speakers_uuids.begin(); it != speakers_uuids.end(); it++) - { - mParticipants->addAvatarIDExceptAgent(*it); - } -} - -////////////////////////////////////////////////////////////////////////// -/// PRIVATE SECTION -////////////////////////////////////////////////////////////////////////// - -void LLCallFloater::leaveCall() -{ - LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); - if (voice_channel) - { - gIMMgr->endCall(voice_channel->getSessionID()); - } -} - -void LLCallFloater::updateSession() -{ - LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); - if (voice_channel) - { - LL_DEBUGS("Voice") << "Current voice channel: " << voice_channel->getSessionID() << LL_ENDL; - - if (mSpeakerManager && voice_channel->getSessionID() == mSpeakerManager->getSessionID()) - { - LL_DEBUGS("Voice") << "Speaker manager is already set for session: " << voice_channel->getSessionID() << LL_ENDL; - return; - } - else - { - mSpeakerManager = NULL; - } - } - - const LLUUID& session_id = voice_channel ? voice_channel->getSessionID() : LLUUID::null; - - LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id); - if (im_session) - { - mSpeakerManager = LLIMModel::getInstance()->getSpeakerManager(session_id); - switch (im_session->mType) - { - case IM_NOTHING_SPECIAL: - case IM_SESSION_P2P_INVITE: - mVoiceType = VC_PEER_TO_PEER; - - if (!im_session->mOtherParticipantIsAvatar) - { - mVoiceType = VC_PEER_TO_PEER_AVALINE; - } - break; - case IM_SESSION_CONFERENCE_START: - case IM_SESSION_GROUP_START: - case IM_SESSION_INVITE: - if (gAgent.isInGroup(session_id)) - { - mVoiceType = VC_GROUP_CHAT; - } - else - { - mVoiceType = VC_AD_HOC_CHAT; - } - break; - default: - llwarning("Failed to determine voice call IM type", 0); - mVoiceType = VC_GROUP_CHAT; - break; - } - } - - if (NULL == mSpeakerManager) - { - // By default show nearby chat participants - mSpeakerManager = LLLocalSpeakerMgr::getInstance(); - LL_DEBUGS("Voice") << "Set DEFAULT speaker manager" << LL_ENDL; - mVoiceType = VC_LOCAL_CHAT; - } - - updateTitle(); - - // Hide "Leave Call" button for nearby chat - bool is_local_chat = mVoiceType == VC_LOCAL_CHAT; - getChildView("leave_call_btn_panel")->setVisible( !is_local_chat); - - refreshParticipantList(); - updateAgentModeratorState(); - - // Show floater for voice calls & only in CONNECTED to voice channel state - if (!is_local_chat && - voice_channel && - LLVoiceChannel::STATE_CONNECTED == voice_channel->getState()) - { - LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); - bool show_me = !(im_floater && im_floater->getVisible()); - if (show_me) - { - setVisible(true); - } - } -} - -void LLCallFloater::refreshParticipantList() -{ - bool non_avatar_caller = VC_PEER_TO_PEER_AVALINE == mVoiceType; - - if (non_avatar_caller) - { - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSpeakerManager->getSessionID()); - mNonAvatarCaller->setSpeakerId(session->mOtherParticipantID); - mNonAvatarCaller->setName(session->mName); - } - - mNonAvatarCaller->setVisible(non_avatar_caller); - mAvatarList->setVisible(!non_avatar_caller); - - if (!non_avatar_caller) - { - llassert(mParticipants == NULL); // check for possible memory leak - mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, mConversationViewModel, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT, false); - mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1)); - const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder"); - mParticipants->setSortOrder(LLParticipantList::EParticipantSortOrder(speaker_sort_order)); - - if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager) - { - mAvatarList->setNoItemsCommentText(getString("no_one_near")); - } - - // we have to made delayed initialization of voice state of participant list. - // it will be performed after first LLAvatarList refreshing in the onAvatarListRefreshed(). - mInitParticipantsVoiceState = true; - } -} - -void LLCallFloater::onAvatarListRefreshed() -{ - if (mInitParticipantsVoiceState) - { - initParticipantsVoiceState(); - mInitParticipantsVoiceState = false; - } - else - { - updateParticipantsVoiceState(); - } -} - -// static -// This entry point now disable, but left for later use. -void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/) -{ - LLVoiceChannel* channel = LLVoiceChannel::getCurrentVoiceChannel(); - - // *NOTE: if signal was sent for voice channel with LLVoiceChannel::STATE_NO_CHANNEL_INFO - // it sill be sent for the same channel again (when state is changed). - // So, lets ignore this call. - if (channel == sCurrentVoiceChannel) return; - - LLCallFloater* call_floater = LLFloaterReg::getTypedInstance<LLCallFloater>("voice_controls"); - - call_floater->connectToChannel(channel); -} - -void LLCallFloater::onAvatarNameCache(const LLUUID& agent_id, - const LLAvatarName& av_name) -{ - LLStringUtil::format_map_t args; - args["[NAME]"] = av_name.getCompleteName(); - std::string title = getString("title_peer_2_peer", args); - setTitle(title); -} - -void LLCallFloater::updateTitle() -{ - LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); - if (mVoiceType == VC_PEER_TO_PEER) - { - LLUUID session_id = voice_channel->getSessionID(); - LLIMModel::LLIMSession* im_session = - LLIMModel::getInstance()->findIMSession(session_id); - if (im_session) - { - LLAvatarNameCache::get(im_session->mOtherParticipantID, - boost::bind(&LLCallFloater::onAvatarNameCache, - this, _1, _2)); - return; - } - } - std::string title; - switch (mVoiceType) - { - case VC_LOCAL_CHAT: - title = getString("title_nearby"); - break; - case VC_PEER_TO_PEER: - case VC_PEER_TO_PEER_AVALINE: - { - title = voice_channel->getSessionName(); - - if (VC_PEER_TO_PEER_AVALINE == mVoiceType) - { - title = LLTextUtil::formatPhoneNumber(title); - } - - LLStringUtil::format_map_t args; - args["[NAME]"] = title; - title = getString("title_peer_2_peer", args); - } - break; - case VC_AD_HOC_CHAT: - title = getString("title_adhoc"); - break; - case VC_GROUP_CHAT: - { - LLStringUtil::format_map_t args; - args["[GROUP]"] = voice_channel->getSessionName(); - title = getString("title_group", args); - } - break; - } - - setTitle(title); -} - -void LLCallFloater::initAgentData() -{ - mAgentPanel = getChild<LLPanel> ("my_panel"); - - if ( mAgentPanel ) - { - mAgentPanel->getChild<LLUICtrl>("user_icon")->setValue(gAgentID); - - // Just use display name, because it's you - LLAvatarName av_name; - LLAvatarNameCache::get( gAgentID, &av_name ); - mAgentPanel->getChild<LLUICtrl>("user_text")->setValue(av_name.mDisplayName); - - mSpeakingIndicator = mAgentPanel->getChild<LLOutputMonitorCtrl>("speaking_indicator"); - mSpeakingIndicator->setSpeakerId(gAgentID); - } -} - -void LLCallFloater::setModeratorMutedVoice(bool moderator_muted) -{ - mIsModeratorMutedVoice = moderator_muted; - - if (moderator_muted) - { - LLNotificationsUtil::add("VoiceIsMutedByModerator"); - } - mSpeakingIndicator->setIsMuted(moderator_muted); -} - -void LLCallFloater::onModeratorNameCache(const LLAvatarName& av_name) -{ - std::string name; - name = av_name.mDisplayName; - - if(mSpeakerManager && gAgent.isInGroup(mSpeakerManager->getSessionID())) - { - // This method can be called when LLVoiceChannel.mState == STATE_NO_CHANNEL_INFO - // in this case there are not any speakers yet. - if (mSpeakerManager->findSpeaker(gAgentID)) - { - // Agent is Moderator - if (mSpeakerManager->findSpeaker(gAgentID)->mIsModerator) - - { - const std::string moderator_indicator(LLTrans::getString("IM_moderator_label")); - name += " " + moderator_indicator; - } - } - } - mAgentPanel->getChild<LLUICtrl>("user_text")->setValue(name); -} - -void LLCallFloater::updateAgentModeratorState() -{ - LLAvatarNameCache::get(gAgentID, boost::bind(&LLCallFloater::onModeratorNameCache, this, _2)); -} - -static void get_voice_participants_uuids(uuid_vec_t& speakers_uuids) -{ - // Get a list of participants from VoiceClient - std::set<LLUUID> participants; - LLVoiceClient::getInstance()->getParticipantList(participants); - - for (std::set<LLUUID>::const_iterator iter = participants.begin(); - iter != participants.end(); ++iter) - { - speakers_uuids.push_back(*iter); - } - -} - -void LLCallFloater::initParticipantsVoiceState() -{ - // Set initial status for each participant in the list. - std::vector<LLPanel*> items; - mAvatarList->getItems(items); - std::vector<LLPanel*>::const_iterator - it = items.begin(), - it_end = items.end(); - - - uuid_vec_t speakers_uuids; - get_voice_participants_uuids(speakers_uuids); - - for(; it != it_end; ++it) - { - LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it); - - if (!item) continue; - - LLUUID speaker_id = item->getAvatarId(); - - uuid_vec_t::const_iterator speaker_iter = std::find(speakers_uuids.begin(), speakers_uuids.end(), speaker_id); - - // If an avatarID assigned to a panel is found in a speakers list - // obtained from VoiceClient we assign the JOINED status to the owner - // of this avatarID. - if (speaker_iter != speakers_uuids.end()) - { - setState(item, STATE_JOINED); - } - else - { - LLPointer<LLSpeaker> speakerp = mSpeakerManager->findSpeaker(speaker_id); - // If someone has already left the call before, we create his - // avatar row panel with HAS_LEFT status and remove it after - // the timeout, otherwise we create a panel with INVITED status - if (speakerp.notNull() && speakerp.get()->mHasLeftCurrentCall) - { - setState(item, STATE_LEFT); - } - else - { - setState(item, STATE_INVITED); - } - } - } -} - -void LLCallFloater::updateParticipantsVoiceState() -{ - uuid_vec_t speakers_list; - - // Get a list of participants from VoiceClient - uuid_vec_t speakers_uuids; - get_voice_participants_uuids(speakers_uuids); - - // Updating the status for each participant already in list. - std::vector<LLPanel*> items; - mAvatarList->getItems(items); - std::vector<LLPanel*>::const_iterator - it = items.begin(), - it_end = items.end(); - - for(; it != it_end; ++it) - { - LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it); - if (!item) continue; - - const LLUUID participant_id = item->getAvatarId(); - bool found = false; - - uuid_vec_t::iterator speakers_iter = std::find(speakers_uuids.begin(), speakers_uuids.end(), participant_id); - - LL_DEBUGS("Voice") << "processing speaker: " << item->getAvatarName() << ", " << item->getAvatarId() << LL_ENDL; - - // If an avatarID assigned to a panel is found in a speakers list - // obtained from VoiceClient we assign the JOINED status to the owner - // of this avatarID. - if (speakers_iter != speakers_uuids.end()) - { - setState(item, STATE_JOINED); - - LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(participant_id); - if (speaker.isNull()) - continue; - speaker->mHasLeftCurrentCall = FALSE; - - speakers_uuids.erase(speakers_iter); - found = true; - } - - if (!found) - { - updateNotInVoiceParticipantState(item); - } - } -} - -void LLCallFloater::updateNotInVoiceParticipantState(LLAvatarListItem* item) -{ - LLUUID participant_id = item->getAvatarId(); - ESpeakerState current_state = getState(participant_id); - - switch (current_state) - { - case STATE_JOINED: - // If an avatarID is not found in a speakers list from VoiceClient and - // a panel with this ID has a JOINED status this means that this person - // HAS LEFT the call. - setState(item, STATE_LEFT); - - { - LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(participant_id); - if (speaker.notNull()) - { - speaker->mHasLeftCurrentCall = TRUE; - } - } - break; - case STATE_LEFT: - // nothing to do. These states should not be changed. - break; - case STATE_INVITED: - // If avatar was invited into group chat and went offline it is still exists in mSpeakerStateMap - // If it goes online it will be rendered as JOINED via LAvatarListItem. - // Lets update its visual representation. See EXT-6660 - case STATE_UNKNOWN: - // If an avatarID is not found in a speakers list from VoiceClient and - // a panel with this ID has an UNKNOWN status this means that this person - // HAS ENTERED session but it is not in voice chat yet. So, set INVITED status - setState(item, STATE_INVITED); - break; - default: - // for possible new future states. - llwarns << "Unsupported (" << getState(participant_id) << ") state for: " << item->getAvatarName() << llendl; - break; - } -} - -void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state) -{ - // *HACK: mantipov: sometimes such situation is possible while switching to voice channel: -/* - - voice channel is switched to the one user is joining - - participant list is initialized with voice states: agent is in voice - - than such log messages were found (with agent UUID) - - LLVivoxProtocolParser::process_impl: parsing: <Response requestId="22" action="Session.MediaDisconnect.1"><ReturnCode>0</ReturnCode><Results><StatusCode>0</StatusCode><StatusString /></Results><InputXml><Request requestId="22" action="Session.MediaDisconnect.1"><SessionGroupHandle>9</SessionGroupHandle><SessionHandle>12</SessionHandle><Media>Audio</Media></Request></InputXml></Response> - - LLVoiceClient::sessionState::removeParticipant: participant "sip:x2pwNkMbpR_mK4rtB_awASA==@bhr.vivox.com" (da9c0d90-c6e9-47f9-8ae2-bb41fdac0048) removed. - - and than while updating participants voice states agent is marked as HAS LEFT - - next updating of LLVoiceClient state makes agent JOINED - So, lets skip HAS LEFT state for agent's avatar -*/ - if (STATE_LEFT == state && item->getAvatarId() == gAgentID) return; - - setState(item->getAvatarId(), state); - - switch (state) - { - case STATE_INVITED: - item->setState(LLAvatarListItem::IS_VOICE_INVITED); - break; - case STATE_JOINED: - removeVoiceRemoveTimer(item->getAvatarId()); - item->setState(LLAvatarListItem::IS_VOICE_JOINED); - break; - case STATE_LEFT: - { - setVoiceRemoveTimer(item->getAvatarId()); - item->setState(LLAvatarListItem::IS_VOICE_LEFT); - } - break; - default: - llwarns << "Unrecognized avatar panel state (" << state << ")" << llendl; - break; - } -} - -void LLCallFloater::setVoiceRemoveTimer(const LLUUID& voice_speaker_id) -{ - mSpeakerDelayRemover->setActionTimer(voice_speaker_id); -} - -bool LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id) -{ - uuid_vec_t& speaker_uuids = mAvatarList->getIDs(); - uuid_vec_t::iterator pos = std::find(speaker_uuids.begin(), speaker_uuids.end(), voice_speaker_id); - if(pos != speaker_uuids.end()) - { - speaker_uuids.erase(pos); - mAvatarList->setDirty(); - } - - return false; -} - - -void LLCallFloater::resetVoiceRemoveTimers() -{ - mSpeakerDelayRemover->removeAllTimers(); -} - -void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id) -{ - mSpeakerDelayRemover->unsetActionTimer(voice_speaker_id); -} - -bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id) -{ - bool is_valid = true; - switch (mVoiceType) - { - case VC_LOCAL_CHAT: - { - // A nearby chat speaker is considered valid it it's known to LLVoiceClient (i.e. has enabled voice). - uuid_vec_t speakers; - get_voice_participants_uuids(speakers); - is_valid = std::find(speakers.begin(), speakers.end(), speaker_id) != speakers.end(); - } - break; - case VC_GROUP_CHAT: - // if participant had left this call before do not allow add her again. See EXT-4216. - // but if she Join she will be added into the list from the LLCallFloater::onChange() - is_valid = STATE_LEFT != getState(speaker_id); - break; - default: - // do nothing. required for Linux build - break; - } - - return is_valid; -} - -void LLCallFloater::connectToChannel(LLVoiceChannel* channel) -{ - mVoiceChannelStateChangeConnection.disconnect(); - - sCurrentVoiceChannel = channel; - - mVoiceChannelStateChangeConnection = sCurrentVoiceChannel->setStateChangedCallback(boost::bind(&LLCallFloater::onVoiceChannelStateChanged, this, _1, _2)); - - updateState(channel->getState()); -} - -void LLCallFloater::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) -{ - // check is voice operational and if it doesn't work hide VCP (EXT-4397) - if(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking()) - { - updateState(new_state); - } - else - { - closeFloater(); - } -} - -void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state) -{ - LL_DEBUGS("Voice") << "Updating state: " << new_state << ", session name: " << sCurrentVoiceChannel->getSessionName() << LL_ENDL; - if (LLVoiceChannel::STATE_CONNECTED == new_state) - { - updateSession(); - } - else - { - reset(new_state); - } -} - -void LLCallFloater::reset(const LLVoiceChannel::EState& new_state) -{ - // lets forget states from the previous session - // for timers... - resetVoiceRemoveTimers(); - - // ...and for speaker state - mSpeakerStateMap.clear(); - - delete mParticipants; - mParticipants = NULL; - mAvatarList->clear(); - - // These ifs were added instead of simply showing "loading" to make VCP work correctly in parcels - // with disabled voice (EXT-4648 and EXT-4649) - if (!LLViewerParcelMgr::getInstance()->allowAgentVoice() && LLVoiceChannel::STATE_HUNG_UP == new_state) - { - // hides "Leave Call" when call is ended in parcel with disabled voice- hiding usually happens in - // updateSession() which won't be called here because connect to nearby voice never happens - getChildView("leave_call_btn_panel")->setVisible( false); - // setting title to nearby chat an "no one near..." text- because in region with disabled - // voice we won't have chance to really connect to nearby, so VCP is changed here manually - setTitle(getString("title_nearby")); - mAvatarList->setNoItemsCommentText(getString("no_one_near")); - } - // "loading" is shown only when state is "ringing" to avoid showing it in nearby chat vcp - // of parcels with disabled voice all the time- "no_one_near" is now shown there (EXT-4648) - else if (new_state == LLVoiceChannel::STATE_RINGING) - { - // update floater to show Loading while waiting for data. - mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData")); - } - - mAvatarList->setVisible(TRUE); - mNonAvatarCaller->setVisible(FALSE); - - mSpeakerManager = NULL; -} - -//EOF diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h deleted file mode 100644 index e1c7b3f43a..0000000000 --- a/indra/newview/llcallfloater.h +++ /dev/null @@ -1,275 +0,0 @@ -/** - * @file llcallfloater.h - * @author Mike Antipov - * @brief Voice Control Panel in a Voice Chats (P2P, Group, Nearby...). - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLCALLFLOATER_H -#define LL_LLCALLFLOATER_H - -#include "lltransientdockablefloater.h" -#include "llvoicechannel.h" -#include "llvoiceclient.h" -#include "llconversationmodel.h" - -class LLAvatarList; -class LLAvatarListItem; -class LLAvatarName; -class LLNonAvatarCaller; -class LLOutputMonitorCtrl; -class LLParticipantList; -class LLSpeakerMgr; -class LLSpeakersDelayActionsStorage; - -/** - * The Voice Control Panel is an ambient window summoned by clicking the flyout chevron - * on the Speak button. It can be torn-off and freely positioned onscreen. - * - * When the Resident is engaged in Voice Chat, the Voice Control Panel provides control - * over the audible volume of each of the other participants, the Resident's own Voice - * Morphing settings (if she has subscribed to enable the feature), and Voice Recording. - * - * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel - * also provides a 'Leave Call' button to allow the Resident to leave that voice channel. - */ -class LLCallFloater : public LLTransientDockableFloater, LLVoiceClientParticipantObserver -{ -public: - - LOG_CLASS(LLCallFloater); - - LLCallFloater(const LLSD& key); - ~LLCallFloater(); - - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void draw(); - /*virtual*/ void setFocus( BOOL b ); - - /** - * Is called by LLVoiceClient::notifyParticipantObservers when voice participant list is changed. - * - * Refreshes list to display participants not in voice as disabled. - */ - /*virtual*/ void onParticipantsChanged(); - - static void onCurrentChannelChanged(const LLUUID& session_id); - -private: - typedef enum e_voice_controls_type - { - VC_LOCAL_CHAT, - VC_GROUP_CHAT, - VC_AD_HOC_CHAT, - VC_PEER_TO_PEER, - VC_PEER_TO_PEER_AVALINE - }EVoiceControls; - - typedef enum e_speaker_state - { - STATE_UNKNOWN, - STATE_INVITED, - STATE_JOINED, - STATE_LEFT, - } ESpeakerState; - - typedef std::map<LLUUID, ESpeakerState> speaker_state_map_t; - - void leaveCall(); - - /** - * Updates mSpeakerManager and list according to current Voice Channel - * - * It compares mSpeakerManager & current Voice Channel session IDs. - * If they are different gets Speaker manager related to current channel and updates channel participant list. - */ - void updateSession(); - - /** - * Refreshes participant list according to current Voice Channel - */ - void refreshParticipantList(); - - /** - * Handles event on avatar list is refreshed after it was marked dirty. - * - * It sets initial participants voice states (once after the first refreshing) - * and updates voice states each time anybody is joined/left voice chat in session. - */ - void onAvatarListRefreshed(); - - /** - * Updates window title with an avatar name - */ - void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); - - void updateTitle(); - void initAgentData(); - void setModeratorMutedVoice(bool moderator_muted); - void updateAgentModeratorState(); - void onModeratorNameCache(const LLAvatarName& av_name); - - /** - * Sets initial participants voice states in avatar list (Invited, Joined, Has Left). - * - * @see refreshParticipantList() - * @see onAvatarListRefreshed() - * @see mInitParticipantsVoiceState - */ - void initParticipantsVoiceState(); - - /** - * Updates participants voice states in avatar list (Invited, Joined, Has Left). - * - * @see onAvatarListRefreshed() - * @see onChanged() - */ - void updateParticipantsVoiceState(); - - /** - * Updates voice state of participant not in current voice channel depend on its current state. - */ - void updateNotInVoiceParticipantState(LLAvatarListItem* item); - void setState(LLAvatarListItem* item, ESpeakerState state); - void setState(const LLUUID& speaker_id, ESpeakerState state) - { - lldebugs << "Storing state: " << speaker_id << ", " << state << llendl; - mSpeakerStateMap[speaker_id] = state; - } - - ESpeakerState getState(const LLUUID& speaker_id) - { - lldebugs << "Getting state: " << speaker_id << ", " << mSpeakerStateMap[speaker_id] << llendl; - - return mSpeakerStateMap[speaker_id]; - } - - /** - * Instantiates new LLAvatarListItemRemoveTimer and adds it into the map if it is not already created. - * - * @param voice_speaker_id LLUUID of Avatar List item to be removed from the list when timer expires. - */ - void setVoiceRemoveTimer(const LLUUID& voice_speaker_id); - - /** - * Removes specified by UUID Avatar List item. - * - * @param voice_speaker_id LLUUID of Avatar List item to be removed from the list. - */ - bool removeVoiceLeftParticipant(const LLUUID& voice_speaker_id); - - /** - * Deletes all timers from the list to prevent started timers from ticking after destruction - * and after switching on another voice channel. - */ - void resetVoiceRemoveTimers(); - - /** - * Removes specified by UUID timer from the map. - * - * @param voice_speaker_id LLUUID of Avatar List item whose timer should be removed from the map. - */ - void removeVoiceRemoveTimer(const LLUUID& voice_speaker_id); - - /** - * Called by LLParticipantList before adding a speaker to the participant list. - * - * If false is returned, the speaker will not be added to the list. - * - * @param speaker_id Speaker to validate. - * @return true if this is a valid speaker, false otherwise. - */ - bool validateSpeaker(const LLUUID& speaker_id); - - /** - * Connects to passed channel to be updated according to channel's voice states. - */ - void connectToChannel(LLVoiceChannel* channel); - - /** - * Callback to process changing of voice channel's states. - */ - void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); - - /** - * Updates floater according to passed channel's voice state. - */ - void updateState(const LLVoiceChannel::EState& new_state); - - /** - * Resets floater to be ready to show voice participants. - * - * Clears all data from the latest voice session. - */ - void reset(const LLVoiceChannel::EState& new_state); - -private: - speaker_state_map_t mSpeakerStateMap; - LLSpeakerMgr* mSpeakerManager; - LLParticipantList* mParticipants; - LLAvatarList* mAvatarList; - LLConversationViewModel mConversationViewModel; - LLNonAvatarCaller* mNonAvatarCaller; - EVoiceControls mVoiceType; - LLPanel* mAgentPanel; - LLOutputMonitorCtrl* mSpeakingIndicator; - bool mIsModeratorMutedVoice; - - /** - * Flag indicated that participants voice states should be initialized. - * - * It is used due to Avatar List has delayed refreshing after it content is changed. - * Real initializing is performed when Avatar List is first time refreshed. - * - * @see onAvatarListRefreshed() - * @see initParticipantsVoiceState() - */ - bool mInitParticipantsVoiceState; - - boost::signals2::connection mAvatarListRefreshConnection; - - - /** - * time out speakers when they are not part of current session - */ - LLSpeakersDelayActionsStorage* mSpeakerDelayRemover; - - /** - * Stores reference to current voice channel. - * - * Is used to ignore voice channel changed callback for the same channel. - * - * @see onCurrentChannelChanged() - */ - static LLVoiceChannel* sCurrentVoiceChannel; - - /* virtual */ - LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } - - boost::signals2::connection mVoiceChannelStateChangeConnection; -}; - - -#endif //LL_LLCALLFLOATER_H - diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index c751550523..b99d04abae 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -32,7 +32,6 @@ #include "llviewerfloaterreg.h" #include "llfloaterautoreplacesettings.h" #include "llcompilequeue.h" -#include "llcallfloater.h" #include "llfasttimerview.h" #include "llfloaterabout.h" #include "llfloaterauction.h" @@ -322,7 +321,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("upload_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptPreview>, "upload"); LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload"); - LLFloaterReg::add("voice_controls", "floater_voice_controls.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLCallFloater>); LLFloaterReg::add("voice_effect", "floater_voice_effect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceEffect>); LLFloaterReg::add("web_content", "floater_web_content.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index f1bf4a6d75..7da71a04d9 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -3712,8 +3712,7 @@ void LLVivoxVoiceClient::participantUpdatedEvent( voice participant mIsModeratorMuted is changed after speakers are updated in Speaker Manager and event is not fired. - So, we have to call LLSpeakerMgr::update() here. In any case it is better than call it - in LLCallFloater::draw() + So, we have to call LLSpeakerMgr::update() here. */ LLVoiceChannel* voice_cnl = LLVoiceChannel::getCurrentVoiceChannel(); diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml deleted file mode 100644 index dce2720cf8..0000000000 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ /dev/null @@ -1,155 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - positioning="cascading" - can_resize="true" - can_minimize="true" - can_close="true" - chrome="true" - height="205" - layout="topleft" - min_height="124" - min_width="190" - name="floater_voice_controls" - help_topic="floater_voice_controls" - title="VOICE CONTROLS" - save_dock_state="true" - save_visibility="true" - save_rect="true" - single_instance="true" - width="282"> - <string - name="title_nearby"> - VOICE SETTINGS - </string> - <string - name="title_group"> - GROUP CALL WITH [GROUP] - </string> - <string - name="title_adhoc"> - CONFERENCE CALL - </string> - <string - name="title_peer_2_peer"> - CALL WITH [NAME] - </string> - <string - name="no_one_near"> - No one near has voice enabled - </string> - <layout_stack - clip="false" - follows="all" - height="189" - layout="topleft" - left="10" - mouse_opaque="false" - name="my_call_stack" - orientation="vertical" - width="263"> - <layout_panel - follows="top|left|right" - auto_resize="false" - layout="topleft" - min_height="20" - height="20" - name="my_panel"> - <avatar_icon - enabled="false" - follows="left|top" - height="18" - default_icon_name="Generic_Person" - layout="topleft" - left="5" - name="user_icon" - top="0" - width="18" /> - <text - follows="top|left|right" - font="SansSerifSmallBold" - height="16" - layout="topleft" - left_pad="10" - name="user_text" - text_color="White" - top="4" - use_ellipses="true" - value="My Avatar:" - width="210" /> - <output_monitor - auto_update="true" - draw_border="false" - follows="top|right" - height="16" - layout="topleft" - right="-3" - name="speaking_indicator" - left_pad="5" - visible="true" - width="20" /> - </layout_panel> - <layout_panel name="leave_call_panel" height="26" min_height="26" auto_resize="false"> - <layout_stack - clip="true" - follows="left|top|right" - height="26" - layout="topleft" - mouse_opaque="false" - name="voice_effect_and_leave_call_stack" - orientation="horizontal" - width="262"> - <layout_panel - height="26" - width="200"> - <panel - class="panel_voice_effect" - name="panel_voice_effect" - visiblity_control="VoiceMorphingEnabled" - filename="panel_voice_effect.xml" /> - </layout_panel> - <layout_panel - auto_resize="false" - follows="top|right" - height="23" - visible="true" - layout="topleft" - name="leave_call_btn_panel" - width="100"> - <button - follows="right|top" - height="23" - label="Leave Call" - name="leave_call_btn" - width="100" /> - </layout_panel> - </layout_stack> - </layout_panel> - <layout_panel - follows="all" - layout="topleft" - left="2" - top_pad="0" - height="132" - name="callers_panel" - auto_resize="true" - width="280"> - <avatar_list - follows="all" - height="132" - ignore_online_status="true" - layout="topleft" - multi_select="true" - name="speakers_list" - width="280" /> - <panel - filename="panel_avatar_list_item.xml" - follows="left|right|top" - height="24" - layout="topleft" - left="0" - name="non_avatar_caller" - top="10" - width="276" /> - </layout_panel> - </layout_stack> -</floater> -- cgit v1.2.3 From 37c416dee38a082aada799f0430022bd3051e54a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 5 Nov 2012 17:39:29 -0800 Subject: CHUI-479: Problem: The parent folder's view model did not store the session id. Because of this, the speaker indicator would be set to a session id of null (nearby chat). Solution: Now when the folder view model is created in the torn off list, pass in the session id. This allows the folder view model to know which session id it belongs to. Participants can then look at the parent folder (folder view) and retrieve the session id. --- indra/newview/llimconversation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index de769d95ac..3e42e0b4ef 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -187,7 +187,7 @@ BOOL LLIMConversation::postBuild() mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); // Create a root view folder for all participants - LLConversationItem* base_item = new LLConversationItem(mConversationViewModel); + LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); p.rect = LLRect(0, 0, getRect().getWidth(), 0); p.parent_panel = mParticipantListPanel; -- cgit v1.2.3 From 2d9d44e31643214c80bde5ffee03f9b6af6af9d0 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 5 Nov 2012 18:33:39 -0800 Subject: CHUI-468 : WIP : Taking LLAvatarList and related out of LLParticipantList --- indra/newview/llconversationview.cpp | 7 +- indra/newview/llimconversation.cpp | 5 +- indra/newview/llimconversation.h | 1 + indra/newview/llimfloatercontainer.cpp | 4 +- indra/newview/llparticipantlist.cpp | 142 ++++----------------- indra/newview/llparticipantlist.h | 37 ++---- .../xui/en/panel_conversation_list_item.xml | 2 +- 7 files changed, 43 insertions(+), 155 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 81212a9141..87532268e7 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -108,7 +108,7 @@ BOOL LLConversationViewSession::postBuild() mSessionTitle = mItemPanel->getChild<LLTextBox>("conversation_title"); mActiveVoiceChannelConnection = LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLConversationViewSession::onCurrentVoiceSessionChanged, this, _1)); - mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicatorn"); + mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator"); LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); if (vmi) @@ -476,10 +476,11 @@ void LLConversationViewParticipant::selectItem() void LLConversationViewParticipant::refresh() { // Refresh the participant view from its model data - LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); + LLConversationItemParticipant* vmi = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem()); vmi->resetRefresh(); - // Note: for the moment, all that needs to be done is done by LLFolderViewItem::refresh() + // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat + mSpeakingIndicator->setIsMuted(vmi->isMuted()); // Do the regular upstream refresh LLFolderViewItem::refresh(); diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index de769d95ac..62712a5c7c 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -485,7 +485,8 @@ LLConversationViewParticipant* LLIMConversation::createConversationViewParticipa void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata) { - // TODO: Check this code when sort order menu will be added. (EM) + // *TODO: Check this code when sort order menu will be added. (EM) + /* if (!getParticipantList()) { return; @@ -497,7 +498,7 @@ void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata) { getParticipantList()->setSortOrder(LLParticipantList::E_SORT_BY_NAME); } - + */ } void LLIMConversation::onIMSessionMenuItemClicked(const LLSD& userdata) diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index cb306c4d8d..ff248d97ff 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -36,6 +36,7 @@ #include "llimview.h" #include "llconversationmodel.h" #include "llconversationview.h" +#include "lltexteditor.h" class LLPanelChatControlPanel; class LLChatEntry; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 72e0f90f8c..e6657260e6 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -115,7 +115,7 @@ void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) { - // CHUI-441 : We should do this *without* delete and recreate + // *TODO: We should do this *without* delete and recreate addConversationListItem(new_session_id, removeConversationListItem(old_session_id)); } @@ -1164,7 +1164,7 @@ LLConversationItem* LLIMFloaterContainer::addConversationListItem(const LLUUID& LLSpeakerMgr* speaker_manager = (is_nearby_chat ? (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()) : LLIMModel::getInstance()->getSpeakerManager(uuid)); if (speaker_manager) { - item = new LLParticipantList(speaker_manager, NULL, getRootViewModel(), true, false); + item = new LLParticipantList(speaker_manager, getRootViewModel(), true, false); } if (!item) { diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index e199cb5776..6afcf21348 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -1,6 +1,6 @@ /** * @file llparticipantlist.cpp - * @brief LLParticipantList intended to update view(LLAvatarList) according to incoming messages + * @brief LLParticipantList widgets of a conversation list * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code @@ -48,23 +48,6 @@ #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally #endif -static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR; - -// helper function to update AvatarList Item's indicator in the voice participant list -static void update_speaker_indicator(const LLAvatarList* const avatar_list, const LLUUID& avatar_uuid, bool is_muted) -{ - if (avatar_list) - { - LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(avatar_list->getItemByValue(avatar_uuid)); - if (item) - { - LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("speaking_indicator"); - indicator->setIsMuted(is_muted); - } - } -} - - // See EXT-4301. /** * class LLAvalineUpdater - observe the list of voice participants in session and check @@ -205,14 +188,12 @@ private: }; LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, - LLAvatarList* avatar_list, LLFolderViewModelInterface& root_view_model, bool use_context_menu/* = true*/, bool exclude_agent /*= true*/, bool can_toggle_icons /*= true*/) : LLConversationItemSession(data_source->getSessionID(), root_view_model), mSpeakerMgr(data_source), - mAvatarList(avatar_list), mExcludeAgent(exclude_agent), mValidateSpeakerCallback(NULL) { @@ -234,7 +215,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, mSpeakerMgr->addListener(mSpeakerUpdateListener, "update_speaker"); setSessionID(mSpeakerMgr->getSessionID()); - + /* if (mAvatarList) { mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData")); @@ -260,7 +241,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, mAvatarListToggleIconsConnection = gSavedSettings.getControl("ParticipantListShowIcons")->getSignal()->connect(boost::bind(&LLAvatarList::toggleIcons, mAvatarList)); } } - + */ //Lets fill avatarList with existing speakers LLSpeakerMgr::speaker_list_t speaker_list; mSpeakerMgr->getSpeakerList(&speaker_list, true); @@ -278,8 +259,6 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, mModeratorToRemoveList.insert(speakerp->mID); } } - // we need to exclude agent id for non group chat - sort(); // Identify and store what kind of session we are LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(data_source->getSessionID()); @@ -305,6 +284,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLParticipantList::~LLParticipantList() { + /* if (mAvatarList) { mAvatarListDoubleClickConnection.disconnect(); @@ -318,10 +298,11 @@ LLParticipantList::~LLParticipantList() mAvatarList->setContextMenu(NULL); mAvatarList->setComparator(NULL); } - + */ delete mAvalineUpdater; } +/* void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible) { if (mAvatarList) @@ -329,7 +310,8 @@ void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible) mAvatarList->setSpeakingIndicatorsVisible(visible); } } - +*/ +/* void LLParticipantList::onAvatarListDoubleClicked(LLUICtrl* ctrl) { LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(ctrl); @@ -345,7 +327,8 @@ void LLParticipantList::onAvatarListDoubleClicked(LLUICtrl* ctrl) LLAvatarActions::startIM(clicked_id); } - +*/ +/* void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) { LLAvatarList* list = dynamic_cast<LLAvatarList*>(ctrl); @@ -423,11 +406,10 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) { setParticipantIsMuted(speakerp->mID, speakerp->mModeratorMutedVoice); - update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); } } } - +*/ /* Seems this method is not necessary after onAvalineCallerRemoved was implemented; @@ -441,40 +423,11 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) */ void LLParticipantList::onAvalineCallerFound(const LLUUID& participant_id) { - if (mAvatarList) - { - LLPanel* item = mAvatarList->getItemByValue(participant_id); - - if (NULL == item) - { - LL_WARNS("Avaline") << "Something wrong. Unable to find item for: " << participant_id << LL_ENDL; - return; - } - - if (typeid(*item) == typeid(LLAvalineListItem)) - { - LL_DEBUGS("Avaline") << "Avaline caller has already correct class type for: " << participant_id << LL_ENDL; - // item representing an Avaline caller has a correct type already. - return; - } - - LL_DEBUGS("Avaline") << "remove item from the list and re-add it: " << participant_id << LL_ENDL; - - // remove UUID from LLAvatarList::mIDs to be able add it again. - uuid_vec_t& ids = mAvatarList->getIDs(); - uuid_vec_t::iterator pos = std::find(ids.begin(), ids.end(), participant_id); - ids.erase(pos); - - // remove item directly - mAvatarList->removeItem(item); - } - LLConversationItemParticipant* participant = findParticipant(participant_id); if (participant) { removeParticipant(participant); } - // re-add avaline caller with a correct class instance. addAvatarIDExceptAgent(participant_id); } @@ -485,7 +438,7 @@ void LLParticipantList::onAvalineCallerRemoved(const LLUUID& participant_id) mSpeakerMgr->removeAvalineSpeaker(participant_id); } - +/* void LLParticipantList::setSortOrder(EParticipantSortOrder order) { const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder"); @@ -502,7 +455,7 @@ const LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder() const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder"); return EParticipantSortOrder(speaker_sort_order); } - +*/ void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb) { mValidateSpeakerCallback = cb; @@ -512,19 +465,14 @@ void LLParticipantList::update() { mSpeakerMgr->update(true); + /* // Need to resort the participant list if it's in sort by recent speaker order. - if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder() && !isHovered()) + if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder()) { // Resort avatar list sort(); } -} - -bool LLParticipantList::isHovered() -{ - S32 x, y; - LLUI::getMousePositionScreen(&x, &y); - return (mAvatarList ? mAvatarList->calcScreenRect().pointInRect(x, y) : false); + */ } bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) @@ -537,35 +485,18 @@ bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, co } addAvatarIDExceptAgent(uu_id); - sort(); return true; } bool LLParticipantList::onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) { LLUUID avatar_id = event->getValue().asUUID(); - if (mAvatarList) - { - uuid_vec_t& group_members = mAvatarList->getIDs(); - uuid_vec_t::iterator pos = std::find(group_members.begin(), group_members.end(), avatar_id); - if(pos != group_members.end()) - { - group_members.erase(pos); - mAvatarList->setDirty(); - } - } removeParticipant(avatar_id); return true; } bool LLParticipantList::onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) { - if (mAvatarList) - { - uuid_vec_t& group_members = mAvatarList->getIDs(); - group_members.clear(); - mAvatarList->setDirty(); - } clearParticipants(); return true; } @@ -605,9 +536,9 @@ bool LLParticipantList::onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> e mModeratorList.erase(id); } } - + // *TODO : do we have to fire an event so that LLIMConversation::refreshConversation() gets called // apply changes immediately - onAvatarListRefreshed(mAvatarList, LLSD()); + //onAvatarListRefreshed(mAvatarList, LLSD()); } } return true; @@ -622,11 +553,11 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event if (event->getValue().asString() == "voice") { setParticipantIsMuted(speakerp->mID, speakerp->mModeratorMutedVoice); - update_speaker_indicator(mAvatarList, speakerp->mID, speakerp->mModeratorMutedVoice); } return true; } +/* void LLParticipantList::sort() { // *TODO : Merov : Need to plan for sort() for LLConversationModel @@ -658,12 +589,12 @@ void LLParticipantList::sort() return; } } +*/ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) { // Do not add if already in there or excluded for some reason if (mExcludeAgent && gAgent.getID() == avatar_id) return; - if (mAvatarList && mAvatarList->contains(avatar_id)) return; if (findParticipant(avatar_id)) return; bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(avatar_id); @@ -677,21 +608,25 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name); participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.mDisplayName , avatar_id, mRootViewModel); participant->fetchAvatarName(); + /* if (mAvatarList) { mAvatarList->getIDs().push_back(avatar_id); mAvatarList->setDirty(); } + */ } else { std::string display_name = LLVoiceClient::getInstance()->getDisplayName(avatar_id); // Create a participant view model instance participant = new LLConversationItemParticipant(display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name, avatar_id, mRootViewModel); + /* if (mAvatarList) { mAvatarList->addAvalineItem(avatar_id, mSpeakerMgr->getSessionID(), display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name); } + */ mAvalineUpdater->watchAvalineCaller(avatar_id); } @@ -768,33 +703,4 @@ bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents:: return mParent.onSpeakerMuteEvent(event, userdata); } -bool LLParticipantList::LLAvatarItemRecentSpeakerComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const -{ - if (mParent.mSpeakerMgr) - { - LLPointer<LLSpeaker> lhs = mParent.mSpeakerMgr->findSpeaker(avatar_item1->getAvatarId()); - LLPointer<LLSpeaker> rhs = mParent.mSpeakerMgr->findSpeaker(avatar_item2->getAvatarId()); - if ( lhs.notNull() && rhs.notNull() ) - { - // Compare by last speaking time - if( lhs->mLastSpokeTime != rhs->mLastSpokeTime ) - return ( lhs->mLastSpokeTime > rhs->mLastSpokeTime ); - else if ( lhs->mSortIndex != rhs->mSortIndex ) - return ( lhs->mSortIndex < rhs->mSortIndex ); - } - else if ( lhs.notNull() ) - { - // True if only avatar_item1 speaker info available - return true; - } - else if ( rhs.notNull() ) - { - // False if only avatar_item2 speaker info available - return false; - } - } - // By default compare by name. - return LLAvatarItemNameComparator::doCompare(avatar_item1, avatar_item2); -} - //EOF diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index aaf1e070a5..97e06dcfea 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -1,6 +1,6 @@ /** * @file llparticipantlist.h - * @brief LLParticipantList intended to update view(LLAvatarList) according to incoming messages + * @brief LLParticipantList widgets of a conversation list * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code @@ -29,12 +29,10 @@ #include "llviewerprecompiledheaders.h" #include "llevent.h" -#include "llavatarlist.h" // for LLAvatarItemRecentSpeakerComparator #include "lllistcontextmenu.h" #include "llconversationmodel.h" class LLSpeakerMgr; -class LLAvatarList; class LLUICtrl; class LLAvalineUpdater; @@ -46,13 +44,12 @@ public: typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t; LLParticipantList(LLSpeakerMgr* data_source, - LLAvatarList* avatar_list, LLFolderViewModelInterface& root_view_model, bool use_context_menu = true, bool exclude_agent = true, bool can_toggle_icons = true); ~LLParticipantList(); - void setSpeakingIndicatorsVisible(BOOL visible); +// void setSpeakingIndicatorsVisible(BOOL visible); enum EParticipantSortOrder { @@ -70,8 +67,8 @@ public: /** * Set and sort Avatarlist by given order */ - void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME); - const EParticipantSortOrder getSortOrder() const; + //void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME); + //const EParticipantSortOrder getSortOrder() const; /** * Refreshes the participant list. @@ -101,7 +98,7 @@ protected: /** * Sorts the Avatarlist by stored order */ - void sort(); + //void sort(); /** * List of listeners implementing LLOldEvents::LLSimpleListener. @@ -159,24 +156,9 @@ protected: /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); }; - /** - * Comparator for comparing avatar items by last spoken time - */ - class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator, public LLRefCount - { - LOG_CLASS(LLAvatarItemRecentSpeakerComparator); - public: - LLAvatarItemRecentSpeakerComparator(LLParticipantList& parent):mParent(parent){}; - virtual ~LLAvatarItemRecentSpeakerComparator() {}; - protected: - virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const; - private: - LLParticipantList& mParent; - }; - private: - void onAvatarListDoubleClicked(LLUICtrl* ctrl); - void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param); +// void onAvatarListDoubleClicked(LLUICtrl* ctrl); +// void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param); void onAvalineCallerFound(const LLUUID& participant_id); void onAvalineCallerRemoved(const LLUUID& participant_id); @@ -188,10 +170,7 @@ private: */ void adjustParticipant(const LLUUID& speaker_id); - bool isHovered(); - LLSpeakerMgr* mSpeakerMgr; - LLAvatarList* mAvatarList; std::set<LLUUID> mModeratorList; std::set<LLUUID> mModeratorToRemoveList; @@ -216,7 +195,7 @@ private: boost::signals2::connection mAvatarListReturnConnection; boost::signals2::connection mAvatarListToggleIconsConnection; - LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers; +// LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers; validate_speaker_callback_t mValidateSpeakerCallback; LLAvalineUpdater* mAvalineUpdater; }; diff --git a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml index 56056ed560..771d9fa680 100644 --- a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml @@ -90,7 +90,7 @@ layout="topleft" left_pad="5" mouse_opaque="true" - name="speaking_indicatorn" + name="speaking_indicator" visible="false" width="20" /> </layout_panel> -- cgit v1.2.3 From 50615ba69c94441c99f21f861cf0290972162998 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 6 Nov 2012 17:56:25 -0800 Subject: CHUI-507: Updated to the new layout of 'Chat Preferences' according to CHUI Notifications spec. The functionality for the new preferences is not yet implemented. --- .../default/xui/en/panel_preferences_chat.xml | 449 +++++++++++++++------ 1 file changed, 331 insertions(+), 118 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index c76a3cfaaf..28434a670e 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -9,151 +9,364 @@ name="chat" top="1" width="517"> - <text - follows="left|top" - layout="topleft" - left="30" - height="12" - name="font_size" - width="120" - top="10"> - Font size: - </text> - <radio_group - height="30" - layout="topleft" - left="40" - control_name="ChatFontSize" - name="chat_font_size" - top_pad="0" - width="440"> - <radio_item - height="16" - label="Small" - layout="topleft" - left="0" - name="radio" - value="0" - top="10" - width="125" /> - <radio_item - height="16" - label="Medium" - layout="topleft" - left_delta="145" - name="radio2" - value="1" - top_delta="0" - width="125" /> - <radio_item - height="16" - label="Large" - layout="topleft" - left_delta="170" - name="radio3" - value="2" - top_delta="0" - width="125" /> - </radio_group> - + + <panel + border="false" + follows="left|top" + height="90" + layout="topleft" + top="10" + left="13" + width="517"> + <check_box - control_name="PlayTypingAnim" - height="16" - initial_value="true" - label="Play typing animation when chatting" - layout="topleft" - left="30" - name="play_typing_animation" - top_pad="10" - width="400" /> + control_name="PlayTypingAnim" + height="16" + initial_value="true" + label="Play typing animation when chatting" + layout="topleft" + top="0" + name="play_typing_animation" + width="330" /> <check_box enabled="false" height="16" label="Email me IMs when I'm offline" layout="topleft" - left_delta="0" name="send_im_to_email" - top_pad="5" - width="400" /> + top_pad="6" + width="330" /> + <check_box + height="16" + label="Keep a conversation log and transcripts" + layout="topleft" + name="keep_convo_log_and_transcripts" + top_pad="6" + width="330" /> <check_box control_name="UseChatBubbles" follows="left|top" height="16" label="Bubble Chat" layout="topleft" - left_delta="0" - top_pad="5" + top_pad="6" name="bubble_text_chat" - width="150" /> + width="330" /> <text - name="disable_toast_label" follows="left|top" layout="topleft" - top_pad="20" - left="30" - height="10" - width="400"> - Enable incoming chat popups: - </text> - <check_box - control_name="EnableGroupChatPopups" - name="EnableGroupChatPopups" - label="Group Chats" - layout="topleft" - top_pad="5" - left_delta="10" - height="20" - tool_tip="Check to see popups when a Group Chat message arrives" - width="400" /> - <check_box - control_name="EnableIMChatPopups" - name="EnableIMChatPopups" - label="IM Chats" - layout="topleft" - top_pad="5" - height="16" - tool_tip="Check to see popups when an instant message arrives" - width="400" /> - <spinner - control_name="NearbyToastLifeTime" - decimal_digits="0" + left="345" + height="12" + name="font_size" + width="120" + top="0"> + Font size: + </text> + <radio_group + height="90" + layout="topleft" + left="352" + control_name="ChatFontSize" + name="chat_font_size" + top_pad="0" + width="50"> + <radio_item + height="16" + label="Small" + layout="topleft" + name="radio" + value="0" + top="10" + width="125" /> + <radio_item + height="16" + label="Medium" + layout="topleft" + name="radio2" + value="1" + top_pad="6" + width="125" /> + <radio_item + height="16" + label="Large" + layout="topleft" + name="radio3" + value="2" + top_pad="6" + width="125" /> + </radio_group> + + </panel> + + <panel + border="false" + follows="left|top" + height="193" + layout="topleft" + left="13" + width="517"> + + <text follows="left|top" - height="23" - increment="1" - initial_value="23" - label="Nearby chat toasts life time:" - label_width="285" layout="topleft" - left="45" - max_val="60" - min_val="1" - name="nearby_toasts_lifetime" - top_pad="10" - width="325" /> - <spinner - control_name="NearbyToastFadingTime" - decimal_digits="0" + height="12" + name="notifications" + left="0" + width="120"> + Notifications: + </text> + <text follows="left|top" - height="23" - increment="1" - initial_value="3" - label="Nearby chat toasts fading time:" - label_width="285" layout="topleft" - left_delta="0" - max_val="60" - min_val="0" - name="nearby_toasts_fadingtime" - top_pad="3" - width="325" /> + height="12" + name="friend_ims" + width="145" + left="0" + top_pad="15" + > + Friend IMs: + </text> + <combo_box + control_name="NotificationFriendIMOptions" + height="23" + layout="topleft" + left_pad="5" + top_delta="-6" + name="FriendIMOptions" + width="223"> + <combo_box.item + label="Pop up the message" + name="0" + value="0"/> + <combo_box.item + label="Flash toolbar button" + name="1" + value="1"/> + <combo_box.item + label="None" + name="2" + value="2"/> + </combo_box> + <text + follows="left|top" + layout="topleft" + height="12" + name="non_friend_ims" + width="145" + left="0" + top_pad="15" + > + Non-friend IMs: + </text> + <combo_box + control_name="NotificationNonFriendIMOptions" + height="23" + layout="topleft" + left_pad="5" + top_delta="-6" + name="NonFriendIMOptions" + width="223"> + <combo_box.item + label="Pop up the message" + name="0" + value="0"/> + <combo_box.item + label="Flash toolbar button" + name="1" + value="1"/> + <combo_box.item + label="None" + name="2" + value="2"/> + </combo_box> + <text + follows="left|top" + layout="topleft" + left="0" + height="13" + name="conference_ims" + width="145" + top_pad="14" + > + Conference IMs: + </text> + <combo_box + control_name="NotificationConferenceIMOptions" + height="23" + layout="topleft" + left_pad="5" + top_delta="-6" + name="ConferenceIMOptions" + width="223"> + <combo_box.item + label="Pop up the message" + name="0" + value="0"/> + <combo_box.item + label="Flash toolbar button" + name="1" + value="1"/> + <combo_box.item + label="None" + name="2" + value="2"/> + </combo_box> + <text + follows="left|top" + layout="topleft" + left="0" + height="13" + name="group_chat" + width="145" + top_pad="14" + > + Group chat: + </text> + <combo_box + control_name="NotificationGroupChatOptions" + height="23" + layout="topleft" + left_pad="5" + top_delta="-6" + name="GroupChatOptions" + width="223"> + <combo_box.item + label="Pop up the message" + name="0" + value="0"/> + <combo_box.item + label="Flash toolbar button" + name="1" + value="1"/> + <combo_box.item + label="None" + name="2" + value="2"/> + </combo_box> + <text + follows="left|top" + layout="topleft" + left="0" + height="12" + name="nearby_chat" + width="145" + top_pad="14" + > + Nearby chat: + </text> + <combo_box + control_name="NotificationNearbyChatOptions" + height="23" + layout="topleft" + left_pad="5" + top_delta="-6" + name="NearbyChatOptions" + width="223"> + <combo_box.item + label="Pop up the message" + name="0" + value="0"/> + <combo_box.item + label="Flash toolbar button" + name="1" + value="1"/> + <combo_box.item + label="None" + name="2" + value="2"/> + </combo_box> + <text + follows="left|top" + layout="topleft" + left="0" + height="12" + name="notifications_alert" + width="350" + top_pad="11" + visible="true" + text_color="DrYellow" + > + To temporarily stop all notifications, use Me > Status > Busy. + </text> + + </panel> + + <panel + border="false" + follows="left|top" + height="1" + layout="topleft" + left="13" + width="517"> + + <text + follows="left|top" + layout="topleft" + left="0" + name="play_sound" + width="100" + top_pad="13" + visible="true"> + Play sound: + </text> + <check_box + control_name="NewConversation" + height="16" + initial_value="true" + label="New conversation" + layout="topleft" + left_pad="15" + top_pad="-10" + name="new_conversation" + width="150" /> + <check_box + control_name="IncomingVoiceCall" + height="16" + initial_value="true" + label="Incoming voice call" + layout="topleft" + top_pad="6" + name="incoming_voice_call" + width="150" /> + <check_box + control_name="GroupChatMessages" + height="16" + initial_value="false" + label="Group chat messages" + layout="topleft" + top_pad="6" + name="group_chat_messages" + width="150" /> + <check_box + control_name="TeleportOffer" + height="16" + initial_value="true" + label="Teleport offer" + layout="topleft" + left_pad="35" + top_pad="-59" + name="teleport_offer" + width="150" /> + <check_box + control_name="InventoryOffer" + height="16" + initial_value="false" + label="Inventory offer" + layout="topleft" + top_pad="6" + name="inventory_offer" + width="150" /> + + </panel> + <button follows="left|top" height="23" label="Translation..." layout="topleft" - left="30" + left="9" name="ok_btn" - top="-50" + top="-29" width="170"> <button.commit_callback function="Pref.TranslationSettings" /> -- cgit v1.2.3 From a337d7e59776f0ae6ecf72f67c813c9c60cfd8c7 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 7 Nov 2012 12:47:00 +0200 Subject: Fixed postBuild() for Ad-hoc conference --- indra/newview/llconversationview.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index de0c65e24f..0f649361fb 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -133,6 +133,7 @@ BOOL LLConversationViewSession::postBuild() LLGroupIconCtrl* icon = mItemPanel->getChild<LLGroupIconCtrl>("group_icon"); icon->setVisible(true); mSpeakingIndicator->setSpeakerId(gAgentID, vmi->getUUID(), true); + break; } case LLConversationItem::CONV_SESSION_GROUP: { -- cgit v1.2.3 From 8828eb21e2a8960bbcfd4edb2d113dbada7d4a5d Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Tue, 6 Nov 2012 22:02:09 +0200 Subject: CHUI-448 FIXED p2p IM chat conversations show a participant list with a carat --- indra/llui/llfolderviewitem.h | 2 +- indra/newview/llconversationview.cpp | 9 ++++++++ indra/newview/llconversationview.h | 2 ++ indra/newview/llimfloatercontainer.cpp | 41 +++++++++++++++++++++------------- 4 files changed, 38 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 7cbe70fb8b..8bb73bcf5d 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -260,7 +260,7 @@ public: // virtual void handleDropped(); virtual void draw(); - void drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color); + virtual void drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color); void drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor); void drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 0f649361fb..2d3a008bf4 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -344,6 +344,15 @@ void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& sessi } } +void LLConversationViewSession::drawOpenFolderArrow(const LLFolderViewItem::Params& default_params, const LLUIColor& fg_color) +{ + LLConversationItem * itemp = dynamic_cast<LLConversationItem*>(getViewModelItem()); + if (itemp && itemp->getType() != LLConversationItem::CONV_SESSION_1_ON_1) + { + LLFolderViewFolder::drawOpenFolderArrow(default_params, fg_color); + } +} + // // Implementation of conversations list participant (avatar) widgets // diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 4d77a4ade0..aeca747260 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -71,6 +71,8 @@ public: /*virtual*/ bool isMinimized() { return mMinimizedMode; } + /*virtual*/ void drawOpenFolderArrow(const LLFolderViewItem::Params& default_params, const LLUIColor& fg_color); + void toggleMinimizedMode(bool is_minimized); void setVisibleIfDetached(BOOL visible); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 52deae445b..af43b1ac38 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -424,15 +424,21 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]); if (session_model) { - LLConversationItemParticipant* participant_model = session_model->findParticipant(participant_id); - if (participant_model) + const LLUUID& uuid = session_model->getUUID(); + + LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(uuid); + + if (uuid.isNull() || im_sessionp && !im_sessionp->isP2PSessionType()) { - participant_view = createConversationViewParticipant(participant_model); - participant_view->addToFolder(session_view); - participant_view->setVisible(TRUE); + LLConversationItemParticipant* participant_model = session_model->findParticipant(participant_id); + if (participant_model) + { + participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(session_view); + participant_view->setVisible(TRUE); + } } } - } } else if (type == "update_participant") @@ -1175,17 +1181,22 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWi // Add a new conversation widget to the root folder of the folder view widget->addToFolder(mConversationsRoot); widget->requestArrange(); - + + LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(uuid); + // Create the participants widgets now // Note: usually, we do not get an updated avatar list at that point - LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); - LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); - while (current_participant_model != end_participant_model) - { - LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); - LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); - participant_view->addToFolder(widget); - current_participant_model++; + if (uuid.isNull() || im_sessionp && !im_sessionp->isP2PSessionType()) + { + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); + while (current_participant_model != end_participant_model) + { + LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); + LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(widget); + current_participant_model++; + } } // set the widget to minimized mode if conversations pane is collapsed -- cgit v1.2.3 From 990a8c6085b43cb0290a631b664b3160938b0536 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Tue, 6 Nov 2012 22:44:22 +0200 Subject: CHUI-462 (Torn-off Nearby Chat can't be closed) --- indra/newview/llimconversation.cpp | 4 ---- indra/newview/llimfloatercontainer.cpp | 7 +++++++ indra/newview/llimfloatercontainer.h | 2 ++ indra/newview/llnearbychat.cpp | 22 +++++++++++++++++++++- indra/newview/llnearbychat.h | 2 ++ 5 files changed, 32 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index b687e18cae..44cf300930 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -202,10 +202,6 @@ BOOL LLIMConversation::postBuild() if (isChatMultiTab()) { - if (mIsNearbyChat) - { - setCanClose(FALSE); - } result = LLFloater::postBuild(); } else diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index f85aa9a353..c9cd013317 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -1475,4 +1475,11 @@ void LLIMFloaterContainer::openNearbyChat() } } +void LLIMFloaterContainer::onNearbyChatClosed() +{ + // If nearby chat is the only remaining conversation and it is closed, close whole conversation floater as well + if (mConversationsItems.size() == 1) + closeFloater(); +} + // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 05ea94019b..16218fc287 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -92,6 +92,8 @@ public: LLUUID getSelectedSession() { return mSelectedSession; } void setSelectedSession(LLUUID sessionID) { mSelectedSession = sessionID; } + void onNearbyChatClosed(); + private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; avatarID_panel_map_t mSessions; diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index d1c7c6bfd7..cf42fcb91a 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -293,7 +293,7 @@ void LLNearbyChat::setVisible(BOOL visible) setFocus(visible); } - +// virtual void LLNearbyChat::onTearOffClicked() { LLIMConversation::onTearOffClicked(); @@ -311,6 +311,26 @@ void LLNearbyChat::onOpen(const LLSD& key) showTranslationCheckbox(LLTranslate::isTranslationConfigured()); } +// virtual +void LLNearbyChat::onClose(bool app_quitting) +{ + // Override LLIMConversation::onClose() so that Nearby Chat is not removed from the conversation floater +} + +// virtual +void LLNearbyChat::onClickCloseBtn() +{ + if (!isTornOff()) + return; + onTearOffClicked(); + + LLIMFloaterContainer *im_box = LLIMFloaterContainer::findInstance(); + if (im_box) + { + im_box->onNearbyChatClosed(); + } +} + void LLNearbyChat::onChatFontChange(LLFontGL* fontp) { // Update things with the new font whohoo diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index b155fd3c26..a6c4439b1d 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -52,6 +52,7 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setFocus(BOOL focusFlag); /*virtual*/ void setVisible(BOOL visible); @@ -96,6 +97,7 @@ protected: void onChatFontChange(LLFontGL* fontp); /*virtual*/ void onTearOffClicked(); + /*virtual*/ void onClickCloseBtn(); static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); EChatType processChatTypeTriggers(EChatType type, std::string &str); -- cgit v1.2.3 From 18011db7f0b60e4ec499e3cbdda4e4f716f458a2 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Tue, 6 Nov 2012 15:47:08 -0800 Subject: Altering the line item phone icon. --- indra/newview/skins/default/xui/en/panel_conversation_list_item.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml index 56056ed560..67feade9a3 100644 --- a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml @@ -54,14 +54,14 @@ visible="false" width="20"> <icon - height="20" + height="18" follows="top|right|left" image_name="Conv_toolbar_open_call" layout="topleft" left="0" name="selected_icon" - top="2" - width="20" /> + top="3" + width="18" /> </layout_panel> <layout_panel auto_resize="true" -- cgit v1.2.3 From 8c64fbf1b76e46fa3f5a8f8c6baba30d4583b7ec Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 6 Nov 2012 18:32:45 -0800 Subject: CHUI-468 : WIP : More cleanup and fix of the participants sorting in LLIMConversation --- indra/newview/llimconversation.cpp | 22 ++++++---------------- indra/newview/llimconversation.h | 5 ++--- indra/newview/llimfloatercontainer.cpp | 13 +++++++++++++ indra/newview/llimfloatercontainer.h | 1 + indra/newview/llparticipantlist.cpp | 9 --------- indra/newview/llparticipantlist.h | 1 - 6 files changed, 22 insertions(+), 29 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index f91c25ef8c..fb247b4604 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -166,7 +166,8 @@ void LLIMConversation::addToHost(const LLUUID& session_id) conversp->setHost(floater_container); conversp->setHost(NULL); } - + // Added floaters share some state (like sort order) with their host + conversp->setSortOrder(floater_container->getSortOrder()); } } } @@ -483,22 +484,11 @@ LLConversationViewParticipant* LLIMConversation::createConversationViewParticipa return LLUICtrlFactory::create<LLConversationViewParticipant>(params); } -void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata) +void LLIMConversation::setSortOrder(const LLConversationSort& order) { - // *TODO: Check this code when sort order menu will be added. (EM) - /* - if (!getParticipantList()) - { - return; - } - - std::string chosen_item = userdata.asString(); - - if (chosen_item == "sort_name") - { - getParticipantList()->setSortOrder(LLParticipantList::E_SORT_BY_NAME); - } - */ + mConversationViewModel.setSorter(order); + mConversationsRoot->arrangeAll(); + refreshConversation(); } void LLIMConversation::onIMSessionMenuItemClicked(const LLSD& userdata) diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index ff248d97ff..edcae5e45d 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -89,7 +89,8 @@ public: void refreshConversation(); void buildConversationViewParticipant(); - + void setSortOrder(const LLConversationSort& order); + protected: // callback for click on any items of the visual states menu @@ -107,8 +108,6 @@ protected: // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); - void onSortMenuItemClicked(const LLSD& userdata); - void hideOrShowTitle(); // toggle the floater's drag handle void hideAllStandardButtons(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index e6657260e6..4b992a2e0f 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -764,6 +764,19 @@ void LLIMFloaterContainer::setSortOrder(const LLConversationSort& order) mConversationsRoot->arrangeAll(); // try to keep selection onscreen, even if it wasn't to start with mConversationsRoot->scrollToShowSelection(); + + // Notify all conversation (torn off or not) of the change to the sort order + // Note: For the moment, the sort order is *unique* across all conversations. That might change in the future. + for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) + { + LLUUID session_id = it_session->first; + LLIMConversation *conversation_floater = (session_id.isNull() ? (LLIMConversation*)(LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")) : (LLIMConversation*)(LLIMFloater::findInstance(session_id))); + if (conversation_floater) + { + conversation_floater->setSortOrder(order); + } + } + gSavedSettings.setU32("ConversationSortOrder", (U32)order); } diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index a6f8677e46..5ae3f9f1d4 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -92,6 +92,7 @@ public: LLUUID getSelectedSession() { return mSelectedSession; } void setSelectedSession(LLUUID sessionID) { mSelectedSession = sessionID; } LLConversationItem* getSessionModel(const LLUUID& session_id) { return get_ptr_in_map(mConversationsItems,session_id); } + LLConversationSort& getSortOrder() { return mConversationViewModel.getSorter(); } private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 6afcf21348..e6eef56628 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -302,15 +302,6 @@ LLParticipantList::~LLParticipantList() delete mAvalineUpdater; } -/* -void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible) -{ - if (mAvatarList) - { - mAvatarList->setSpeakingIndicatorsVisible(visible); - } -} -*/ /* void LLParticipantList::onAvatarListDoubleClicked(LLUICtrl* ctrl) { diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 97e06dcfea..f4469b03f4 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -49,7 +49,6 @@ public: bool exclude_agent = true, bool can_toggle_icons = true); ~LLParticipantList(); -// void setSpeakingIndicatorsVisible(BOOL visible); enum EParticipantSortOrder { -- cgit v1.2.3 From 4ec5ee63e28a427d88dfc0329151eacaf375fdb6 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Wed, 7 Nov 2012 12:07:52 +0200 Subject: CHUI-450 (Your own name does not appear in nearby chat participant list if voice chat disabled) Added audio module initialization without faking mVoiceEnabled value --- indra/newview/llspeakers.cpp | 2 +- indra/newview/llvoicevivox.cpp | 42 +++++++++++++++++------------------------- indra/newview/llvoicevivox.h | 2 ++ 3 files changed, 20 insertions(+), 26 deletions(-) (limited to 'indra') diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 46fd8c1290..726199b7aa 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -504,7 +504,7 @@ void LLSpeakerMgr::update(BOOL resort_ok) void LLSpeakerMgr::updateSpeakerList() { // are we bound to the currently active voice channel? - if ((!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive())) + if ((!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel)) { std::set<LLUUID> participants; LLVoiceClient::getInstance()->getParticipantList(participants); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index f236123ef1..839de395a7 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -291,6 +291,7 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() : mCaptureDeviceDirty(false), mRenderDeviceDirty(false), mSpatialCoordsDirty(false), + mIsInitialized(false), mMuteMic(false), mMuteMicDirty(false), @@ -394,15 +395,7 @@ const LLVoiceVersionInfo& LLVivoxVoiceClient::getVersion() void LLVivoxVoiceClient::updateSettings() { - if(!mAudioSession) - { - // If audio module is not initialized, pretend that voice is enabled, thus letting state machine to take a full cycle - setVoiceEnabled(true); - } - else - { - setVoiceEnabled(gSavedSettings.getBOOL("EnableVoiceChat")); - } + setVoiceEnabled(gSavedSettings.getBOOL("EnableVoiceChat")); setEarLocation(gSavedSettings.getS32("VoiceEarLocation")); std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice"); @@ -528,7 +521,7 @@ void LLVivoxVoiceClient::requestVoiceAccountProvision(S32 retries) { LLViewerRegion *region = gAgent.getRegion(); - if ( region && mVoiceEnabled ) + if ( region && (mVoiceEnabled || !mIsInitialized)) { std::string url = region->getCapability("ProvisionVoiceAccountRequest"); @@ -699,7 +692,7 @@ void LLVivoxVoiceClient::stateMachine() setVoiceEnabled(false); } - if(mVoiceEnabled) + if(mVoiceEnabled || !mIsInitialized) { updatePosition(); } @@ -744,7 +737,7 @@ void LLVivoxVoiceClient::stateMachine() //MARK: stateDisabled case stateDisabled: - if(mTuningMode || (mVoiceEnabled && !mAccountName.empty())) + if(mTuningMode || ((mVoiceEnabled || !mIsInitialized) && !mAccountName.empty())) { setState(stateStart); } @@ -899,7 +892,7 @@ void LLVivoxVoiceClient::stateMachine() mTuningExitState = stateIdle; setState(stateMicTuningStart); } - else if(!mVoiceEnabled) + else if(!mVoiceEnabled && mIsInitialized) { // We never started up the connector. This will shut down the daemon. setState(stateConnectorStopped); @@ -1093,7 +1086,7 @@ void LLVivoxVoiceClient::stateMachine() //MARK: stateConnectorStart case stateConnectorStart: - if(!mVoiceEnabled) + if(!mVoiceEnabled && mIsInitialized) { // We were never logged in. This will shut down the connector. setState(stateLoggedOut); @@ -1111,7 +1104,7 @@ void LLVivoxVoiceClient::stateMachine() //MARK: stateConnectorStarted case stateConnectorStarted: // connector handle received - if(!mVoiceEnabled) + if(!mVoiceEnabled && mIsInitialized) { // We were never logged in. This will shut down the connector. setState(stateLoggedOut); @@ -1255,7 +1248,7 @@ void LLVivoxVoiceClient::stateMachine() //MARK: stateCreatingSessionGroup case stateCreatingSessionGroup: - if(mSessionTerminateRequested || !mVoiceEnabled) + if(mSessionTerminateRequested || !mVoiceEnabled && mIsInitialized) { // *TODO: Question: is this the right way out of this state setState(stateSessionTerminated); @@ -1271,7 +1264,7 @@ void LLVivoxVoiceClient::stateMachine() //MARK: stateRetrievingParcelVoiceInfo case stateRetrievingParcelVoiceInfo: // wait until parcel voice info is received. - if(mSessionTerminateRequested || !mVoiceEnabled) + if(mSessionTerminateRequested || !mVoiceEnabled && mIsInitialized) { // if a terminate request has been received, // bail and go to the stateSessionTerminated @@ -1291,7 +1284,7 @@ void LLVivoxVoiceClient::stateMachine() // Otherwise, if you log in but don't join a proximal channel (such as when your login location has voice disabled), your friends list won't sync. sendFriendsListUpdates(); - if(mSessionTerminateRequested || !mVoiceEnabled) + if(mSessionTerminateRequested || !mVoiceEnabled && mIsInitialized) { // TODO: Question: Is this the right way out of this state? setState(stateSessionTerminated); @@ -1372,7 +1365,7 @@ void LLVivoxVoiceClient::stateMachine() } // joinedAudioSession() will transition from here to stateSessionJoined. - if(!mVoiceEnabled) + if(!mVoiceEnabled && mIsInitialized) { // User bailed out during connect -- jump straight to teardown. setState(stateSessionTerminated); @@ -1419,7 +1412,7 @@ void LLVivoxVoiceClient::stateMachine() notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED); } - else if(!mVoiceEnabled) + else if(!mVoiceEnabled && mIsInitialized) { // User bailed out during connect -- jump straight to teardown. setState(stateSessionTerminated); @@ -1439,7 +1432,7 @@ void LLVivoxVoiceClient::stateMachine() //MARK: stateRunning case stateRunning: // steady state // Disabling voice or disconnect requested. - if(!mVoiceEnabled || mSessionTerminateRequested) + if(!mVoiceEnabled && mIsInitialized || mSessionTerminateRequested) { leaveAudioSession(); } @@ -1487,8 +1480,7 @@ void LLVivoxVoiceClient::stateMachine() sendPositionalUpdate(); } - // Now that audio module is fully initialized, check for actual mVoiceEnabled value - updateSettings(); + mIsInitialized = true; } break; @@ -1522,7 +1514,7 @@ void LLVivoxVoiceClient::stateMachine() // Always reset the terminate request flag when we get here. mSessionTerminateRequested = false; - if(mVoiceEnabled && !mRelogRequested) + if((mVoiceEnabled || !mIsInitialized) && !mRelogRequested) { // Just leaving a channel, go back to stateNoChannel (the "logged in but have no channel" state). setState(stateNoChannel); @@ -1550,7 +1542,7 @@ void LLVivoxVoiceClient::stateMachine() mAccountHandle.clear(); cleanUp(); - if(mVoiceEnabled && !mRelogRequested) + if((mVoiceEnabled || !mIsInitialized) && !mRelogRequested) { // User was logged out, but wants to be logged in. Send a new login request. setState(stateNeedsLogin); diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index 1142a1a49c..f2a3a7d3dd 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -741,6 +741,8 @@ private: std::string mRenderDevice; bool mCaptureDeviceDirty; bool mRenderDeviceDirty; + + bool mIsInitialized; bool checkParcelChanged(bool update = false); -- cgit v1.2.3 From d1f45654d91762af4e614de2156304d7acad6619 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 7 Nov 2012 18:45:02 +0200 Subject: CHUI-473, CHUI-482 FIXED (Clicking on nearby chat toast to open Conversation floater does not show Nearby Chat conversation selected in list; Nearby chat conversation is not selected in list by default when it is the only conversation ): implement. new logic in LLIMFloaterContainer for the syncronous select the conv. list's item and corresponding convers. floater; removed floater selecting from conv. items; fixed bug with item select --- indra/llui/llfolderviewitem.cpp | 2 +- indra/newview/llconversationview.cpp | 76 +++++++++++++--------------------- indra/newview/llconversationview.h | 6 ++- indra/newview/llimconversation.cpp | 23 +++++++++- indra/newview/llimconversation.h | 2 + indra/newview/llimfloater.cpp | 13 ------ indra/newview/llimfloater.h | 3 +- indra/newview/llimfloatercontainer.cpp | 41 ++++++++++++++++++ indra/newview/llimfloatercontainer.h | 2 + indra/newview/llnearbychat.cpp | 18 +++----- indra/newview/llnearbychat.h | 1 - 11 files changed, 107 insertions(+), 80 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 7c63cad1b7..21fb9bff90 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -410,8 +410,8 @@ void LLFolderViewItem::selectItem(void) { if (mIsSelected == FALSE) { - getViewModelItem()->selectItem(); mIsSelected = TRUE; + getViewModelItem()->selectItem(); } } diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 2d3a008bf4..34b5976e3e 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -203,6 +203,17 @@ void LLConversationViewSession::draw() LLView::draw(); } +BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem()); + LLUUID session_id = item? item->getUUID() : LLUUID(); + + (LLFloaterReg::getTypedInstance<LLIMFloaterContainer>("im_container"))-> + selectConversationPair(session_id, false); + + return LLFolderViewFolder::handleMouseDown(x, y, mask); +} + // virtual S32 LLConversationViewSession::arrange(S32* width, S32* height) { @@ -233,29 +244,6 @@ void LLConversationViewSession::toggleOpen() } } -void LLConversationViewSession::selectItem() -{ - - LLConversationItem* item = dynamic_cast<LLConversationItem*>(mViewModelItem); - LLFloater* session_floater = LLIMConversation::getConversation(item->getUUID()); - LLMultiFloater* host_floater = session_floater->getHost(); - - if (host_floater == mContainer) - { - // Always expand the message pane if the panel is hosted by the container - mContainer->collapseMessagesPane(false); - // Switch to the conversation floater that is being selected - mContainer->selectFloater(session_floater); - } - - // Set the focus on the selected floater - session_floater->setFocus(TRUE); - // Store the active session - LLIMFloaterContainer::getInstance()->setSelectedSession(item->getUUID()); - - - LLFolderViewItem::selectItem(); -} void LLConversationViewSession::toggleMinimizedMode(bool is_minimized) { @@ -441,31 +429,6 @@ void LLConversationViewParticipant::draw() LLView::draw(); } -void LLConversationViewParticipant::selectItem() -{ - LLConversationItem* vmi = this->getParentFolder() ? static_cast<LLConversationItem*>(this->getParentFolder()->getViewModelItem()) : NULL; - LLIMFloaterContainer* container = LLIMFloaterContainer::getInstance(); - LLFloater* session_floater; - - if(vmi) - { - session_floater = LLIMConversation::getConversation(vmi->getUUID()); - - //Only execute when switching floaters (conversations) - if(vmi->getUUID() != container->getSelectedSession()) - { - container->selectFloater(session_floater); - // Store the active session - container->setSelectedSession(vmi->getUUID()); - } - - //Redirect focus to the conversation floater - session_floater->setFocus(TRUE); - } - - LLFolderViewItem::selectItem(); -} - void LLConversationViewParticipant::refresh() { // Refresh the participant view from its model data @@ -514,6 +477,23 @@ void LLConversationViewParticipant::onMouseLeave(S32 x, S32 y, MASK mask) LLFolderViewItem::onMouseLeave(x, y, mask); } +BOOL LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + LLConversationItem* item = NULL; + LLConversationViewSession* session_widget = + dynamic_cast<LLConversationViewSession *>(this->getParentFolder()); + if (session_widget) + { + item = dynamic_cast<LLConversationItem*>(session_widget->getViewModelItem()); + } + LLUUID session_id = item? item->getUUID() : LLUUID(); + + (LLFloaterReg::getTypedInstance<LLIMFloaterContainer>("im_container"))-> + selectConversationPair(session_id, false); + + return LLFolderViewItem::handleMouseDown(x, y, mask); +} + S32 LLConversationViewParticipant::getLabelXPos() { return mAvatarIcon->getRect().mRight + mIconPad; diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index aeca747260..ac91d2d26f 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -60,10 +60,10 @@ protected: public: virtual ~LLConversationViewSession(); - virtual void selectItem(); /*virtual*/ BOOL postBuild(); /*virtual*/ void draw(); + /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); /*virtual*/ S32 arrange(S32* width, S32* height); @@ -117,11 +117,13 @@ public: }; virtual ~LLConversationViewParticipant( void ) { } - void selectItem(); + bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } virtual void refresh(); void addToFolder(LLFolderViewFolder* folder); + /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + void onMouseEnter(S32 x, S32 y, MASK mask); void onMouseLeave(S32 x, S32 y, MASK mask); diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 833feff3c4..827059513f 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -128,6 +128,22 @@ void LLIMConversation::setVisible(BOOL visible) setFocus(visible); } +/*virtual*/ +void LLIMConversation::setFocus(BOOL focus) +{ + LLTransientDockableFloater::setFocus(focus); + + //Redirect focus to input editor + if (focus) + { + updateMessages(); + + if (mInputEditor) + { + mInputEditor->setFocus(TRUE); + } + } +} void LLIMConversation::addToHost(const LLUUID& session_id) @@ -247,7 +263,6 @@ void LLIMConversation::enableDisableCallBtn() && mSession->mCallBackEnabled); } - void LLIMConversation::onFocusReceived() { setBackgroundOpaque(true); @@ -258,6 +273,12 @@ void LLIMConversation::onFocusReceived() } LLTransientDockableFloater::onFocusReceived(); + + LLIMFloaterContainer* container = LLFloaterReg::getTypedInstance<LLIMFloaterContainer>("im_container"); + if (container) + { + container->selectConversationPair(mSessionID, true); + } } void LLIMConversation::onFocusLost() diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index bff4cb4a31..d1e2bfff55 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -79,7 +79,9 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void draw(); /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ void setFocus(BOOL focus); + virtual void updateMessages() {} protected: diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 3545b8ff18..2ff883da67 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -671,19 +671,6 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock) } } -void LLIMFloater::setFocus(BOOL focusFlag) -{ - LLTransientDockableFloater::setFocus(focusFlag); - - //Redirect focus to input editor - if (focusFlag) - { - updateMessages(); - mInputEditor->setFocus(TRUE); - } - -} - void LLIMFloater::setVisible(BOOL visible) { LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 6c69ed3462..1fae3cff50 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -65,7 +65,6 @@ public: // LLView overrides /*virtual*/ BOOL postBuild(); - /*virtual*/ void setFocus(BOOL focusFlag); /*virtual*/ void setVisible(BOOL visible); /*virtual*/ BOOL getVisible(); // Check typing timeout timer. @@ -86,7 +85,7 @@ public: void sessionInitReplyReceived(const LLUUID& im_session_id); // get new messages from LLIMModel - void updateMessages(); + /*virtual*/ void updateMessages(); void reloadMessages(); static void onSendMsg(LLUICtrl*, void*); void sendMsgFromInputEditor(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index af43b1ac38..c2ad94c423 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -1091,6 +1091,47 @@ void LLIMFloaterContainer::selectConversation(const LLUUID& session_id) } } +// Synchronous select the conversation item and the conversation floater +BOOL LLIMFloaterContainer::selectConversationPair(const LLUUID& session_id, bool select_widget) +{ + BOOL handled = TRUE; + + /* widget processing */ + if (select_widget) + { + LLFolderViewItem* widget = mConversationsWidgets[session_id]; + if (widget && widget->getParentFolder()) + { + widget->getParentFolder()->setSelection(widget, FALSE, FALSE); + } + } + + /* floater processing */ + + if (session_id != getSelectedSession()) + { + // Store the active session + setSelectedSession(session_id); + + LLIMConversation* session_floater = LLIMConversation::getConversation(session_id); + + if (session_floater->getHost()) + { + // Always expand the message pane if the panel is hosted by the container + collapseMessagesPane(false); + // Switch to the conversation floater that is being selected + selectFloater(session_floater); + } + + // Set the focus on the selected floater + if (!session_floater->hasFocus()) + { + session_floater->setFocus(TRUE); + } + } + + return handled; +} void LLIMFloaterContainer::setTimeNow(const LLUUID& session_id, const LLUUID& participant_id) { diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 05ea94019b..25387fe83b 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -68,6 +68,8 @@ public: void showConversation(const LLUUID& session_id); void selectConversation(const LLUUID& session_id); + BOOL selectConversationPair(const LLUUID& session_id, bool select_widget); + /*virtual*/ void tabClose(); static LLFloater* getCurrentVoiceFloater(); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index d1c7c6bfd7..a30d8b685e 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -195,8 +195,13 @@ BOOL LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask) //background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. if(mChatHistory) + { mChatHistory->setFocus(TRUE); - return LLPanel::handleMouseDown(x, y, mask); + } + + BOOL handled = LLPanel::handleMouseDown(x, y, mask); + setFocus(handled); + return handled; } void LLNearbyChat::reloadMessages() @@ -270,17 +275,6 @@ void LLNearbyChat::removeScreenChat() } } -void LLNearbyChat::setFocus(BOOL focusFlag) -{ - LLTransientDockableFloater::setFocus(focusFlag); - - //Redirect focus to input editor - if (focusFlag) - { - mInputEditor->setFocus(TRUE); - } - -} void LLNearbyChat::setVisible(BOOL visible) { diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index b155fd3c26..11346a313c 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -52,7 +52,6 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void setFocus(BOOL focusFlag); /*virtual*/ void setVisible(BOOL visible); void loadHistory(); -- cgit v1.2.3 From bfb22638f865c2270fad95c35eff273b134772e3 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Wed, 7 Nov 2012 14:12:58 -0800 Subject: CHUI-514: Updating to Leo's latest icon batch. --- .../default/textures/icons/Conv_toolbar_add_person.png | Bin 322 -> 373 bytes .../default/textures/icons/Conv_toolbar_arrow_ne.png | Bin 301 -> 215 bytes .../default/textures/icons/Conv_toolbar_arrow_sw.png | Bin 293 -> 211 bytes .../skins/default/textures/icons/Conv_toolbar_close.png | Bin 262 -> 275 bytes .../default/textures/icons/Conv_toolbar_collapse.png | Bin 663 -> 345 bytes .../default/textures/icons/Conv_toolbar_expand.png | Bin 662 -> 342 bytes .../default/textures/icons/Conv_toolbar_hang_up.png | Bin 460 -> 459 bytes .../default/textures/icons/Conv_toolbar_open_call.png | Bin 485 -> 366 bytes .../skins/default/textures/icons/Conv_toolbar_plus.png | Bin 195 -> 144 bytes .../skins/default/textures/icons/Conv_toolbar_sort.png | Bin 196 -> 230 bytes .../skins/default/textures/icons/nearby_chat_icon.png | Bin 553 -> 399 bytes 11 files changed, 0 insertions(+), 0 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png index f024c733f3..0631f16f3b 100755 Binary files a/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png and b/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png index a19e720d42..578482f5ed 100755 Binary files a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png and b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png index 7f3f42639d..7676131790 100755 Binary files a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png and b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png index 25a939d7f5..d009c8f446 100755 Binary files a/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png and b/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png index 82baabde47..8d82960e28 100755 Binary files a/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png and b/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png index 7d64abb042..f718d3fc60 100755 Binary files a/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png and b/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png index f0da962c2d..315e2c581a 100755 Binary files a/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png and b/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png index 0db001dcdb..732ab02a20 100755 Binary files a/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png and b/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png index 0cf7edc2d4..25a32cb2ba 100755 Binary files a/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png and b/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png index a0c15a6d3e..08debeb91f 100755 Binary files a/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png and b/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png differ diff --git a/indra/newview/skins/default/textures/icons/nearby_chat_icon.png b/indra/newview/skins/default/textures/icons/nearby_chat_icon.png index 48c2379133..5ac4258b9d 100644 Binary files a/indra/newview/skins/default/textures/icons/nearby_chat_icon.png and b/indra/newview/skins/default/textures/icons/nearby_chat_icon.png differ -- cgit v1.2.3 From 626d07daa1219e6834bf371547cc8c4852840fb9 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 7 Nov 2012 15:36:16 -0800 Subject: CHUI-468 : WIP : Clean up LLAvatarList and all sorting code left over in LLParticipantList --- indra/newview/app_settings/settings.xml | 11 --- indra/newview/llimfloatercontainer.cpp | 2 +- indra/newview/llparticipantlist.cpp | 126 +------------------------------- indra/newview/llparticipantlist.h | 37 +--------- 4 files changed, 4 insertions(+), 172 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0537487ca3..5694cb9f30 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12395,17 +12395,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>SpeakerParticipantDefaultOrder</key> - <map> - <key>Comment</key> - <string>Order for displaying speakers in voice controls. 0 = alphabetical. 1 = recent.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <integer>1</integer> - </map> <key>SpeakerParticipantRemoveDelay</key> <map> <key>Comment</key> diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 4b992a2e0f..c0465c6956 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -1177,7 +1177,7 @@ LLConversationItem* LLIMFloaterContainer::addConversationListItem(const LLUUID& LLSpeakerMgr* speaker_manager = (is_nearby_chat ? (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()) : LLIMModel::getInstance()->getSpeakerManager(uuid)); if (speaker_manager) { - item = new LLParticipantList(speaker_manager, getRootViewModel(), true, false); + item = new LLParticipantList(speaker_manager, getRootViewModel()); } if (!item) { diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index e6eef56628..0124f8a143 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -187,14 +187,9 @@ private: uuid_set_t mAvalineCallers; }; -LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, - LLFolderViewModelInterface& root_view_model, - bool use_context_menu/* = true*/, - bool exclude_agent /*= true*/, - bool can_toggle_icons /*= true*/) : +LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLFolderViewModelInterface& root_view_model) : LLConversationItemSession(data_source->getSessionID(), root_view_model), mSpeakerMgr(data_source), - mExcludeAgent(exclude_agent), mValidateSpeakerCallback(NULL) { @@ -215,33 +210,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, mSpeakerMgr->addListener(mSpeakerUpdateListener, "update_speaker"); setSessionID(mSpeakerMgr->getSessionID()); - /* - if (mAvatarList) - { - mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData")); - LL_DEBUGS("SpeakingIndicator") << "Set session for speaking indicators: " << mSpeakerMgr->getSessionID() << LL_ENDL; - mAvatarList->setSessionID(mSpeakerMgr->getSessionID()); - mAvatarListDoubleClickConnection = mAvatarList->setItemDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, _1)); - mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2)); - // Set onAvatarListDoubleClicked as default on_return action. - mAvatarListReturnConnection = mAvatarList->setReturnCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); - - if (use_context_menu) - { - mAvatarList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); - } - else - { - mAvatarList->setContextMenu(NULL); - } - if (use_context_menu && can_toggle_icons) - { - mAvatarList->setShowIcons("ParticipantListShowIcons"); - mAvatarListToggleIconsConnection = gSavedSettings.getControl("ParticipantListShowIcons")->getSignal()->connect(boost::bind(&LLAvatarList::toggleIcons, mAvatarList)); - } - } - */ //Lets fill avatarList with existing speakers LLSpeakerMgr::speaker_list_t speaker_list; mSpeakerMgr->getSpeakerList(&speaker_list, true); @@ -284,21 +253,6 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLParticipantList::~LLParticipantList() { - /* - if (mAvatarList) - { - mAvatarListDoubleClickConnection.disconnect(); - mAvatarListRefreshConnection.disconnect(); - mAvatarListReturnConnection.disconnect(); - mAvatarListToggleIconsConnection.disconnect(); - } - - if (mAvatarList) - { - mAvatarList->setContextMenu(NULL); - mAvatarList->setComparator(NULL); - } - */ delete mAvalineUpdater; } @@ -429,24 +383,7 @@ void LLParticipantList::onAvalineCallerRemoved(const LLUUID& participant_id) mSpeakerMgr->removeAvalineSpeaker(participant_id); } -/* -void LLParticipantList::setSortOrder(EParticipantSortOrder order) -{ - const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder"); - - if ( speaker_sort_order != order ) - { - gSavedSettings.setU32("SpeakerParticipantDefaultOrder", (U32)order); - sort(); - } -} -const LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder() const -{ - const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder"); - return EParticipantSortOrder(speaker_sort_order); -} -*/ void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb) { mValidateSpeakerCallback = cb; @@ -455,15 +392,6 @@ void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t c void LLParticipantList::update() { mSpeakerMgr->update(true); - - /* - // Need to resort the participant list if it's in sort by recent speaker order. - if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder()) - { - // Resort avatar list - sort(); - } - */ } bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) @@ -528,8 +456,6 @@ bool LLParticipantList::onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> e } } // *TODO : do we have to fire an event so that LLIMConversation::refreshConversation() gets called - // apply changes immediately - //onAvatarListRefreshed(mAvatarList, LLSD()); } } return true; @@ -548,44 +474,9 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event return true; } -/* -void LLParticipantList::sort() -{ - // *TODO : Merov : Need to plan for sort() for LLConversationModel - if ( !mAvatarList ) - return; - - switch ( getSortOrder() ) - { - case E_SORT_BY_NAME : - // if mExcludeAgent == true , then no need to keep agent on top of the list - if(mExcludeAgent) - { - mAvatarList->sortByName(); - } - else - { - mAvatarList->setComparator(&AGENT_ON_TOP_NAME_COMPARATOR); - mAvatarList->sort(); - } - break; - case E_SORT_BY_RECENT_SPEAKERS: - if (mSortByRecentSpeakers.isNull()) - mSortByRecentSpeakers = new LLAvatarItemRecentSpeakerComparator(*this); - mAvatarList->setComparator(mSortByRecentSpeakers.get()); - mAvatarList->sort(); - break; - default : - llwarns << "Unrecognized sort order for " << mAvatarList->getName() << llendl; - return; - } -} -*/ - void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) { // Do not add if already in there or excluded for some reason - if (mExcludeAgent && gAgent.getID() == avatar_id) return; if (findParticipant(avatar_id)) return; bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(avatar_id); @@ -599,29 +490,16 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name); participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.mDisplayName , avatar_id, mRootViewModel); participant->fetchAvatarName(); - /* - if (mAvatarList) - { - mAvatarList->getIDs().push_back(avatar_id); - mAvatarList->setDirty(); - } - */ } else { std::string display_name = LLVoiceClient::getInstance()->getDisplayName(avatar_id); // Create a participant view model instance participant = new LLConversationItemParticipant(display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name, avatar_id, mRootViewModel); - /* - if (mAvatarList) - { - mAvatarList->addAvalineItem(avatar_id, mSpeakerMgr->getSessionID(), display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name); - } - */ mAvalineUpdater->watchAvalineCaller(avatar_id); } - // *TODO : Merov : need to update the online/offline status of the participant. + // *TODO : Need to update the online/offline status of the participant // Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id)) // Add the participant model to the session's children list diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index f4469b03f4..9332634c31 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -43,19 +43,9 @@ public: typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t; - LLParticipantList(LLSpeakerMgr* data_source, - LLFolderViewModelInterface& root_view_model, - bool use_context_menu = true, - bool exclude_agent = true, - bool can_toggle_icons = true); + LLParticipantList(LLSpeakerMgr* data_source, LLFolderViewModelInterface& root_view_model); ~LLParticipantList(); - enum EParticipantSortOrder - { - E_SORT_BY_NAME = 0, - E_SORT_BY_RECENT_SPEAKERS = 1, - }; - /** * Adds specified avatar ID to the existing list if it is not Agent's ID * @@ -63,12 +53,6 @@ public: */ void addAvatarIDExceptAgent(const LLUUID& avatar_id); - /** - * Set and sort Avatarlist by given order - */ - //void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME); - //const EParticipantSortOrder getSortOrder() const; - /** * Refreshes the participant list. */ @@ -94,11 +78,6 @@ protected: bool onSpeakerUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); - /** - * Sorts the Avatarlist by stored order - */ - //void sort(); - /** * List of listeners implementing LLOldEvents::LLSimpleListener. * There is no way to handle all the events in one listener as LLSpeakerMgr registers @@ -181,20 +160,6 @@ private: LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener; LLPointer<SpeakerMuteListener> mSpeakerMuteListener; - /** - * This field manages an adding a new avatar_id in the mAvatarList - * If true, then agent_id wont be added into mAvatarList - * Also by default this field is controlling a sort procedure, @c sort() - */ - bool mExcludeAgent; - - // boost::connections - boost::signals2::connection mAvatarListDoubleClickConnection; - boost::signals2::connection mAvatarListRefreshConnection; - boost::signals2::connection mAvatarListReturnConnection; - boost::signals2::connection mAvatarListToggleIconsConnection; - -// LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers; validate_speaker_callback_t mValidateSpeakerCallback; LLAvalineUpdater* mAvalineUpdater; }; -- cgit v1.2.3 From 7701d421e53da63731d969f66d743792fe72976f Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Wed, 7 Nov 2012 16:48:45 -0800 Subject: CHUI-484: Ensuring that the busy/do-no-disturb message is sent when the user is in the busy/do-not-disturb mode. --- indra/newview/llviewermessage.cpp | 40 +++++++++++++-------------------------- indra/newview/llviewermessage.h | 1 - 2 files changed, 13 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 775280ca34..c5d25ebd1b 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -179,6 +179,8 @@ const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = FALSE // TeleportYourAgent }; +static void busy_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id = LLUUID::null); + bool friendship_offer_callback(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); @@ -2358,12 +2360,11 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) BOOL is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat) // object IMs contain sender object id in session_id (STORM-1209) || dialog == IM_FROM_TASK && LLMuteList::getInstance()->isMuted(session_id); - BOOL is_linden = LLMuteList::getInstance()->isLinden(name); BOOL is_owned_by_me = FALSE; BOOL is_friend = (LLAvatarTracker::instance().getBuddyInfo(from_id) == NULL) ? false : true; BOOL accept_im_from_only_friend = gSavedSettings.getBOOL("VoiceCallsFriendsOnly"); - chat.mMuted = is_muted && !is_linden; + chat.mMuted = is_muted; chat.mFromID = from_id; chat.mFromName = name; chat.mSourceType = (from_id.isNull() || (name == std::string(SYSTEM_FROM))) ? CHAT_SOURCE_SYSTEM : CHAT_SOURCE_AGENT; @@ -2401,7 +2402,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // do nothing -- don't distract newbies in // Prelude with global IMs } - else if (offline == IM_ONLINE && !is_linden && is_busy && name != SYSTEM_FROM) + else if (offline == IM_ONLINE && is_busy && name != SYSTEM_FROM) { // return a standard "busy" message, but only do it to online IM // (i.e. not other auto responses and not store-and-forward IM) @@ -2409,21 +2410,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) { // if there is not a panel for this conversation (i.e. it is a new IM conversation // initiated by the other party) then... - std::string my_name; - LLAgentUI::buildFullname(my_name); - std::string response = gSavedPerAccountSettings.getString("BusyModeResponse"); - pack_instant_message( - gMessageSystem, - gAgent.getID(), - FALSE, - gAgent.getSessionID(), - from_id, - my_name, - response, - IM_ONLINE, - IM_BUSY_AUTO_RESPONSE, - session_id); - gAgent.sendReliableMessage(); + busy_message(msg, from_id, session_id); } // now store incoming IM in chat history @@ -2484,7 +2471,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) mute_im = true; } - if (!mute_im || is_linden) + if (!mute_im) { gIMMgr->addMessage( session_id, @@ -2658,11 +2645,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) break; case IM_GROUP_INVITATION: { - //if (!is_linden && (is_busy || is_muted)) - if ((is_busy || is_muted)) + if (is_busy || is_muted) { - LLMessageSystem *msg = gMessageSystem; - busy_message(msg,from_id); + busy_message(msg, from_id); } else { @@ -2974,7 +2959,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } else if (is_busy) { - busy_message(msg,from_id); + busy_message(msg, from_id); } else { @@ -3261,7 +3246,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } } -void busy_message (LLMessageSystem* msg, LLUUID from_id) +static void busy_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id) { if (gAgent.getBusy()) { @@ -3269,7 +3254,7 @@ void busy_message (LLMessageSystem* msg, LLUUID from_id) LLAgentUI::buildFullname(my_name); std::string response = gSavedPerAccountSettings.getString("BusyModeResponse"); pack_instant_message( - gMessageSystem, + msg, gAgent.getID(), FALSE, gAgent.getSessionID(), @@ -3277,7 +3262,8 @@ void busy_message (LLMessageSystem* msg, LLUUID from_id) my_name, response, IM_ONLINE, - IM_BUSY_AUTO_RESPONSE); + IM_BUSY_AUTO_RESPONSE, + session_id); gAgent.sendReliableMessage(); } } diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 594c22ed9c..b298f0060b 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -67,7 +67,6 @@ enum InventoryOfferResponse BOOL can_afford_transaction(S32 cost); void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_group = FALSE, S32 trx_type = TRANS_GIFT, const std::string& desc = LLStringUtil::null); -void busy_message (LLMessageSystem* msg, LLUUID from_id); void process_logout_reply(LLMessageSystem* msg, void**); void process_layer_data(LLMessageSystem *mesgsys, void **user_data); -- cgit v1.2.3 From 87c94625d39a72ce8b19b2c295c3824fb45717a3 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 7 Nov 2012 16:49:03 -0800 Subject: CHUI-468 : Fixed. Final clean up of LLParticipantList, including dependencies. --- indra/newview/llparticipantlist.cpp | 112 +----------------------------------- indra/newview/llparticipantlist.h | 7 +-- 2 files changed, 2 insertions(+), 117 deletions(-) (limited to 'indra') diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 0124f8a143..9a4d1166db 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -1,6 +1,6 @@ /** * @file llparticipantlist.cpp - * @brief LLParticipantList widgets of a conversation list + * @brief LLParticipantList : model of a conversation session with added speaker events handling * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code @@ -26,22 +26,11 @@ #include "llviewerprecompiledheaders.h" -// common includes -#include "lltrans.h" -#include "llavataractions.h" #include "llavatarnamecache.h" -#include "llavatarname.h" -#include "llagent.h" - #include "llimview.h" #include "llimfloatercontainer.h" -#include "llpanelpeoplemenus.h" -#include "llnotificationsutil.h" #include "llparticipantlist.h" #include "llspeakers.h" -#include "llviewercontrol.h" -#include "llviewermenu.h" -#include "llvoiceclient.h" //LLParticipantList retrieves add, clear and remove events and updates view accordingly #if LL_MSVC @@ -256,105 +245,6 @@ LLParticipantList::~LLParticipantList() delete mAvalineUpdater; } -/* -void LLParticipantList::onAvatarListDoubleClicked(LLUICtrl* ctrl) -{ - LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(ctrl); - if(!item) - { - return; - } - - LLUUID clicked_id = item->getAvatarId(); - - if (clicked_id.isNull() || clicked_id == gAgent.getID()) - return; - - LLAvatarActions::startIM(clicked_id); -} -*/ -/* -void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) -{ - LLAvatarList* list = dynamic_cast<LLAvatarList*>(ctrl); - const std::string moderator_indicator(LLTrans::getString("IM_moderator_label")); - const std::size_t moderator_indicator_len = moderator_indicator.length(); - - // Firstly remove moderators indicator - std::set<LLUUID>::const_iterator - moderator_list_it = mModeratorToRemoveList.begin(), - moderator_list_end = mModeratorToRemoveList.end(); - for (;moderator_list_it != moderator_list_end; ++moderator_list_it) - { - LLAvatarListItem* item = (list ? dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it)) : NULL); - if ( item ) - { - std::string name = item->getAvatarName(); - std::string tooltip = item->getAvatarToolTip(); - size_t found = name.find(moderator_indicator); - if (found != std::string::npos) - { - name.erase(found, moderator_indicator_len); - item->setAvatarName(name); - } - found = tooltip.find(moderator_indicator); - if (found != tooltip.npos) - { - tooltip.erase(found, moderator_indicator_len); - item->setAvatarToolTip(tooltip); - } - } - setParticipantIsModerator(*moderator_list_it,false); - } - - mModeratorToRemoveList.clear(); - - // Add moderators indicator - moderator_list_it = mModeratorList.begin(); - moderator_list_end = mModeratorList.end(); - for (;moderator_list_it != moderator_list_end; ++moderator_list_it) - { - LLAvatarListItem* item = (list ? dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it)) : NULL); - if ( item ) - { - std::string name = item->getAvatarName(); - std::string tooltip = item->getAvatarToolTip(); - size_t found = name.find(moderator_indicator); - if (found == std::string::npos) - { - name += " "; - name += moderator_indicator; - item->setAvatarName(name); - } - found = tooltip.find(moderator_indicator); - if (found == std::string::npos) - { - tooltip += " "; - tooltip += moderator_indicator; - item->setAvatarToolTip(tooltip); - } - } - setParticipantIsModerator(*moderator_list_it,true); - } - - // update voice mute state of all items. See EXT-7235 - LLSpeakerMgr::speaker_list_t speaker_list; - - // Use also participants which are not in voice session now (the second arg is TRUE). - // They can already have mModeratorMutedVoice set from the previous voice session - // and LLSpeakerVoiceModerationEvent will not be sent when speaker manager is updated next time. - mSpeakerMgr->getSpeakerList(&speaker_list, TRUE); - for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++) - { - const LLPointer<LLSpeaker>& speakerp = *it; - - if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) - { - setParticipantIsMuted(speakerp->mID, speakerp->mModeratorMutedVoice); - } - } -} -*/ /* Seems this method is not necessary after onAvalineCallerRemoved was implemented; diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 9332634c31..3a3ae76604 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -1,6 +1,6 @@ /** * @file llparticipantlist.h - * @brief LLParticipantList widgets of a conversation list + * @brief LLParticipantList : model of a conversation session with added speaker events handling * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code @@ -28,8 +28,6 @@ #define LL_PARTICIPANTLIST_H #include "llviewerprecompiledheaders.h" -#include "llevent.h" -#include "lllistcontextmenu.h" #include "llconversationmodel.h" class LLSpeakerMgr; @@ -135,9 +133,6 @@ protected: }; private: -// void onAvatarListDoubleClicked(LLUICtrl* ctrl); -// void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param); - void onAvalineCallerFound(const LLUUID& participant_id); void onAvalineCallerRemoved(const LLUUID& participant_id); -- cgit v1.2.3 From fa85e16d63b09326b9facb4850d50cd163f87bc7 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Wed, 7 Nov 2012 17:47:35 -0800 Subject: Removing unused code. --- indra/llmessage/lldbstrings.h | 12 --------- indra/llmessage/llinstantmessage.cpp | 17 +----------- indra/llmessage/llinstantmessage.h | 51 ------------------------------------ 3 files changed, 1 insertion(+), 79 deletions(-) (limited to 'indra') diff --git a/indra/llmessage/lldbstrings.h b/indra/llmessage/lldbstrings.h index 9bf1b3eda4..e23d17d5b6 100644 --- a/indra/llmessage/lldbstrings.h +++ b/indra/llmessage/lldbstrings.h @@ -156,18 +156,6 @@ const S32 DB_USER_SKILLS_BUF_SIZE = 255; const S32 DB_NV_NAME_STR_LEN = 128; const S32 DB_NV_NAME_BUF_SIZE = 129; -// votes.vote_text varchar(254) -const S32 DB_VOTE_TEXT_STR_LEN = 254; -const S32 DB_VOTE_TEXT_BUF_SIZE = 255; - -// vpte type text varchar(9) -const S32 DB_VOTE_TYPE_STR_LEN = 9; -const S32 DB_VOTE_TYPE_BUF_SIZE = 10; - -// vote result text -const S32 DB_VOTE_RESULT_BUF_LEN = 8; -const S32 DB_VOTE_RESULT_BUF_SIZE = 9; - // user_start_location.location_name varchar(254) const S32 DB_START_LOCATION_STR_LEN = 254; const S32 DB_START_LOCATION_BUF_SIZE = 255; diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp index d68e0c423e..b0275c161b 100644 --- a/indra/llmessage/llinstantmessage.cpp +++ b/indra/llmessage/llinstantmessage.cpp @@ -43,14 +43,6 @@ const U8 IM_ONLINE = 0; const U8 IM_OFFLINE = 1; -const S32 VOTE_YES = 1; -const S32 VOTE_NO = 0; -const S32 VOTE_ABSTAIN = -1; - -const S32 VOTE_MAJORITY = 0; -const S32 VOTE_SUPER_MAJORITY = 1; -const S32 VOTE_UNANIMOUS = 2; - const char EMPTY_BINARY_BUCKET[] = ""; const S32 EMPTY_BINARY_BUCKET_SIZE = 1; const U32 NO_TIMESTAMP = 0; @@ -69,7 +61,6 @@ LLIMInfo::LLIMInfo() : mViewerThinksToIsOnline(false), mIMType(IM_NOTHING_SPECIAL), mTimeStamp(0), - mSource(IM_FROM_SIM), mTTL(IM_TTL) { } @@ -88,7 +79,6 @@ LLIMInfo::LLIMInfo( LLSD data, U8 offline, U32 timestamp, - EIMSource source, S32 ttl) : mFromID(from_id), mFromGroup(from_group), @@ -104,14 +94,12 @@ LLIMInfo::LLIMInfo( mName(name), mMessage(message), mData(data), - mSource(source), mTTL(ttl) { } -LLIMInfo::LLIMInfo(LLMessageSystem* msg, EIMSource source, S32 ttl) : +LLIMInfo::LLIMInfo(LLMessageSystem* msg, S32 ttl) : mViewerThinksToIsOnline(false), - mSource(source), mTTL(ttl) { unpackMessageBlock(msg); @@ -326,7 +314,6 @@ LLSD im_info_to_llsd(LLPointer<LLIMInfo> im_info) param_message["region_id"] = im_info->mRegionID; param_message["position"] = ll_sd_from_vector3(im_info->mPosition); param_message["data"] = im_info->mData; - param_message["source"]= im_info->mSource; param_message["ttl"] = im_info->mTTL; LLSD param_agent; @@ -359,7 +346,6 @@ LLPointer<LLIMInfo> llsd_to_im_info(const LLSD& im_info_sd) param_message["data"], (U8) param_message["offline"].asInteger(), (U32) param_message["timestamp"].asInteger(), - (EIMSource)param_message["source"].asInteger(), param_message["ttl"].asInteger()); return im_info; @@ -381,7 +367,6 @@ LLPointer<LLIMInfo> LLIMInfo::clone() mData, mOffline, mTimeStamp, - mSource, mTTL); } diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index e0dae376b4..12e4e79475 100644 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -164,57 +164,9 @@ enum EInstantMessage }; -// Hooks for quickly hacking in experimental admin debug messages -// without needing to recompile the viewer -// *NOTE: This functionality has been moved to be a string based -// operation so that we don't even have to do a full recompile. This -// enumeration will be phased out soon. -enum EGodlikeRequest -{ - GOD_WANTS_NOTHING, - - // for requesting physics information about an object - GOD_WANTS_PHYSICS_INFO, - - // two unused requests that can be appropriated for debug - // purposes (no viewer recompile necessary) - GOD_WANTS_FOO, - GOD_WANTS_BAR, - - // to dump simulator terrain data to terrain.raw file - GOD_WANTS_TERRAIN_SAVE, - // to load simulator terrain data from terrain.raw file - GOD_WANTS_TERRAIN_LOAD, - - GOD_WANTS_TOGGLE_AVATAR_GEOMETRY, // HACK for testing new avatar geom - - // real-time telehub operations - GOD_WANTS_TELEHUB_INFO, - GOD_WANTS_CONNECT_TELEHUB, - GOD_WANTS_DELETE_TELEHUB, - GOD_WANTS_ADD_TELEHUB_SPAWNPOINT, - GOD_WANTS_REMOVE_TELEHUB_SPAWNPOINT, - -}; - -enum EIMSource -{ - IM_FROM_VIEWER, - IM_FROM_DATASERVER, - IM_FROM_SIM -}; - extern const U8 IM_ONLINE; extern const U8 IM_OFFLINE; -extern const S32 VOTE_YES; -extern const S32 VOTE_NO; -extern const S32 VOTE_ABSTAIN; - -extern const S32 VOTE_MAJORITY; -extern const S32 VOTE_SUPER_MAJORITY; -extern const S32 VOTE_UNANIMOUS; - extern const char EMPTY_BINARY_BUCKET[]; extern const S32 EMPTY_BINARY_BUCKET_SIZE; @@ -234,7 +186,6 @@ protected: public: LLIMInfo(LLMessageSystem* msg, - EIMSource source = IM_FROM_SIM, S32 ttl = IM_TTL); LLIMInfo( @@ -251,7 +202,6 @@ public: LLSD data, U8 offline, U32 timestamp, - EIMSource source, S32 ttl = IM_TTL); void packInstantMessage(LLMessageSystem* msg) const; @@ -274,7 +224,6 @@ public: std::string mMessage; LLSD mData; - EIMSource mSource; S32 mTTL; }; -- cgit v1.2.3 From 93f9c6991819f53ea03b36dff1af77bbd74ff43b Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 8 Nov 2012 17:00:42 +0200 Subject: CHUI-387 FIXED (Conversation toasts not shown for open conversations when conversation floater is in a minimized state or undocked conversation is minimized): added checking of the minimized state --- indra/newview/llimview.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d5f1e81933..11337c358f 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -121,7 +121,14 @@ void toast_callback(const LLSD& msg){ // Skip toasting if we have open window of IM with this session id LLIMFloater* open_im_floater = LLIMFloater::findInstance(msg["session_id"]); - if (open_im_floater && open_im_floater->isInVisibleChain() && open_im_floater->hasFocus()) + if ( + open_im_floater + && open_im_floater->isInVisibleChain() + && open_im_floater->hasFocus() + && !open_im_floater->isMinimized() + && !(open_im_floater->getHost() + && open_im_floater->getHost()->isMinimized()) + ) { return; } -- cgit v1.2.3 From c4eaaa3d6a08330863119d550d365315ba7526bb Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Thu, 8 Nov 2012 12:35:15 -0800 Subject: CHUI-484: Updating the code to rather than refer to it as Busy Mode, it now refers to it as Do Not Disturb mode. --- indra/llcharacter/llanimationstates.cpp | 4 +- indra/llcharacter/llanimationstates.h | 2 +- indra/llmessage/llinstantmessage.h | 4 +- .../newview/app_settings/settings_per_account.xml | 8 +-- indra/newview/llagent.cpp | 36 ++++------ indra/newview/llagent.h | 9 ++- indra/newview/llappearancemgr.cpp | 6 -- indra/newview/llavataractions.cpp | 8 +-- indra/newview/llfloaterpreference.cpp | 46 +++++------- indra/newview/llfloaterpreference.h | 8 +-- indra/newview/llimview.cpp | 8 +-- indra/newview/llinventorybridge.cpp | 21 ------ indra/newview/llnearbychathandler.cpp | 2 +- indra/newview/llviewermenu.cpp | 24 +++---- indra/newview/llviewermenu.h | 2 +- indra/newview/llviewermessage.cpp | 83 ++++++++++------------ indra/newview/llviewerwindow.cpp | 4 +- indra/newview/llvoavatar.cpp | 16 ++--- indra/newview/llvoavatar.h | 2 +- indra/newview/llvoicevivox.cpp | 6 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 4 +- .../newview/skins/default/xui/en/notifications.xml | 14 ++-- .../default/xui/en/panel_preferences_general.xml | 4 +- indra/newview/skins/default/xui/en/strings.xml | 8 +-- 24 files changed, 137 insertions(+), 192 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/llanimationstates.cpp b/indra/llcharacter/llanimationstates.cpp index 155226cf17..c16cae1bbc 100644 --- a/indra/llcharacter/llanimationstates.cpp +++ b/indra/llcharacter/llanimationstates.cpp @@ -46,7 +46,7 @@ LLUUID const ANIM_AGENT_BLOW_KISS ("db84829b-462c-ee83-1e27-9bbee66b LLUUID const ANIM_AGENT_BORED ("b906c4ba-703b-1940-32a3-0c7f7d791510"); LLUUID const ANIM_AGENT_BOW ("82e99230-c906-1403-4d9c-3889dd98daba"); LLUUID const ANIM_AGENT_BRUSH ("349a3801-54f9-bf2c-3bd0-1ac89772af01"); -LLUUID const ANIM_AGENT_BUSY ("efcf670c-2d18-8128-973a-034ebc806b67"); +LLUUID const ANIM_AGENT_DO_NOT_DISTURB ("efcf670c-2d18-8128-973a-034ebc806b67"); LLUUID const ANIM_AGENT_CLAP ("9b0c1c4e-8ac7-7969-1494-28c874c4f668"); LLUUID const ANIM_AGENT_COURTBOW ("9ba1c942-08be-e43a-fb29-16ad440efc50"); LLUUID const ANIM_AGENT_CROUCH ("201f3fdf-cb1f-dbec-201f-7333e328ae7c"); @@ -211,7 +211,7 @@ LLAnimationLibrary::LLAnimationLibrary() : mAnimMap[ANIM_AGENT_BORED]= mAnimStringTable.addString("express_bored"); mAnimMap[ANIM_AGENT_BOW]= mAnimStringTable.addString("bow"); mAnimMap[ANIM_AGENT_BRUSH]= mAnimStringTable.addString("brush"); - mAnimMap[ANIM_AGENT_BUSY]= mAnimStringTable.addString("busy"); + mAnimMap[ANIM_AGENT_DO_NOT_DISTURB]= mAnimStringTable.addString("busy"); mAnimMap[ANIM_AGENT_CLAP]= mAnimStringTable.addString("clap"); mAnimMap[ANIM_AGENT_COURTBOW]= mAnimStringTable.addString("courtbow"); mAnimMap[ANIM_AGENT_CROUCH]= mAnimStringTable.addString("crouch"); diff --git a/indra/llcharacter/llanimationstates.h b/indra/llcharacter/llanimationstates.h index aa6579ac8e..84185c3f92 100644 --- a/indra/llcharacter/llanimationstates.h +++ b/indra/llcharacter/llanimationstates.h @@ -56,7 +56,7 @@ extern const LLUUID ANIM_AGENT_BLOW_KISS; extern const LLUUID ANIM_AGENT_BORED; extern const LLUUID ANIM_AGENT_BOW; extern const LLUUID ANIM_AGENT_BRUSH; -extern const LLUUID ANIM_AGENT_BUSY; +extern const LLUUID ANIM_AGENT_DO_NOT_DISTURB; extern const LLUUID ANIM_AGENT_CLAP; extern const LLUUID ANIM_AGENT_COURTBOW; extern const LLUUID ANIM_AGENT_CROUCH; diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index 12e4e79475..db4a38ea9e 100644 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -115,8 +115,8 @@ enum EInstantMessage // viewer, since you can't IM an object yet. IM_FROM_TASK = 19, - // sent an IM to a busy user, this is the auto response - IM_BUSY_AUTO_RESPONSE = 20, + // sent an IM to a do not disturb user, this is the auto response + IM_DO_NOT_DISTURB_AUTO_RESPONSE = 20, // Shows the message in the console and chat history IM_CONSOLE_AND_CHAT_HISTORY = 21, diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 1f637ef3ff..8126e20b1b 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -1,9 +1,9 @@ <llsd> <map> - <key>BusyResponseChanged</key> + <key>DoNotDisturbResponseChanged</key> <map> <key>Comment</key> - <string>Does user's busy mode message differ from default?</string> + <string>Does user's do not disturb mode message differ from default?</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -11,10 +11,10 @@ <key>Value</key> <integer>0</integer> </map> - <key>BusyModeResponse</key> + <key>DoNotDisturbModeResponse</key> <map> <key>Comment</key> - <string>Auto response to instant messages while in busy mode.</string> + <string>Auto response to instant messages while in do not disturb mode.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index bb0dbc7ff0..cefd5c72e8 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -376,7 +376,7 @@ LLAgent::LLAgent() : mShowAvatar(TRUE), mFrameAgent(), - mIsBusy(FALSE), + mIsDoNotDisturb(false), mControlFlags(0x00000000), mbFlagsDirty(FALSE), @@ -1397,39 +1397,27 @@ BOOL LLAgent::getAFK() const } //----------------------------------------------------------------------------- -// setBusy() +// setDoNotDisturb() //----------------------------------------------------------------------------- -void LLAgent::setBusy() +void LLAgent::setDoNotDisturb(bool pIsDotNotDisturb) { - sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_START); - mIsBusy = TRUE; - if (gBusyMenu) - { - gBusyMenu->setLabel(LLTrans::getString("AvatarSetNotBusy")); - } - LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(true); -} + mIsDoNotDisturb = pIsDotNotDisturb; + EAnimRequest animRequest = (pIsDotNotDisturb ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); -//----------------------------------------------------------------------------- -// clearBusy() -//----------------------------------------------------------------------------- -void LLAgent::clearBusy() -{ - mIsBusy = FALSE; - sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_STOP); - if (gBusyMenu) + sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, animRequest); + if (gDoNotDisturbMenu) { - gBusyMenu->setLabel(LLTrans::getString("AvatarSetBusy")); + gDoNotDisturbMenu->setLabel(LLTrans::getString((pIsDotNotDisturb ? "AvatarSetAvailable" : "AvatarSetDoNotDisturb"))); } - LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(false); + LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(pIsDotNotDisturb); } //----------------------------------------------------------------------------- -// getBusy() +// isDoNotDisturb() //----------------------------------------------------------------------------- -BOOL LLAgent::getBusy() const +bool LLAgent::isDoNotDisturb() const { - return mIsBusy; + return mIsDoNotDisturb; } diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 99904e118c..daa15b0c1a 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -378,14 +378,13 @@ public: void sitDown(); //-------------------------------------------------------------------- - // Busy + // Do Not Disturb //-------------------------------------------------------------------- public: - void setBusy(); - void clearBusy(); - BOOL getBusy() const; + void setDoNotDisturb(bool pIsDoNotDisturb); + bool isDoNotDisturb() const; private: - BOOL mIsBusy; + bool mIsDoNotDisturb; //-------------------------------------------------------------------- // Grab diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 510abf198a..658da0205f 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1602,8 +1602,6 @@ void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, boo { gAgentWearables.setWearableOutfit(items, wearables, !append); } - -// dec_busy_count(); } static void remove_non_link_items(LLInventoryModel::item_array_t &items) @@ -2004,7 +2002,6 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego void LLAppearanceMgr::wearOutfitByName(const std::string& name) { LL_INFOS("Avatar") << self_av_string() << "Wearing category " << name << LL_ENDL; - //inc_busy_count(); LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; @@ -2044,8 +2041,6 @@ void LLAppearanceMgr::wearOutfitByName(const std::string& name) llwarns << "Couldn't find outfit " <<name<< " in wearOutfitByName()" << llendl; } - - //dec_busy_count(); } bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventoryItem *b) @@ -2967,7 +2962,6 @@ public: { llwarns << "Nothing fetched in category " << mComplete.front() << llendl; - //dec_busy_count(); gInventory.removeObserver(this); // lets notify observers that loading is finished. diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 13262efb3b..130428f3c0 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -386,12 +386,12 @@ void LLAvatarActions::showOnMap(const LLUUID& id) // static void LLAvatarActions::pay(const LLUUID& id) { - LLNotification::Params params("BusyModePay"); + LLNotification::Params params("DoNotDisturbModePay"); params.functor.function(boost::bind(&LLAvatarActions::handlePay, _1, _2, id)); - if (gAgent.getBusy()) + if (gAgent.isDoNotDisturb()) { - // warn users of being in busy mode during a transaction + // warn users of being in do not disturb mode during a transaction LLNotifications::instance().add(params); } else @@ -982,7 +982,7 @@ bool LLAvatarActions::handlePay(const LLSD& notification, const LLSD& response, S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { - gAgent.clearBusy(); + gAgent.setDoNotDisturb(false); } LLFloaterPayUtil::payDirectly(&give_money, avatar_id, /*is_group=*/false); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index c78a803bf3..b60af1a635 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -443,23 +443,23 @@ BOOL LLFloaterPreference::postBuild() getChild<LLComboBox>("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this)); - // if floater is opened before login set default localized busy message + // if floater is opened before login set default localized do not disturb message if (LLStartUp::getStartupState() < STATE_STARTED) { - gSavedPerAccountSettings.setString("BusyModeResponse", LLTrans::getString("BusyModeResponseDefault")); + gSavedPerAccountSettings.setString("DoNotDisturbModeResponse", LLTrans::getString("DoNotDisturbModeResponseDefault")); } return TRUE; } -void LLFloaterPreference::onBusyResponseChanged() +void LLFloaterPreference::onDoNotDisturbResponseChanged() { - // set "BusyResponseChanged" TRUE if user edited message differs from default, FALSE otherwise - bool busy_flag = - LLTrans::getString("BusyModeResponseDefault") - != getChild<LLUICtrl>("busy_response")->getValue().asString(); + // set "DoNotDisturbResponseChanged" TRUE if user edited message differs from default, FALSE otherwise + bool response_changed_flag = + LLTrans::getString("DoNotDisturbModeResponseDefault") + != getChild<LLUICtrl>("do_not_disturb_response")->getValue().asString(); - gSavedPerAccountSettings.setBOOL("BusyResponseChanged", busy_flag ); + gSavedPerAccountSettings.setBOOL("DoNotDisturbResponseChanged", response_changed_flag ); } LLFloaterPreference::~LLFloaterPreference() @@ -542,12 +542,8 @@ void LLFloaterPreference::apply() LLViewerMedia::setProxyConfig(proxy_enable, proxy_address, proxy_port); } -// LLWString busy_response = utf8str_to_wstring(getChild<LLUICtrl>("busy_response")->getValue().asString()); -// LLWStringUtil::replaceTabsWithSpaces(busy_response, 4); - if (mGotPersonalInfo) { -// gSavedSettings.setString("BusyModeResponse2", std::string(wstring_to_utf8str(busy_response))); bool new_im_via_email = getChild<LLUICtrl>("send_im_to_email")->getValue().asBoolean(); bool new_hide_online = getChild<LLUICtrl>("online_visibility")->getValue().asBoolean(); @@ -633,21 +629,21 @@ void LLFloaterPreference::cancel() void LLFloaterPreference::onOpen(const LLSD& key) { - // this variable and if that follows it are used to properly handle busy mode response message + // this variable and if that follows it are used to properly handle do not disturb mode response message static bool initialized = FALSE; - // if user is logged in and we haven't initialized busy_response yet, do it + // if user is logged in and we haven't initialized do not disturb mode response yet, do it if (!initialized && LLStartUp::getStartupState() == STATE_STARTED) { - // Special approach is used for busy response localization, because "BusyModeResponse" is + // Special approach is used for do not disturb response localization, because "DoNotDisturbModeResponse" is // in non-localizable xml, and also because it may be changed by user and in this case it shouldn't be localized. - // To keep track of whether busy response is default or changed by user additional setting BusyResponseChanged + // To keep track of whether do not disturb response is default or changed by user additional setting DoNotDisturbResponseChanged // was added into per account settings. // initialization should happen once,so setting variable to TRUE initialized = TRUE; - // this connection is needed to properly set "BusyResponseChanged" setting when user makes changes in - // busy response message. - gSavedPerAccountSettings.getControl("BusyModeResponse")->getSignal()->connect(boost::bind(&LLFloaterPreference::onBusyResponseChanged, this)); + // this connection is needed to properly set "DoNotDisturbResponseChanged" setting when user makes changes in + // do not disturb response message. + gSavedPerAccountSettings.getControl("DoNotDisturbModeResponse")->getSignal()->connect(boost::bind(&LLFloaterPreference::onDoNotDisturbResponseChanged, this)); } gAgent.sendAgentUserInfoRequest(); @@ -709,12 +705,12 @@ void LLFloaterPreference::onVertexShaderEnable() } //static -void LLFloaterPreference::initBusyResponse() +void LLFloaterPreference::initDoNotDisturbResponse() { - if (!gSavedPerAccountSettings.getBOOL("BusyResponseChanged")) + if (!gSavedPerAccountSettings.getBOOL("DoNotDisturbResponseChanged")) { - //LLTrans::getString("BusyModeResponseDefault") is used here for localization (EXT-5885) - gSavedPerAccountSettings.setString("BusyModeResponse", LLTrans::getString("BusyModeResponseDefault")); + //LLTrans::getString("DoNotDisturbModeResponseDefault") is used here for localization (EXT-5885) + gSavedPerAccountSettings.setString("DoNotDisturbModeResponse", LLTrans::getString("DoNotDisturbModeResponseDefault")); } } @@ -1431,14 +1427,11 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im getChild<LLUICtrl>("send_im_to_email")->setValue(im_via_email); getChildView("log_instant_messages")->setEnabled(TRUE); // getChildView("log_chat")->setEnabled(TRUE); -// getChildView("busy_response")->setEnabled(TRUE); // getChildView("log_instant_messages_timestamp")->setEnabled(TRUE); // getChildView("log_chat_timestamp")->setEnabled(TRUE); getChildView("log_chat_IM")->setEnabled(TRUE); getChildView("log_date_timestamp")->setEnabled(TRUE); -// getChild<LLUICtrl>("busy_response")->setValue(gSavedSettings.getString("BusyModeResponse2")); - getChildView("favorites_on_login_check")->setEnabled(TRUE); getChildView("log_nearby_chat")->setEnabled(TRUE); getChildView("log_instant_messages")->setEnabled(TRUE); @@ -1662,7 +1655,6 @@ BOOL LLPanelPreference::postBuild() if (hasChild("online_visibility") && hasChild("send_im_to_email")) { getChild<LLUICtrl>("email_address")->setValue(getString("log_in_to_change") ); -// getChild<LLUICtrl>("busy_response")->setValue(getString("log_in_to_change")); } //////////////////////PanelPrivacy /////////////////// diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index b71f7c647b..10a416beb5 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -75,8 +75,8 @@ public: // refresh all the graphics preferences menus static void refreshEnabledGraphics(); - // translate user's busy response message according to current locale if message is default, otherwise do nothing - static void initBusyResponse(); + // translate user's do not disturb response message according to current locale if message is default, otherwise do nothing + static void initDoNotDisturbResponse(); void processProperties( void* pData, EAvatarProcessorType type ); void processProfileProperties(const LLAvatarData* pAvatarData ); @@ -93,9 +93,9 @@ protected: void onLanguageChange(); void onNameTagOpacityChange(const LLSD& newvalue); - // set value of "BusyResponseChanged" in account settings depending on whether busy response + // set value of "DoNotDisturbResponseChanged" in account settings depending on whether do not disturb response // string differs from default after user changes. - void onBusyResponseChanged(); + void onDoNotDisturbResponseChanged(); // if the custom settings box is clicked void onChangeCustom(); void updateMeterText(LLUICtrl* ctrl); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d5f1e81933..9b14a77c08 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -113,8 +113,8 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id, } void toast_callback(const LLSD& msg){ - // do not show toast in busy mode or it goes from agent - if (gAgent.getBusy() || gAgent.getID() == msg["from_id"]) + // do not show toast in do not disturb mode or it goes from agent + if (gAgent.isDoNotDisturb() || gAgent.getID() == msg["from_id"]) { return; } @@ -3292,13 +3292,13 @@ public: time_t timestamp = (time_t) message_params["timestamp"].asInteger(); - BOOL is_busy = gAgent.getBusy(); + BOOL is_do_not_disturb = gAgent.isDoNotDisturb(); BOOL is_muted = LLMuteList::getInstance()->isMuted( from_id, name, LLMute::flagTextChat); - if (is_busy || is_muted) + if (is_do_not_disturb || is_muted) { return; } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 5d8d82b226..8b04af71c7 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -92,21 +92,6 @@ struct LLMoveInv using namespace LLOldEvents; -// Helpers -// bug in busy count inc/dec right now, logic is complex... do we really need it? -void inc_busy_count() -{ -// gViewerWindow->getWindow()->incBusyCount(); -// check balance of these calls if this code is changed to ever actually -// *do* something! -} -void dec_busy_count() -{ -// gViewerWindow->getWindow()->decBusyCount(); -// check balance of these calls if this code is changed to ever actually -// *do* something! -} - // Function declarations void remove_inventory_category_from_avatar(LLInventoryCategory* category); void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id); @@ -167,7 +152,6 @@ public: { if (clear_observer) { - dec_busy_count(); gInventory.removeObserver(this); delete this; } @@ -2668,7 +2652,6 @@ void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer) llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl; if (clear_observer) { - dec_busy_count(); gInventory.removeObserver(this); delete this; } @@ -2682,7 +2665,6 @@ void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer) // could notify observers and throw us into an infinite loop. if (clear_observer) { - dec_busy_count(); gInventory.removeObserver(this); delete this; } @@ -2744,7 +2726,6 @@ void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer) { // it's all on its way - add an observer, and the inventory // will call done for us when everything is here. - inc_busy_count(); gInventory.addObserver(outfit); } */ @@ -2763,7 +2744,6 @@ void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer) { // it's all on its way - add an observer, and the inventory // will call done for us when everything is here. - inc_busy_count(); gInventory.addObserver(categories); } } @@ -3475,7 +3455,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items else { // it's all on its way - add an observer, and the inventory will call done for us when everything is here. - inc_busy_count(); gInventory.addObserver(fetch); } } diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 7834f6d320..1494d9d6ee 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -560,7 +560,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT && gSavedSettings.getBOOL("UseChatBubbles") ) || mChannel.isDead() - || !mChannel.get()->getShowToasts() ) // to prevent toasts in Busy mode + || !mChannel.get()->getShowToasts() ) // to prevent toasts in Do Not Disturb mode return;//no need in toast if chat is visible or if bubble chat is enabled // arrange a channel on a screen diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 7990b81d92..ac6110f84f 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -179,7 +179,7 @@ LLContextMenu* gDetachScreenPieMenu = NULL; LLContextMenu* gDetachBodyPartPieMenus[8]; LLMenuItemCallGL* gAFKMenu = NULL; -LLMenuItemCallGL* gBusyMenu = NULL; +LLMenuItemCallGL* gDoNotDisturbMenu = NULL; // // Local prototypes @@ -471,7 +471,7 @@ void init_menus() gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", upload_cost); gAFKMenu = gMenuBarView->getChild<LLMenuItemCallGL>("Set Away", TRUE); - gBusyMenu = gMenuBarView->getChild<LLMenuItemCallGL>("Set Busy", TRUE); + gDoNotDisturbMenu = gMenuBarView->getChild<LLMenuItemCallGL>("set_do_not_disturb", TRUE); gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE); gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE); @@ -5564,18 +5564,18 @@ class LLWorldSetAway : public view_listener_t } }; -class LLWorldSetBusy : public view_listener_t +class LLWorldSetDoNotDisturb : public view_listener_t { bool handleEvent(const LLSD& userdata) { - if (gAgent.getBusy()) + if (gAgent.isDoNotDisturb()) { - gAgent.clearBusy(); + gAgent.setDoNotDisturb(false); } else { - gAgent.setBusy(); - LLNotificationsUtil::add("BusyModeSet"); + gAgent.setDoNotDisturb(true); + LLNotificationsUtil::add("DoNotDisturbModeSet"); } return true; } @@ -5737,7 +5737,7 @@ bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjec S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { - gAgent.clearBusy(); + gAgent.setDoNotDisturb(false); } LLViewerObject* objectp = selection->getPrimaryObject(); @@ -5770,12 +5770,12 @@ bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjec void handle_give_money_dialog() { - LLNotification::Params params("BusyModePay"); + LLNotification::Params params("DoNotDisturbModePay"); params.functor.function(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection())); - if (gAgent.getBusy()) + if (gAgent.isDoNotDisturb()) { - // warn users of being in busy mode during a transaction + // warn users of being in do not disturb mode during a transaction LLNotifications::instance().add(params); } else @@ -8288,7 +8288,7 @@ void initialize_menus() view_listener_t::addMenu(new LLWorldSetHomeLocation(), "World.SetHomeLocation"); view_listener_t::addMenu(new LLWorldTeleportHome(), "World.TeleportHome"); view_listener_t::addMenu(new LLWorldSetAway(), "World.SetAway"); - view_listener_t::addMenu(new LLWorldSetBusy(), "World.SetBusy"); + view_listener_t::addMenu(new LLWorldSetDoNotDisturb(), "World.SetDoNotDisturb"); view_listener_t::addMenu(new LLWorldEnableCreateLandmark(), "World.EnableCreateLandmark"); view_listener_t::addMenu(new LLWorldEnableSetHomeLocation(), "World.EnableSetHomeLocation"); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 3515aa4302..e8665a6ef6 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -188,7 +188,7 @@ extern LLContextMenu* gAttachBodyPartPieMenus[8]; extern LLContextMenu* gDetachBodyPartPieMenus[8]; extern LLMenuItemCallGL* gAFKMenu; -extern LLMenuItemCallGL* gBusyMenu; +extern LLMenuItemCallGL* gDoNotDisturbMenu; extern LLMenuItemCallGL* gMutePieMenu; extern LLMenuItemCallGL* gMuteObjectPieMenu; extern LLMenuItemCallGL* gBuyPassPieMenu; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c5d25ebd1b..d500fd78ff 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -179,7 +179,7 @@ const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = FALSE // TeleportYourAgent }; -static void busy_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id = LLUUID::null); +static void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id = LLUUID::null); bool friendship_offer_callback(const LLSD& notification, const LLSD& response) { @@ -258,11 +258,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) static LLNotificationFunctorRegistration friendship_offer_callback_reg("OfferFriendship", friendship_offer_callback); static LLNotificationFunctorRegistration friendship_offer_callback_reg_nm("OfferFriendshipNoMessage", friendship_offer_callback); -//const char BUSY_AUTO_RESPONSE[] = "The Resident you messaged is in 'busy mode' which means they have " -// "requested not to be disturbed. Your message will still be shown in their IM " -// "panel for later viewing."; - -// // Functions // @@ -1520,8 +1515,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& // TODO: when task inventory offers can also be handled the new way, migrate the code that sets these strings here: from_string = chatHistory_string = mFromName; - bool busy = gAgent.getBusy(); - LLNotificationFormPtr modified_form(notification_ptr ? new LLNotificationForm(*notification_ptr->getForm()) : new LLNotificationForm()); switch(button) @@ -1623,9 +1616,9 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& } - if (busy && (!mFromGroup && !mFromObject)) + if (gAgent.isDoNotDisturb() && (!mFromGroup && !mFromObject)) { - busy_message(gMessageSystem, mFromID); + send_do_not_disturb_message(gMessageSystem, mFromID); } if (modified_form != NULL) @@ -1750,7 +1743,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const from_string = chatHistory_string = mFromName; } - bool busy = gAgent.getBusy(); + bool is_do_not_disturb = gAgent.isDoNotDisturb(); switch(button) { @@ -1823,9 +1816,9 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const LLNotificationsUtil::add("SystemMessageTip", args); } - if (busy && (!mFromGroup && !mFromObject)) + if (is_do_not_disturb && (!mFromGroup && !mFromObject)) { - busy_message(msg,mFromID); + send_do_not_disturb_message(msg,mFromID); } break; } @@ -2207,7 +2200,7 @@ static std::string clean_name_from_im(const std::string& name, EInstantMessage t case IM_SESSION_SEND: case IM_SESSION_LEAVE: //IM_FROM_TASK - case IM_BUSY_AUTO_RESPONSE: + case IM_DO_NOT_DISTURB_AUTO_RESPONSE: case IM_CONSOLE_AND_CHAT_HISTORY: case IM_LURE_USER: case IM_LURE_ACCEPTED: @@ -2356,7 +2349,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // IDEVO convert new-style "Resident" names for display name = clean_name_from_im(name, dialog); - BOOL is_busy = gAgent.getBusy(); + BOOL is_do_not_disturb = gAgent.isDoNotDisturb(); BOOL is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat) // object IMs contain sender object id in session_id (STORM-1209) || dialog == IM_FROM_TASK && LLMuteList::getInstance()->isMuted(session_id); @@ -2402,15 +2395,15 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // do nothing -- don't distract newbies in // Prelude with global IMs } - else if (offline == IM_ONLINE && is_busy && name != SYSTEM_FROM) + else if (offline == IM_ONLINE && is_do_not_disturb && name != SYSTEM_FROM) { - // return a standard "busy" message, but only do it to online IM + // return a standard "do not disturb" message, but only do it to online IM // (i.e. not other auto responses and not store-and-forward IM) if (!gIMMgr->hasSession(session_id)) { // if there is not a panel for this conversation (i.e. it is a new IM conversation // initiated by the other party) then... - busy_message(msg, from_id, session_id); + send_do_not_disturb_message(msg, from_id, session_id); } // now store incoming IM in chat history @@ -2645,9 +2638,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) break; case IM_GROUP_INVITATION: { - if (is_busy || is_muted) + if (is_do_not_disturb || is_muted) { - busy_message(msg, from_id); + send_do_not_disturb_message(msg, from_id); } else { @@ -2730,7 +2723,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) info->mFromName = name; info->mDesc = message; info->mHost = msg->getSender(); - //if (((is_busy && !is_owned_by_me) || is_muted)) + //if (((is_do_not_disturb && !is_owned_by_me) || is_muted)) if (is_muted) { // Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331) @@ -2741,9 +2734,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Same as closing window info->forceResponse(IOR_DECLINE); } - else if (is_busy && dialog != IM_TASK_INVENTORY_OFFERED) // busy mode must not affect interaction with objects (STORM-565) + else if (is_do_not_disturb && dialog != IM_TASK_INVENTORY_OFFERED) // busy mode must not affect interaction with objects (STORM-565) { - // Until throttling is implemented, busy mode should reject inventory instead of silently + // Until throttling is implemented, do not disturb mode should reject inventory instead of silently // accepting it. SEE SL-39554 info->forceResponse(IOR_DECLINE); } @@ -2788,7 +2781,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) case IM_SESSION_SEND: { - if (is_busy) + if (is_do_not_disturb) { return; } @@ -2829,7 +2822,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) case IM_FROM_TASK: { - if (is_busy && !is_owned_by_me) + if (is_do_not_disturb && !is_owned_by_me) { return; } @@ -2926,7 +2919,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } break; case IM_FROM_TASK_AS_ALERT: - if (is_busy && !is_owned_by_me) + if (is_do_not_disturb && !is_owned_by_me) { return; } @@ -2937,10 +2930,10 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LLNotificationsUtil::add("ObjectMessage", args); } break; - case IM_BUSY_AUTO_RESPONSE: + case IM_DO_NOT_DISTURB_AUTO_RESPONSE: if (is_muted) { - LL_DEBUGS("Messaging") << "Ignoring busy response from " << from_id << LL_ENDL; + LL_DEBUGS("Messaging") << "Ignoring do-not-disturb response from " << from_id << LL_ENDL; return; } else @@ -2957,9 +2950,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) { return; } - else if (is_busy) + else if (is_do_not_disturb) { - busy_message(msg, from_id); + send_do_not_disturb_message(msg, from_id); } else { @@ -3180,9 +3173,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) payload["online"] = (offline == IM_ONLINE); payload["sender"] = msg->getSender().getIPandPort(); - if (is_busy) + if (is_do_not_disturb) { - busy_message(msg, from_id); + send_do_not_disturb_message(msg, from_id); LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1); } else if (is_muted) @@ -3246,13 +3239,13 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } } -static void busy_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id) +static void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id) { - if (gAgent.getBusy()) + if (gAgent.isDoNotDisturb()) { std::string my_name; LLAgentUI::buildFullname(my_name); - std::string response = gSavedPerAccountSettings.getString("BusyModeResponse"); + std::string response = gSavedPerAccountSettings.getString("DoNotDisturbModeResponse"); pack_instant_message( msg, gAgent.getID(), @@ -3262,7 +3255,7 @@ static void busy_message (LLMessageSystem* msg, const LLUUID& from_id, const LLU my_name, response, IM_ONLINE, - IM_BUSY_AUTO_RESPONSE, + IM_DO_NOT_DISTURB_AUTO_RESPONSE, session_id); gAgent.sendReliableMessage(); } @@ -3298,7 +3291,7 @@ bool callingcard_offer_callback(const LLSD& notification, const LLSD& response) msg->nextBlockFast(_PREHASH_TransactionBlock); msg->addUUIDFast(_PREHASH_TransactionID, notification["payload"]["transaction_id"].asUUID()); msg->sendReliable(LLHost(notification["payload"]["sender"].asString())); - busy_message(msg, notification["payload"]["source_id"].asUUID()); + send_do_not_disturb_message(msg, notification["payload"]["source_id"].asUUID()); break; default: // close button probably, possibly timed out @@ -3340,7 +3333,7 @@ void process_offer_callingcard(LLMessageSystem* msg, void**) if(!source_name.empty()) { - if (gAgent.getBusy() + if (gAgent.isDoNotDisturb() || LLMuteList::getInstance()->isMuted(source_id, source_name, LLMute::flagTextChat)) { // automatically decline offer @@ -3469,7 +3462,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) chat.mFromName = from_name; } - BOOL is_busy = gAgent.getBusy(); + BOOL is_do_not_disturb = gAgent.isDoNotDisturb(); BOOL is_muted = FALSE; BOOL is_linden = FALSE; @@ -3503,7 +3496,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) // record last audible utterance if (is_audible - && (is_linden || (!is_muted && !is_busy))) + && (is_linden || (!is_muted && !is_do_not_disturb))) { if (chat.mChatType != CHAT_TYPE_START && chat.mChatType != CHAT_TYPE_STOP) @@ -3598,7 +3591,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) LLLocalSpeakerMgr::getInstance()->setSpeakerTyping(from_id, FALSE); ((LLVOAvatar*)chatter)->stopTyping(); - if (!is_muted && !is_busy) + if (!is_muted && !is_do_not_disturb) { visible_in_chat_bubble = gSavedSettings.getBOOL("UseChatBubbles"); std::string formated_msg = ""; @@ -4136,14 +4129,14 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) gAgent.setFlying(gAgent.canFly()); } - // force simulator to recognize busy state - if (gAgent.getBusy()) + // force simulator to recognize do not disturb state + if (gAgent.isDoNotDisturb()) { - gAgent.setBusy(); + gAgent.setDoNotDisturb(true); } else { - gAgent.clearBusy(); + gAgent.setDoNotDisturb(false); } if (isAgentAvatarValid()) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 3b2292c04d..ee838b19b7 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1824,8 +1824,8 @@ void LLViewerWindow::initBase() gDebugView->init(); gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view"); - // Initialize busy response message when logged in - LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLFloaterPreference::initBusyResponse)); + // Initialize do not disturb response message when logged in + LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLFloaterPreference::initDoNotDisturbResponse)); // Add the progress bar view (startup view), which overrides everything mProgressView = getRootView()->findChild<LLProgressView>("progress_view"); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 7b08744598..4cdba0fba9 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -680,7 +680,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mNameString(), mTitle(), mNameAway(false), - mNameBusy(false), + mNameDoNotDisturb(false), mNameMute(false), mNameAppearance(false), mNameFriend(false), @@ -1366,7 +1366,7 @@ void LLVOAvatar::initInstance(void) if (LLCharacter::sInstances.size() == 1) { LLKeyframeMotion::setVFS(gStaticVFS); - registerMotion( ANIM_AGENT_BUSY, LLNullMotion::create ); + registerMotion( ANIM_AGENT_DO_NOT_DISTURB, LLNullMotion::create ); registerMotion( ANIM_AGENT_CROUCH, LLKeyframeStandMotion::create ); registerMotion( ANIM_AGENT_CROUCHWALK, LLKeyframeWalkMotion::create ); registerMotion( ANIM_AGENT_EXPRESS_AFRAID, LLEmote::create ); @@ -3100,7 +3100,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) if (!firstname || !lastname) return; bool is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end(); - bool is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end(); + bool is_do_not_disturb = mSignaledAnimations.find(ANIM_AGENT_DO_NOT_DISTURB) != mSignaledAnimations.end(); bool is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end(); bool is_muted; if (isSelf()) @@ -3132,7 +3132,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) || (!title && !mTitle.empty()) || (title && mTitle != title->getString()) || is_away != mNameAway - || is_busy != mNameBusy + || is_do_not_disturb != mNameDoNotDisturb || is_muted != mNameMute || is_appearance != mNameAppearance || is_friend != mNameFriend @@ -3142,7 +3142,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) clearNameTag(); - if (is_away || is_muted || is_busy || is_appearance) + if (is_away || is_muted || is_do_not_disturb || is_appearance) { std::string line; if (is_away) @@ -3150,9 +3150,9 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) line += LLTrans::getString("AvatarAway"); line += ", "; } - if (is_busy) + if (is_do_not_disturb) { - line += LLTrans::getString("AvatarBusy"); + line += LLTrans::getString("AvatarDoNotDisturb"); line += ", "; } if (is_muted) @@ -3222,7 +3222,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) } mNameAway = is_away; - mNameBusy = is_busy; + mNameDoNotDisturb = is_do_not_disturb; mNameMute = is_muted; mNameAppearance = is_appearance; mNameFriend = is_friend; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index e45069dbfe..c59a3a150c 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -942,7 +942,7 @@ private: std::string mNameString; // UTF-8 title + name + status std::string mTitle; bool mNameAway; - bool mNameBusy; + bool mNameDoNotDisturb; bool mNameMute; bool mNameAppearance; bool mNameFriend; diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index f1bf4a6d75..71006d38d2 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -3939,7 +3939,7 @@ void LLVivoxVoiceClient::messageEvent( sessionState *session = findSession(sessionHandle); if(session) { - bool is_busy = gAgent.getBusy(); + bool is_do_not_disturb = gAgent.isDoNotDisturb(); bool is_muted = LLMuteList::getInstance()->isMuted(session->mCallerID, session->mName, LLMute::flagTextChat); bool is_linden = LLMuteList::getInstance()->isLinden(session->mName); bool quiet_chat = false; @@ -3953,10 +3953,10 @@ void LLVivoxVoiceClient::messageEvent( chat.mFromName = session->mName; chat.mSourceType = CHAT_SOURCE_AGENT; - if(is_busy && !is_linden) + if(is_do_not_disturb && !is_linden) { quiet_chat = true; - // TODO: Question: Return busy mode response here? Or maybe when session is started instead? + // TODO: Question: Return do not disturb mode response here? Or maybe when session is started instead? } LL_DEBUGS("Voice") << "adding message, name " << session->mName << " session " << session->mIMSessionID << ", target " << session->mCallerID << LL_ENDL; diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index c805b6db42..f6a307d9d0 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -138,9 +138,9 @@ </menu_item_call> <menu_item_call label="Busy" - name="Set Busy"> + name="set_do_not_disturb"> <menu_item_call.on_click - function="World.SetBusy"/> + function="World.SetDoNotDisturb"/> </menu_item_call> </menu> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 4410f41e29..1c1642abac 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3691,12 +3691,12 @@ Cannot offer friendship at this time. Please try again in a moment. <notification icon="alert.tga" - name="BusyModeSet" + name="DoNotDisturbModeSet" type="alert"> Busy mode is set. Chat and instant messages will be hidden. Instant messages will get your Busy mode response. All teleportation offers will be declined. All inventory offers will go to your Trash. <usetemplate - ignoretext="I change my status to Busy mode" + ignoretext="I change my status to Do Not Disturb mode" name="okignore" yestext="OK"/> </notification> @@ -5167,8 +5167,8 @@ Do you want to replace it with the selected object? <notification icon="alert.tga" - label="Busy Mode Warning" - name="BusyModePay" + label="Do Not Disturb Mode Warning" + name="DoNotDisturbModePay" type="alert"> You are in Busy Mode, which means you will not receive any items offered in exchange for this payment. @@ -5177,15 +5177,15 @@ Would you like to leave Busy Mode before completing this transaction? <form name="form"> <ignore name="ignore" save_option="true" - text="I am about to pay a person or object while I am in Busy mode"/> + text="I am about to pay a person or object while I am in Do Not Disturb mode"/> <button default="true" - ignore="Always leave Busy Mode" + ignore="Always leave Do Not Disturb Mode" index="0" name="Yes" text="OK"/> <button - ignore="Never leave Busy Mode" + ignore="Never leave Do Not Disturb Mode" index="1" name="No" text="Cancel"/> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml index 24882988b0..2cb063e8ee 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -412,7 +412,7 @@ Busy mode response: </text> <text_editor - control_name="BusyModeResponse" + control_name="DoNotDisturbModeResponse" text_readonly_color="LabelDisabledColor" bg_writeable_color="LtGray" use_ellipses="false" @@ -421,7 +421,7 @@ height="29" layout="topleft" left="30" - name="busy_response" + name="do_not_disturb_response" width="470" word_wrap="true"> log_in_to_change diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 01da0a3686..04b6326769 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -295,7 +295,7 @@ Please try logging in again in a minute.</string> <!-- llvoavatar. Displayed in the avatar chat bubble --> <string name="AvatarEditingAppearance">(Editing Appearance)</string> <string name="AvatarAway">Away</string> - <string name="AvatarBusy">Busy</string> + <string name="AvatarDoNotDisturb">Busy</string> <string name="AvatarMuted">Blocked</string> <!-- animations --> @@ -2077,8 +2077,8 @@ For AI Character: Get the closest navigable point to the point provided. <!-- Avatar busy/away mode --> <string name="AvatarSetNotAway">Not Away</string> <string name="AvatarSetAway">Away</string> - <string name="AvatarSetNotBusy">Not Busy</string> - <string name="AvatarSetBusy">Busy</string> + <string name="AvatarSetAvailable">Not Busy</string> + <string name="AvatarSetDoNotDisturb">Busy</string> <!-- Wearable Types --> <string name="shape">Shape</string> @@ -2526,7 +2526,7 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale <string name="PanelContentsNewScript">New Script</string> <!-- panel preferences general --> - <string name="BusyModeResponseDefault">The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing.</string> + <string name="DoNotDisturbModeResponseDefault">The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing.</string> <!-- Mute --> <string name="MuteByName">(By name)</string> -- cgit v1.2.3 From 5aa5a77af66425dd90599b0b0cad5b8f58d7669a Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Thu, 8 Nov 2012 15:15:27 -0800 Subject: CHUI-516: Correcting crash when receiving a god-like teleport lure request while in do-not-disturb mode. --- indra/newview/llviewermessage.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index d500fd78ff..1ddfc51f27 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2033,11 +2033,14 @@ bool lure_callback(const LLSD& notification, const LLSD& response) LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); - LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); - modified_form->setElementEnabled("Teleport", false); - modified_form->setElementEnabled("Cancel", false); - notification_ptr->updateForm(modified_form); - notification_ptr->repost(); + if (notification_ptr) + { + LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); + modified_form->setElementEnabled("Teleport", false); + modified_form->setElementEnabled("Cancel", false); + notification_ptr->updateForm(modified_form); + notification_ptr->repost(); + } return false; } -- cgit v1.2.3 From 1d590cd5fdecabbbf6e96be37a2673de347e2224 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 8 Nov 2012 17:09:23 -0800 Subject: CHUI-464, CHUI-466, CHUI-474 : Fixed! Better, unified and more consistent use of refreshConversation() to update torn off dialogs. --- indra/newview/llimconversation.cpp | 25 ++++++++----------------- indra/newview/llimconversation.h | 1 - 2 files changed, 8 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index e031b0e829..d1fa6e2103 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -51,7 +51,6 @@ LLIMConversation::LLIMConversation(const LLSD& session_id) , mTearOffBtn(NULL) , mCloseBtn(NULL) , mSessionID(session_id.asUUID()) -// , mParticipantList(NULL) , mConversationsRoot(NULL) , mChatHistory(NULL) , mInputEditor(NULL) @@ -77,14 +76,6 @@ LLIMConversation::LLIMConversation(const LLSD& session_id) LLIMConversation::~LLIMConversation() { - /* - if (mParticipantList) - { - delete mParticipantList; - mParticipantList = NULL; - } - */ - delete mRefreshTimer; } @@ -246,8 +237,6 @@ BOOL LLIMConversation::postBuild() buildConversationViewParticipant(); - updateHeaderAndToolbar(); - mSaveRect = isTornOff(); initRectControl(); @@ -264,6 +253,8 @@ BOOL LLIMConversation::postBuild() result = LLDockableFloater::postBuild(); } + refreshConversation(); + return result; } @@ -274,8 +265,6 @@ LLParticipantList* LLIMConversation::getParticipantList() void LLIMConversation::draw() { - LLTransientDockableFloater::draw(); - if (mRefreshTimer->hasExpired()) { if (getParticipantList()) @@ -283,12 +272,13 @@ void LLIMConversation::draw() getParticipantList()->update(); } - refresh(); - updateHeaderAndToolbar(); + refreshConversation(); // Restart the refresh timer mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); } + + LLTransientDockableFloater::draw(); } void LLIMConversation::enableDisableCallBtn() @@ -488,6 +478,8 @@ void LLIMConversation::refreshConversation() mConversationViewModel.requestSortAll(); mConversationsRoot->arrangeAll(); mConversationsRoot->update(); + updateHeaderAndToolbar(); + refresh(); } // Copied from LLIMFloaterContainer::createConversationViewParticipant(). Refactor opportunity! @@ -731,7 +723,6 @@ void LLIMConversation::onTearOffClicked() mSaveRect = isTornOff(); initRectControl(); LLFloater::onClickTearOff(this); - updateHeaderAndToolbar(); refreshConversation(); } @@ -749,7 +740,7 @@ bool LLIMConversation::checkIfTornOff() if (isTorn != isTornOff()) { setTornOff(isTorn); - updateHeaderAndToolbar(); + refreshConversation(); } return isTorn; diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 49cfcb68c4..93a1ab847e 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -142,7 +142,6 @@ protected: LLUUID mSessionID; LLLayoutPanel* mParticipantListPanel; // add the widgets to that see mConversationsListPanel - //LLParticipantList* mParticipantList; get this from the mConversationsItems for the moment LLParticipantList* getParticipantList(); conversations_widgets_map mConversationsWidgets; LLConversationViewModel mConversationViewModel; -- cgit v1.2.3 From 486bdf32845e248ec4923224f1f4ea5d239ac0f3 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 9 Nov 2012 12:45:36 +0200 Subject: CHUI-337 FIXED: To avoid confusion with a classes "...conversation..." and in accordance with the naming convention in the project, some classes and corresponding files should be renamed: LLIMConversation -> LLFloaterIMSessionTab LLIMFloater -> LLFloaterIMSession LLNearbyChat -> LLFloaterIMNearbyChat LLIMFloaterContainer -> LLFloaterIMContainer LLNearbyChatBarListener -> LLFloaterIMNearbyChatListener LLNearbyChatHandler -> LLFloaterIMNearbyChatHandler --- indra/newview/CMakeLists.txt | 24 +- indra/newview/llagent.cpp | 6 +- indra/newview/llappviewer.cpp | 4 +- indra/newview/llavataractions.cpp | 6 +- indra/newview/llavatariconctrl.cpp | 2 +- indra/newview/llchatbar.cpp | 2 +- indra/newview/llchatitemscontainerctrl.cpp | 38 +- indra/newview/llchatitemscontainerctrl.h | 8 +- indra/newview/llchiclet.cpp | 16 +- indra/newview/llchiclet.h | 2 +- indra/newview/llchicletbar.cpp | 10 +- indra/newview/llconversationlog.cpp | 6 +- indra/newview/llconversationlog.h | 4 +- indra/newview/llconversationloglistitem.cpp | 6 +- indra/newview/llconversationloglistitem.h | 2 +- indra/newview/llconversationview.cpp | 14 +- indra/newview/llconversationview.h | 8 +- indra/newview/llfloaterconversationpreview.cpp | 4 +- indra/newview/llfloaterimcontainer.cpp | 1557 +++++++++++++++++++++++ indra/newview/llfloaterimcontainer.h | 178 +++ indra/newview/llfloaterimnearbychat.cpp | 867 +++++++++++++ indra/newview/llfloaterimnearbychat.h | 125 ++ indra/newview/llfloaterimnearbychathandler.cpp | 630 +++++++++ indra/newview/llfloaterimnearbychathandler.h | 54 + indra/newview/llfloaterimnearbychatlistener.cpp | 100 ++ indra/newview/llfloaterimnearbychatlistener.h | 50 + indra/newview/llfloaterimsession.cpp | 1202 +++++++++++++++++ indra/newview/llfloaterimsession.h | 196 +++ indra/newview/llfloaterimsessiontab.cpp | 743 +++++++++++ indra/newview/llfloaterimsessiontab.h | 176 +++ indra/newview/llfloaterpreference.cpp | 6 +- indra/newview/llfloatertranslationsettings.cpp | 4 +- indra/newview/llgesturemgr.cpp | 4 +- indra/newview/llgroupactions.cpp | 4 +- indra/newview/llgroupiconctrl.cpp | 2 +- indra/newview/llimconversation.cpp | 743 ----------- indra/newview/llimconversation.h | 176 --- indra/newview/llimfloater.cpp | 1202 ----------------- indra/newview/llimfloater.h | 196 --- indra/newview/llimfloatercontainer.cpp | 1557 ----------------------- indra/newview/llimfloatercontainer.h | 178 --- indra/newview/llimpanel.cpp | 2 +- indra/newview/llimview.cpp | 36 +- indra/newview/llinventorybridge.cpp | 4 +- indra/newview/llinventorypanel.cpp | 4 +- indra/newview/llnearbychat.cpp | 867 ------------- indra/newview/llnearbychat.h | 125 -- indra/newview/llnearbychatbarlistener.cpp | 100 -- indra/newview/llnearbychatbarlistener.h | 50 - indra/newview/llnearbychathandler.cpp | 630 --------- indra/newview/llnearbychathandler.h | 54 - indra/newview/llnotificationhandler.h | 2 +- indra/newview/llnotificationhandlerutil.cpp | 10 +- indra/newview/llnotificationmanager.cpp | 4 +- indra/newview/llnotificationmanager.h | 2 +- indra/newview/llnotificationtiphandler.cpp | 6 +- indra/newview/llparticipantlist.cpp | 6 +- indra/newview/llscreenchannel.cpp | 2 +- indra/newview/llscriptfloater.cpp | 2 +- indra/newview/llstartup.cpp | 8 +- indra/newview/lltoastnotifypanel.cpp | 2 +- indra/newview/llviewerfloaterreg.cpp | 12 +- indra/newview/llviewergesture.cpp | 4 +- indra/newview/llviewerkeyboard.cpp | 10 +- indra/newview/llviewermessage.cpp | 6 +- indra/newview/llviewerwindow.cpp | 6 +- 66 files changed, 6033 insertions(+), 6033 deletions(-) create mode 100644 indra/newview/llfloaterimcontainer.cpp create mode 100644 indra/newview/llfloaterimcontainer.h create mode 100644 indra/newview/llfloaterimnearbychat.cpp create mode 100644 indra/newview/llfloaterimnearbychat.h create mode 100644 indra/newview/llfloaterimnearbychathandler.cpp create mode 100644 indra/newview/llfloaterimnearbychathandler.h create mode 100644 indra/newview/llfloaterimnearbychatlistener.cpp create mode 100644 indra/newview/llfloaterimnearbychatlistener.h create mode 100644 indra/newview/llfloaterimsession.cpp create mode 100644 indra/newview/llfloaterimsession.h create mode 100644 indra/newview/llfloaterimsessiontab.cpp create mode 100644 indra/newview/llfloaterimsessiontab.h delete mode 100644 indra/newview/llimconversation.cpp delete mode 100644 indra/newview/llimconversation.h delete mode 100644 indra/newview/llimfloater.cpp delete mode 100644 indra/newview/llimfloater.h delete mode 100644 indra/newview/llimfloatercontainer.cpp delete mode 100644 indra/newview/llimfloatercontainer.h delete mode 100644 indra/newview/llnearbychat.cpp delete mode 100644 indra/newview/llnearbychat.h delete mode 100644 indra/newview/llnearbychatbarlistener.cpp delete mode 100644 indra/newview/llnearbychatbarlistener.h delete mode 100644 indra/newview/llnearbychathandler.cpp delete mode 100644 indra/newview/llnearbychathandler.h (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 2c7e96f1e4..45c719f28d 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -299,9 +299,9 @@ set(viewer_SOURCE_FILES llhudrender.cpp llhudtext.cpp llhudview.cpp - llimconversation.cpp - llimfloater.cpp - llimfloatercontainer.cpp + llfloaterimsessiontab.cpp + llfloaterimsession.cpp + llfloaterimcontainer.cpp llimhandler.cpp llimview.cpp llinspect.cpp @@ -353,9 +353,9 @@ set(viewer_SOURCE_FILES llnameeditor.cpp llnamelistctrl.cpp llnavigationbar.cpp - llnearbychat.cpp - llnearbychathandler.cpp - llnearbychatbarlistener.cpp + llfloaterimnearbychat.cpp + llfloaterimnearbychathandler.cpp + llfloaterimnearbychatlistener.cpp llnetmap.cpp llnotificationalerthandler.cpp llnotificationgrouphandler.cpp @@ -882,9 +882,9 @@ set(viewer_HEADER_FILES llhudrender.h llhudtext.h llhudview.h - llimconversation.h - llimfloater.h - llimfloatercontainer.h + llfloaterimsessiontab.h + llfloaterimsession.h + llfloaterimcontainer.h llimview.h llinspect.h llinspectavatar.h @@ -936,9 +936,9 @@ set(viewer_HEADER_FILES llnameeditor.h llnamelistctrl.h llnavigationbar.h - llnearbychat.h - llnearbychathandler.h - llnearbychatbarlistener.h + llfloaterimnearbychat.h + llfloaterimnearbychathandler.h + llfloaterimnearbychatlistener.h llnetmap.h llnotificationhandler.h llnotificationmanager.h diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index cefd5c72e8..9c3a7ac45b 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -54,7 +54,7 @@ #include "llmorphview.h" #include "llmoveview.h" #include "llnavigationbar.h" // to show/hide navigation bar when changing mouse look state -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" #include "llnotificationsutil.h" #include "llpanelpathfindingrebakenavmesh.h" #include "llpaneltopinfobar.h" @@ -1899,7 +1899,7 @@ void LLAgent::startTyping() { sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START); } - (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> + (LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))-> sendChatFromViewer("", CHAT_TYPE_START, FALSE); } @@ -1912,7 +1912,7 @@ void LLAgent::stopTyping() { clearRenderState(AGENT_STATE_TYPING); sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); - (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> + (LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))-> sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); } } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b23e5866dc..8abe9bcfc1 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -42,7 +42,7 @@ #include "llagentcamera.h" #include "llagentlanguage.h" #include "llagentwearables.h" -#include "llimfloatercontainer.h" +#include "llfloaterimcontainer.h" #include "llwindow.h" #include "llviewerstats.h" #include "llviewerstatsrecorder.h" @@ -1204,7 +1204,7 @@ bool LLAppViewer::mainLoop() LLVoiceChannel::initClass(); LLVoiceClient::getInstance()->init(gServicePump); - LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLIMFloaterContainer::onCurrentChannelChanged, _1), true); + LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true); LLTimer frameTimer,idleTimer; LLTimer debugTime; LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 130428f3c0..4f57498506 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -56,7 +56,7 @@ #include "llinventorybridge.h" #include "llinventorymodel.h" // for gInventory.findCategoryUUIDForType #include "llinventorypanel.h" -#include "llimfloatercontainer.h" +#include "llfloaterimcontainer.h" #include "llimview.h" // for gIMMgr #include "llmutelist.h" #include "llnotificationsutil.h" // for LLNotificationsUtil @@ -184,7 +184,7 @@ static void on_avatar_name_cache_start_im(const LLUUID& agent_id, LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id); if (session_id != LLUUID::null) { - LLIMFloaterContainer::getInstance()->showConversation(session_id); + LLFloaterIMContainer::getInstance()->showConversation(session_id); } make_ui_sound("UISndStartIM"); } @@ -302,7 +302,7 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids, const LLUUID& float return; } - LLIMFloaterContainer::getInstance()->showConversation(session_id); + LLFloaterIMContainer::getInstance()->showConversation(session_id); make_ui_sound("UISndStartIM"); } diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 6355f0db56..b7278d4a3a 100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -38,7 +38,7 @@ #include "llmenugl.h" #include "lluictrlfactory.h" #include "llagentdata.h" -#include "llimfloater.h" +#include "llfloaterimsession.h" // library includes #include "llavatarnamecache.h" diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index d6095cce07..27138e6c06 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -672,7 +672,7 @@ void LLChatBar::onCommitGesture(LLUICtrl* ctrl) /* Cruft - global gChatHandler declared below has been commented out, - so this class is never used. See similar code in llnearbychatbar.cpp + so this class is never used. See similar code in llfloaterimnearbychatbar.cpp class LLChatHandler : public LLCommandHandler { public: diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index f1b5c42ef3..a1a9463d43 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -35,7 +35,7 @@ #include "llfloaterreg.h" #include "lllocalcliprect.h" #include "lltrans.h" -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" #include "llviewercontrol.h" #include "llagentdata.h" @@ -81,18 +81,18 @@ public: LLObjectHandler gObjectHandler; //******************************************************************************************************************* -//LLNearbyChatToastPanel +//LLFloaterIMNearbyChatToastPanel //******************************************************************************************************************* -LLNearbyChatToastPanel* LLNearbyChatToastPanel::createInstance() +LLFloaterIMNearbyChatToastPanel* LLFloaterIMNearbyChatToastPanel::createInstance() { - LLNearbyChatToastPanel* item = new LLNearbyChatToastPanel(); + LLFloaterIMNearbyChatToastPanel* item = new LLFloaterIMNearbyChatToastPanel(); item->buildFromFile("panel_chat_item.xml"); item->setFollows(FOLLOWS_NONE); return item; } -void LLNearbyChatToastPanel::reshape (S32 width, S32 height, BOOL called_from_parent ) +void LLFloaterIMNearbyChatToastPanel::reshape (S32 width, S32 height, BOOL called_from_parent ) { LLPanel::reshape(width, height,called_from_parent); @@ -121,12 +121,12 @@ void LLNearbyChatToastPanel::reshape (S32 width, S32 height, BOOL called_from_p msg_text->setRect(msg_text_rect); } -BOOL LLNearbyChatToastPanel::postBuild() +BOOL LLFloaterIMNearbyChatToastPanel::postBuild() { return LLPanel::postBuild(); } -void LLNearbyChatToastPanel::addMessage(LLSD& notification) +void LLFloaterIMNearbyChatToastPanel::addMessage(LLSD& notification) { std::string messageText = notification["message"].asString(); // UTF-8 line of text @@ -178,7 +178,7 @@ void LLNearbyChatToastPanel::addMessage(LLSD& notification) } -void LLNearbyChatToastPanel::init(LLSD& notification) +void LLFloaterIMNearbyChatToastPanel::init(LLSD& notification) { std::string messageText = notification["message"].asString(); // UTF-8 line of text std::string fromName = notification["from"].asString(); // agent or object name @@ -273,7 +273,7 @@ void LLNearbyChatToastPanel::init(LLSD& notification) mIsDirty = true;//will set Avatar Icon in draw } -void LLNearbyChatToastPanel::snapToMessageHeight () +void LLFloaterIMNearbyChatToastPanel::snapToMessageHeight () { LLChatMsgBox* text_box = getChild<LLChatMsgBox>("msg_text", false); S32 new_height = llmax (text_box->getTextPixelHeight() + 2*text_box->getVPad() + 2*msg_height_pad, 25); @@ -288,22 +288,22 @@ void LLNearbyChatToastPanel::snapToMessageHeight () } -void LLNearbyChatToastPanel::onMouseLeave (S32 x, S32 y, MASK mask) +void LLFloaterIMNearbyChatToastPanel::onMouseLeave (S32 x, S32 y, MASK mask) { } -void LLNearbyChatToastPanel::onMouseEnter (S32 x, S32 y, MASK mask) +void LLFloaterIMNearbyChatToastPanel::onMouseEnter (S32 x, S32 y, MASK mask) { if(mSourceType != CHAT_SOURCE_AGENT) return; } -BOOL LLNearbyChatToastPanel::handleMouseDown (S32 x, S32 y, MASK mask) +BOOL LLFloaterIMNearbyChatToastPanel::handleMouseDown (S32 x, S32 y, MASK mask) { return LLPanel::handleMouseDown(x,y,mask); } -BOOL LLNearbyChatToastPanel::handleMouseUp (S32 x, S32 y, MASK mask) +BOOL LLFloaterIMNearbyChatToastPanel::handleMouseUp (S32 x, S32 y, MASK mask) { /* fix for request EXT-4780 @@ -323,16 +323,16 @@ BOOL LLNearbyChatToastPanel::handleMouseUp (S32 x, S32 y, MASK mask) return TRUE; else { - (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))->showHistory(); + (LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->showHistory(); return FALSE; } } - (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))->showHistory(); + (LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->showHistory(); return LLPanel::handleMouseUp(x,y,mask); } -void LLNearbyChatToastPanel::setHeaderVisibility(EShowItemHeader e) +void LLFloaterIMNearbyChatToastPanel::setHeaderVisibility(EShowItemHeader e) { LLUICtrl* icon = getChild<LLUICtrl>("avatar_icon", false); if(icon) @@ -340,7 +340,7 @@ void LLNearbyChatToastPanel::setHeaderVisibility(EShowItemHeader e) } -bool LLNearbyChatToastPanel::canAddText () +bool LLFloaterIMNearbyChatToastPanel::canAddText () { LLChatMsgBox* msg_text = findChild<LLChatMsgBox>("msg_text"); if(!msg_text) @@ -348,7 +348,7 @@ bool LLNearbyChatToastPanel::canAddText () return msg_text->getLineCount()<10; } -BOOL LLNearbyChatToastPanel::handleRightMouseDown(S32 x, S32 y, MASK mask) +BOOL LLFloaterIMNearbyChatToastPanel::handleRightMouseDown(S32 x, S32 y, MASK mask) { LLUICtrl* avatar_icon = getChild<LLUICtrl>("avatar_icon", false); @@ -360,7 +360,7 @@ BOOL LLNearbyChatToastPanel::handleRightMouseDown(S32 x, S32 y, MASK mask) return TRUE; return LLPanel::handleRightMouseDown(x,y,mask); } -void LLNearbyChatToastPanel::draw() +void LLFloaterIMNearbyChatToastPanel::draw() { LLPanel::draw(); diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h index 89b0c4f37a..54b6499d52 100644 --- a/indra/newview/llchatitemscontainerctrl.h +++ b/indra/newview/llchatitemscontainerctrl.h @@ -40,18 +40,18 @@ typedef enum e_show_item_header CHATITEMHEADER_SHOW_BOTH } EShowItemHeader; -class LLNearbyChatToastPanel : public LLPanel +class LLFloaterIMNearbyChatToastPanel : public LLPanel { protected: - LLNearbyChatToastPanel() + LLFloaterIMNearbyChatToastPanel() : mIsDirty(false), mSourceType(CHAT_SOURCE_OBJECT) {}; public: - ~LLNearbyChatToastPanel(){} + ~LLFloaterIMNearbyChatToastPanel(){} - static LLNearbyChatToastPanel* createInstance(); + static LLFloaterIMNearbyChatToastPanel* createInstance(); const LLUUID& getFromID() const { return mFromID;} const std::string& getFromName() const { return mFromName; } diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index e328186fd6..64d8a68a99 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -33,8 +33,8 @@ #include "lleventtimer.h" #include "llgroupactions.h" #include "lliconctrl.h" -#include "llimfloater.h" -#include "llimfloatercontainer.h" +#include "llfloaterimsession.h" +#include "llfloaterimcontainer.h" #include "llimview.h" #include "llfloaterreg.h" #include "lllocalcliprect.h" @@ -605,7 +605,7 @@ bool LLIMChiclet::getShowNewMessagesIcon() void LLIMChiclet::onMouseDown() { - LLIMFloater::toggle(getSessionId()); + LLFloaterIMSession::toggle(getSessionId()); setCounter(0); } @@ -754,7 +754,7 @@ void LLIMP2PChiclet::updateMenuItems() if(getSessionId().isNull()) return; - LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId()); + LLFloaterIMSession* open_im_floater = LLFloaterIMSession::findInstance(getSessionId()); bool open_window_exists = open_im_floater && open_im_floater->getVisible(); mPopupMenu->getChild<LLUICtrl>("Send IM")->setEnabled(!open_window_exists); @@ -1030,7 +1030,7 @@ void LLIMGroupChiclet::updateMenuItems() if(getSessionId().isNull()) return; - LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId()); + LLFloaterIMSession* open_im_floater = LLFloaterIMSession::findInstance(getSessionId()); bool open_window_exists = open_im_floater && open_im_floater->getVisible(); mPopupMenu->getChild<LLUICtrl>("Chat")->setEnabled(!open_window_exists); } @@ -1116,7 +1116,7 @@ void LLChicletPanel::onMessageCountChanged(const LLSD& data) LLUUID session_id = data["session_id"].asUUID(); S32 unread = data["participant_unread"].asInteger(); - LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); + LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(session_id); if (im_floater && im_floater->getVisible() && im_floater->hasFocus()) { unread = 0; @@ -1197,7 +1197,7 @@ void LLChicletPanel::onCurrentVoiceChannelChanged(const LLUUID& session_id) chiclet->setShowSpeaker(true); if (gSavedSettings.getBOOL("OpenIMOnVoice")) { - LLIMFloaterContainer::getInstance()->showConversation(session_id); + LLFloaterIMContainer::getInstance()->showConversation(session_id); } } } @@ -1688,7 +1688,7 @@ bool LLChicletPanel::isAnyIMFloaterDoked() for (chiclet_list_t::iterator it = mChicletList.begin(); it != mChicletList.end(); it++) { - LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>( + LLFloaterIMSession* im_floater = LLFloaterReg::findTypedInstance<LLFloaterIMSession>( "impanel", (*it)->getSessionId()); if (im_floater != NULL && im_floater->getVisible() && !im_floater->isMinimized() && im_floater->isDocked()) diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 6395f5b694..3c8389e20d 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -37,7 +37,7 @@ #include "llnotifications.h" class LLMenuGL; -class LLIMFloater; +class LLFloaterIMSession; /** * Class for displaying amount of messages/notifications(unread). diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index 3ebb83b336..ad7890b47a 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -34,7 +34,7 @@ // newview includes #include "llchiclet.h" -#include "llimfloater.h" // for LLIMFloater +#include "llfloaterimsession.h" // for LLFloaterIMSession #include "llpaneltopinfobar.h" #include "llsyswellwindow.h" @@ -95,9 +95,9 @@ void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& nam if (session->isP2P() && session->isOtherParticipantAvaline()) return; // Do not spawn chiclet when using the new multitab conversation UI - if (LLIMConversation::isChatMultiTab()) + if (LLFloaterIMSessionTab::isChatMultiTab()) { - LLIMConversation::addToHost(session_id); + LLFloaterIMSessionTab::addToHost(session_id); return; } @@ -109,7 +109,7 @@ void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& nam chiclet->setIMSessionName(name); chiclet->setOtherParticipantId(other_participant_id); - LLIMFloater::onIMChicletCreated(session_id); + LLFloaterIMSession::onIMChicletCreated(session_id); } else @@ -124,7 +124,7 @@ void LLChicletBar::sessionRemoved(const LLUUID& session_id) if(getChicletPanel()) { // IM floater should be closed when session removed and associated chiclet closed - LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); + LLFloaterIMSession* im_floater = LLFloaterReg::findTypedInstance<LLFloaterIMSession>("impanel", session_id); if (im_floater != NULL && !im_floater->getStartConferenceInSameFloater()) { // Close the IM floater only if we are not planning to close the P2P chat diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 7a5a476efb..3d2b6a5c00 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -140,15 +140,15 @@ bool LLConversation::isOlderThan(U32 days) const void LLConversation::setListenIMFloaterOpened() { - LLIMFloater* floater = LLIMFloater::findInstance(mSessionID); + LLFloaterIMSession* floater = LLFloaterIMSession::findInstance(mSessionID); - bool offline_ims_visible = LLIMFloater::isVisible(floater) && floater->hasFocus(); + bool offline_ims_visible = LLFloaterIMSession::isVisible(floater) && floater->hasFocus(); // we don't need to listen for im floater with this conversation is opened // if floater is already opened or this conversation doesn't have unread offline messages if (mHasOfflineIMs && !offline_ims_visible) { - mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1)); + mIMFloaterShowedConnection = LLFloaterIMSession::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1)); } else { diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index b92cf0f5e2..7d0b9113c6 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -27,7 +27,7 @@ #define LLCONVERSATIONLOG_H_ #include "llcallingcard.h" -#include "llimfloater.h" +#include "llfloaterimsession.h" #include "llimview.h" class LLConversationLogObserver; @@ -80,7 +80,7 @@ public: private: /* - * If conversation has unread offline messages sets callback for opening LLIMFloater + * If conversation has unread offline messages sets callback for opening LLFloaterIMSession * with this conversation. */ void setListenIMFloaterOpened(); diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp index b4ae5f19da..9fad0e603e 100644 --- a/indra/newview/llconversationloglistitem.cpp +++ b/indra/newview/llconversationloglistitem.cpp @@ -47,13 +47,13 @@ LLConversationLogListItem::LLConversationLogListItem(const LLConversation* conve { buildFromFile("panel_conversation_log_list_item.xml"); - LLIMFloater* floater = LLIMFloater::findInstance(mConversation->getSessionID()); + LLFloaterIMSession* floater = LLFloaterIMSession::findInstance(mConversation->getSessionID()); - bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); + bool ims_are_read = LLFloaterIMSession::isVisible(floater) && floater->hasFocus(); if (mConversation->hasOfflineMessages() && !ims_are_read) { - mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversationLogListItem::onIMFloaterShown, this, _1)); + mIMFloaterShowedConnection = LLFloaterIMSession::setIMFloaterShowedCallback(boost::bind(&LLConversationLogListItem::onIMFloaterShown, this, _1)); } } diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h index 1bf7a0ed93..57f72db382 100644 --- a/indra/newview/llconversationloglistitem.h +++ b/indra/newview/llconversationloglistitem.h @@ -26,7 +26,7 @@ #ifndef LLCONVERSATIONLOGLISTITEM_H_ #define LLCONVERSATIONLOGLISTITEM_H_ -#include "llimfloater.h" +#include "llfloaterimsession.h" #include "llpanel.h" class LLTextBox; diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index ac5b2ad6ac..3495d74191 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -32,10 +32,10 @@ #include <boost/bind.hpp> #include "llagentdata.h" #include "llconversationmodel.h" -#include "llimfloater.h" -#include "llnearbychat.h" -#include "llimconversation.h" -#include "llimfloatercontainer.h" +#include "llfloaterimsession.h" +#include "llfloaterimnearbychat.h" +#include "llfloaterimsessiontab.h" +#include "llfloaterimcontainer.h" #include "llfloaterreg.h" #include "llgroupiconctrl.h" #include "lluictrlfactory.h" @@ -208,7 +208,7 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem()); LLUUID session_id = item? item->getUUID() : LLUUID(); - (LLFloaterReg::getTypedInstance<LLIMFloaterContainer>("im_container"))-> + (LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"))-> selectConversationPair(session_id, false); return LLFolderViewFolder::handleMouseDown(x, y, mask); @@ -262,7 +262,7 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible) // Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here LLFolderViewModelItem* item = mViewModelItem; LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID(); - LLFloater* session_floater = LLIMConversation::getConversation(session_uuid); + LLFloater* session_floater = LLFloaterIMSessionTab::getConversation(session_uuid); if (session_floater && !session_floater->getHost() && !session_floater->isMinimized()) { @@ -505,7 +505,7 @@ BOOL LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask ) } LLUUID session_id = item? item->getUUID() : LLUUID(); - (LLFloaterReg::getTypedInstance<LLIMFloaterContainer>("im_container"))-> + (LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"))-> selectConversationPair(session_id, false); return LLFolderViewItem::handleMouseDown(x, y, mask); diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 43547d155b..cc6995c207 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -34,7 +34,7 @@ #include "lloutputmonitorctrl.h" class LLTextBox; -class LLIMFloaterContainer; +class LLFloaterIMContainer; class LLConversationViewSession; class LLConversationViewParticipant; @@ -47,7 +47,7 @@ class LLConversationViewSession : public LLFolderViewFolder public: struct Params : public LLInitParam::Block<Params, LLFolderViewItem::Params> { - Optional<LLIMFloaterContainer*> container; + Optional<LLFloaterIMContainer*> container; Params(); }; @@ -56,7 +56,7 @@ protected: friend class LLUICtrlFactory; LLConversationViewSession( const Params& p ); - LLIMFloaterContainer* mContainer; + LLFloaterIMContainer* mContainer; public: virtual ~LLConversationViewSession(); @@ -107,7 +107,7 @@ public: struct Params : public LLInitParam::Block<Params, LLFolderViewItem::Params> { - Optional<LLIMFloaterContainer*> container; + Optional<LLFloaterIMContainer*> container; Optional<LLUUID> participant_id; Optional<LLAvatarIconCtrl::Params> avatar_icon; Optional<LLButton::Params> info_button; diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index a3825eafc8..c93181c0a1 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -29,7 +29,7 @@ #include "llfloaterconversationpreview.h" #include "llimview.h" #include "lllineeditor.h" -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" #include "llspinctrl.h" #include "lltrans.h" @@ -149,7 +149,7 @@ void LLFloaterConversationPreview::showHistory() } else if (from_id.isNull()) { - chat.mSourceType = LLNearbyChat::isWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT; + chat.mSourceType = LLFloaterIMNearbyChat::isWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT; } mChatHistory->appendMessage(chat); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp new file mode 100644 index 0000000000..b20d19d0fd --- /dev/null +++ b/indra/newview/llfloaterimcontainer.cpp @@ -0,0 +1,1557 @@ +/** + * @file llfloaterimcontainer.cpp + * @brief Multifloater containing active IM sessions in separate tab container tabs + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterimsession.h" +#include "llfloaterimcontainer.h" + +#include "llfloaterreg.h" +#include "lllayoutstack.h" +#include "llfloaterimnearbychat.h" + +#include "llagent.h" +#include "llavataractions.h" +#include "llavatariconctrl.h" +#include "llavatarnamecache.h" +#include "llcallbacklist.h" +#include "llgroupactions.h" +#include "llgroupiconctrl.h" +#include "llfloateravatarpicker.h" +#include "llfloaterpreference.h" +#include "llimview.h" +#include "llnotificationsutil.h" +#include "lltransientfloatermgr.h" +#include "llviewercontrol.h" +#include "llconversationview.h" +#include "llcallbacklist.h" +#include "llworld.h" + +#include "llsdserialize.h" +// +// LLFloaterIMContainer +// +LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed) +: LLMultiFloater(seed), + mExpandCollapseBtn(NULL), + mConversationsRoot(NULL), + mConversationsEventStream("ConversationsEvents"), + mInitialized(false) +{ + mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2)); + mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction, this, _2)); + + mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMContainer::checkContextMenuItem, this, _2)); + mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMContainer::enableContextMenuItem, this, _2)); + mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMContainer::doToSelected, this, _2)); + + mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&LLFloaterIMContainer::doToSelectedGroup, this, _2)); + + // Firstly add our self to IMSession observers, so we catch session events + LLIMMgr::getInstance()->addSessionObserver(this); + + mAutoResize = FALSE; + LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); +} + +LLFloaterIMContainer::~LLFloaterIMContainer() +{ + mConversationsEventStream.stopListening("ConversationsRefresh"); + + gIdleCallbacks.deleteFunction(idle, this); + + mNewMessageConnection.disconnect(); + LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); + + gSavedPerAccountSettings.setBOOL("ConversationsListPaneCollapsed", mConversationsPane->isCollapsed()); + gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed()); + + if (!LLSingleton<LLIMMgr>::destroyed()) + { + LLIMMgr::getInstance()->removeSessionObserver(this); + } +} + +void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +{ + addConversationListItem(session_id); + LLFloaterIMSessionTab::addToHost(session_id); +} + +void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +{ + selectConversation(session_id); +} + +void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) +{ + addConversationListItem(session_id); + LLFloaterIMSessionTab::addToHost(session_id); +} + +void LLFloaterIMContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) +{ + // *TODO: We should do this *without* delete and recreate + addConversationListItem(new_session_id, removeConversationListItem(old_session_id)); +} + +void LLFloaterIMContainer::sessionRemoved(const LLUUID& session_id) +{ + removeConversationListItem(session_id); +} + +// static +void LLFloaterIMContainer::onCurrentChannelChanged(const LLUUID& session_id) +{ + if (session_id != LLUUID::null) + { + LLFloaterIMContainer::getInstance()->showConversation(session_id); + } +} + + +BOOL LLFloaterIMContainer::postBuild() +{ + mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLFloaterIMContainer::onNewMessageReceived, this, _1)); + // Do not call base postBuild to not connect to mCloseSignal to not close all floaters via Close button + // mTabContainer will be initialized in LLMultiFloater::addChild() + + setTabContainer(getChild<LLTabContainer>("im_box_tab_container")); + + mConversationsStack = getChild<LLLayoutStack>("conversations_stack"); + mConversationsPane = getChild<LLLayoutPanel>("conversations_layout_panel"); + mMessagesPane = getChild<LLLayoutPanel>("messages_layout_panel"); + + mConversationsListPanel = getChild<LLPanel>("conversations_list_panel"); + + // Open IM session with selected participant on double click event + mConversationsListPanel->setDoubleClickCallback(boost::bind(&LLFloaterIMContainer::doToSelected, this, LLSD("im"))); + + // Create the root model and view for all conversation sessions + LLConversationItem* base_item = new LLConversationItem(getRootViewModel()); + + LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); + p.name = getName(); + p.title = getLabel(); + p.rect = LLRect(0, 0, getRect().getWidth(), 0); + p.parent_panel = mConversationsListPanel; + p.tool_tip = p.name; + p.listener = base_item; + p.view_model = &mConversationViewModel; + p.root = NULL; + p.use_ellipses = true; + p.options_menu = "menu_conversation.xml"; + mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); + mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + + // Add listener to conversation model events + mConversationsEventStream.listen("ConversationsRefresh", boost::bind(&LLFloaterIMContainer::onConversationModelEvent, this, _1)); + + // a scroller for folder view + LLRect scroller_view_rect = mConversationsListPanel->getRect(); + scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); + LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>()); + scroller_params.rect(scroller_view_rect); + + LLScrollContainer* scroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); + scroller->setFollowsAll(); + mConversationsListPanel->addChild(scroller); + scroller->addChild(mConversationsRoot); + mConversationsRoot->setScrollContainer(scroller); + mConversationsRoot->setFollowsAll(); + mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); + + addConversationListItem(LLUUID()); // manually add nearby chat + + mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); + mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onExpandCollapseButtonClicked, this)); + + childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this)); + + collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); + collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); + LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate)); + + if (! mMessagesPane->isCollapsed()) + { + S32 list_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"); + LLRect list_size = mConversationsPane->getRect(); + S32 left_pad = mConversationsListPanel->getRect().mLeft; + list_size.mRight = list_size.mLeft + list_width - left_pad; + + mConversationsPane->handleReshape(list_size, TRUE); + } + + // Init the sort order now that the root had been created + setSortOrder(LLConversationSort(gSavedSettings.getU32("ConversationSortOrder"))); + + mInitialized = true; + + // Add callbacks: + // We'll take care of view updates on idle + gIdleCallbacks.addFunction(idle, this); + // When display name option change, we need to reload all participant names + LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMContainer::processParticipantsStyleUpdate, this)); + + return TRUE; +} + +void LLFloaterIMContainer::onOpen(const LLSD& key) +{ + LLMultiFloater::onOpen(key); + openNearbyChat(); +} + +// virtual +void LLFloaterIMContainer::addFloater(LLFloater* floaterp, + BOOL select_added_floater, + LLTabContainer::eInsertionPoint insertion_point) +{ + if(!floaterp) return; + + // already here + if (floaterp->getHost() == this) + { + openFloater(floaterp->getKey()); + return; + } + + // Make sure the message panel is open when adding a floater or it stays mysteriously hidden + collapseMessagesPane(false); + + // Add the floater + LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); + + LLUUID session_id = floaterp->getKey(); + + LLIconCtrl* icon = 0; + + if(gAgent.isInGroup(session_id, TRUE)) + { + LLGroupIconCtrl::Params icon_params; + icon_params.group_id = session_id; + icon = LLUICtrlFactory::instance().create<LLGroupIconCtrl>(icon_params); + + mSessions[session_id] = floaterp; + floaterp->mCloseSignal.connect(boost::bind(&LLFloaterIMContainer::onCloseFloater, this, session_id)); + } + else + { LLUUID avatar_id = session_id.notNull()? + LLIMModel::getInstance()->getOtherParticipantID(session_id) : LLUUID(); + + LLAvatarIconCtrl::Params icon_params; + icon_params.avatar_id = avatar_id; + icon = LLUICtrlFactory::instance().create<LLAvatarIconCtrl>(icon_params); + + mSessions[session_id] = floaterp; + floaterp->mCloseSignal.connect(boost::bind(&LLFloaterIMContainer::onCloseFloater, this, session_id)); + } + + // forced resize of the floater + LLRect wrapper_rect = this->mTabContainer->getLocalRect(); + floaterp->setRect(wrapper_rect); + + mTabContainer->setTabImage(floaterp, icon); +} + + +void LLFloaterIMContainer::onCloseFloater(LLUUID& id) +{ + mSessions.erase(id); + setFocus(TRUE); +} + +// virtual +void LLFloaterIMContainer::computeResizeLimits(S32& new_min_width, S32& new_min_height) +{ + // possibly increase floater's minimum height according to children's minimums + for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + { + LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getPanelByIndex(tab_idx)); + if (floaterp) + { + new_min_height = llmax(new_min_height, floaterp->getMinHeight()); + } + } + + S32 conversations_pane_min_dim = mConversationsPane->getRelevantMinDim(); + S32 messages_pane_min_dim = mMessagesPane->getRelevantMinDim(); + + // set floater's minimum width according to relevant minimal children's dimensionals + new_min_width = conversations_pane_min_dim + messages_pane_min_dim + LLPANEL_BORDER_WIDTH*2; +} + +void LLFloaterIMContainer::onNewMessageReceived(const LLSD& data) +{ + LLUUID session_id = data["session_id"].asUUID(); + LLFloater* floaterp = get_ptr_in_map(mSessions, session_id); + LLFloater* current_floater = LLMultiFloater::getActiveFloater(); + + if(floaterp && current_floater && floaterp != current_floater) + { + if(LLMultiFloater::isFloaterFlashing(floaterp)) + LLMultiFloater::setFloaterFlashing(floaterp, FALSE); + LLMultiFloater::setFloaterFlashing(floaterp, TRUE); + } +} + +void LLFloaterIMContainer::onExpandCollapseButtonClicked() +{ + if (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed() + && gSavedPerAccountSettings.getBOOL("ConversationsExpandMessagePaneFirst")) + { + // Expand the messages pane from ultra minimized state + // if it was collapsed last in order. + collapseMessagesPane(false); + } + else + { + collapseConversationsPane(!mConversationsPane->isCollapsed()); + } + selectConversation(mSelectedSession); +} + +LLFloaterIMContainer* LLFloaterIMContainer::findInstance() +{ + return LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container"); +} + +LLFloaterIMContainer* LLFloaterIMContainer::getInstance() +{ + return LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); +} + +// Update all participants in the conversation lists +void LLFloaterIMContainer::processParticipantsStyleUpdate() +{ + // On each session in mConversationsItems + for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) + { + // Get the current session descriptors + LLConversationItem* session_model = it_session->second; + // Iterate through each model participant child + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = session_model->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = session_model->getChildrenEnd(); + while (current_participant_model != end_participant_model) + { + LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); + // Get the avatar name for this participant id from the cache and update the model + participant_model->fetchAvatarName(); + // Next participant + current_participant_model++; + } + } +} + +// static +void LLFloaterIMContainer::idle(void* user_data) +{ + LLFloaterIMContainer* self = static_cast<LLFloaterIMContainer*>(user_data); + + // Update the distance to agent in the nearby chat session if required + // Note: it makes no sense of course to update the distance in other session + if (self->mConversationViewModel.getSorter().getSortOrderParticipants() == LLConversationFilter::SO_DISTANCE) + { + self->setNearbyDistances(); + } + self->mConversationsRoot->update(); +} + +bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event) +{ + // For debug only + //std::ostringstream llsd_value; + //llsd_value << LLSDOStreamer<LLSDNotationFormatter>(event) << std::endl; + //llinfos << "LLFloaterIMContainer::onConversationModelEvent, event = " << llsd_value.str() << llendl; + // end debug + + // Note: In conversations, the model is not responsible for creating the view, which is a good thing. This means that + // the model could change substantially and the view could echo only a portion of this model (though currently the + // conversation view does echo the conversation model 1 to 1). + // Consequently, the participant views need to be created either by the session view or by the container panel. + // For the moment, we create them here, at the container level, to conform to the pattern implemented in llinventorypanel.cpp + // (see LLInventoryPanel::buildNewViews()). + + std::string type = event.get("type").asString(); + LLUUID session_id = event.get("session_uuid").asUUID(); + LLUUID participant_id = event.get("participant_uuid").asUUID(); + + LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,session_id)); + if (!session_view) + { + // We skip events that are not associated with a session + return false; + } + LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); + LLFloaterIMSessionTab *conversation_floater = (session_id.isNull() ? (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")) : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(session_id))); + + if (type == "remove_participant") + { + // Remove a participant view from the hierarchical conversation list + if (participant_view) + { + session_view->extractItem(participant_view); + delete participant_view; + session_view->refresh(); + mConversationsRoot->arrangeAll(); + } + // Remove a participant view from the conversation floater + if (conversation_floater) + { + conversation_floater->removeConversationViewParticipant(participant_id); + } + } + else if (type == "add_participant") + { + LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]); + LLConversationItemParticipant* participant_model = (session_model ? session_model->findParticipant(participant_id) : NULL); + if (!participant_view && session_model && participant_model) + { + LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(session_id); + if (session_id.isNull() || (im_sessionp && !im_sessionp->isP2PSessionType())) + { + participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(session_view); + participant_view->setVisible(TRUE); + } + } + // Add a participant view to the conversation floater + if (conversation_floater && participant_model) + { + conversation_floater->addConversationViewParticipant(participant_model); + } + } + else if (type == "update_participant") + { + // Update the participant view in the hierarchical conversation list + if (participant_view) + { + participant_view->refresh(); + } + // Update the participant view in the conversation floater + if (conversation_floater) + { + conversation_floater->updateConversationViewParticipant(participant_id); + } + } + else if (type == "update_session") + { + session_view->refresh(); + if (conversation_floater) + { + conversation_floater->refreshConversation(); + } + } + + mConversationViewModel.requestSortAll(); + mConversationsRoot->arrangeAll(); + + return false; +} + +void LLFloaterIMContainer::draw() +{ + if (mTabContainer->getTabCount() == 0) + { + // Do not close the container when every conversation is torn off because the user + // still needs the conversation list. Simply collapse the message pane in that case. + collapseMessagesPane(true); + } + LLFloater::draw(); +} + +void LLFloaterIMContainer::tabClose() +{ + if (mTabContainer->getTabCount() == 0) + { + // Do not close the container when every conversation is torn off because the user + // still needs the conversation list. Simply collapse the message pane in that case. + collapseMessagesPane(true); + } +} + +void LLFloaterIMContainer::setVisible(BOOL visible) +{ LLFloaterIMNearbyChat* nearby_chat; + if (visible) + { + // Make sure we have the Nearby Chat present when showing the conversation container + nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); + if (nearby_chat == NULL) + { + // If not found, force the creation of the nearby chat conversation panel + // *TODO: find a way to move this to XML as a default panel or something like that + LLSD name("nearby_chat"); + LLFloaterReg::toggleInstanceOrBringToFront(name); + } + openNearbyChat(); + } + + nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); + if (nearby_chat) + { + LLFloaterIMSessionTab::addToHost(LLUUID()); + } + + // We need to show/hide all the associated conversations that have been torn off + // (and therefore, are not longer managed by the multifloater), + // so that they show/hide with the conversations manager. + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + for (;widget_it != mConversationsWidgets.end(); ++widget_it) + { + LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); + if (widget) + { + widget->setVisibleIfDetached(visible); + } + } + + // Now, do the normal multifloater show/hide + LLMultiFloater::setVisible(visible); + +} + +void LLFloaterIMContainer::collapseMessagesPane(bool collapse) +{ + if (mMessagesPane->isCollapsed() == collapse) + { + return; + } + + if (collapse) + { + // Save the messages pane width before collapsing it. + gSavedPerAccountSettings.setS32("ConversationsMessagePaneWidth", mMessagesPane->getRect().getWidth()); + + // Save the order in which the panels are closed to reverse user's last action. + gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", mConversationsPane->isCollapsed()); + } + + // Save left pane rectangle before collapsing/expanding right pane. + LLRect prevRect = mConversationsPane->getRect(); + + // Show/hide the messages pane. + mConversationsStack->collapsePanel(mMessagesPane, collapse); + + if (!collapse) + { + // Make sure layout is updated before resizing conversation pane. + mConversationsStack->updateLayout(); + } + + updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); + if (!collapse) + { + // Restore conversation's pane previous width after expanding messages pane. + mConversationsPane->setTargetDim(prevRect.getWidth()); + } +} +void LLFloaterIMContainer::collapseConversationsPane(bool collapse) +{ + if (mConversationsPane->isCollapsed() == collapse) + { + return; + } + + LLView* button_panel = getChild<LLView>("conversations_pane_buttons_expanded"); + button_panel->setVisible(!collapse); + mExpandCollapseBtn->setImageOverlay(getString(collapse ? "expand_icon" : "collapse_icon")); + + if (collapse) + { + // Save the conversations pane width before collapsing it. + gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", mConversationsPane->getRect().getWidth()); + + // Save the order in which the panels are closed to reverse user's last action. + gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", !mMessagesPane->isCollapsed()); + } + + mConversationsStack->collapsePanel(mConversationsPane, collapse); + + S32 collapsed_width = mConversationsPane->getMinDim(); + updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - collapsed_width); + + for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + widget_it != mConversationsWidgets.end(); ++widget_it) + { + LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); + if (widget) + { + widget->toggleMinimizedMode(collapse); + + // force closing all open conversations when collapsing to minimized state + if (collapse) + { + widget->setOpen(false); + } +} + } +} + +void LLFloaterIMContainer::updateState(bool collapse, S32 delta_width) +{ + LLRect floater_rect = getRect(); + floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); + + // Set by_user = true so that reshaped rect is saved in user_settings. + setShape(floater_rect, true); + + updateResizeLimits(); + + bool is_left_pane_expanded = !mConversationsPane->isCollapsed(); + bool is_right_pane_expanded = !mMessagesPane->isCollapsed(); + + setCanResize(is_left_pane_expanded || is_right_pane_expanded); + setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); + + // force set correct size for the title after show/hide minimize button + LLRect cur_rect = getRect(); + LLRect force_rect = cur_rect; + force_rect.mRight = cur_rect.mRight + 1; + setRect(force_rect); + setRect(cur_rect); + + // restore floater's resize limits (prevent collapse when left panel is expanded) + if (is_left_pane_expanded && !is_right_pane_expanded) + { + S32 expanded_min_size = mConversationsPane->getExpandedMinDim(); + setResizeLimits(expanded_min_size, expanded_min_size); + } + +} + +void LLFloaterIMContainer::onAddButtonClicked() +{ + LLView * button = findChild<LLView>("conversations_pane_buttons_expanded")->findChild<LLButton>("add_btn"); + LLFloater* root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterIMContainer::onAvatarPicked, this, _1), TRUE, TRUE, TRUE, root_floater->getName(), button); + + if (picker && root_floater) + { + root_floater->addDependentFloater(picker); + } +} + +void LLFloaterIMContainer::onAvatarPicked(const uuid_vec_t& ids) +{ + if (ids.size() == 1) + { + LLAvatarActions::startIM(ids.back()); + } + else + { + LLAvatarActions::startConference(ids); + } +} + +void LLFloaterIMContainer::onCustomAction(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + if ("sort_sessions_by_type" == command) + { + setSortOrderSessions(LLConversationFilter::SO_SESSION_TYPE); + } + if ("sort_sessions_by_name" == command) + { + setSortOrderSessions(LLConversationFilter::SO_NAME); + } + if ("sort_sessions_by_recent" == command) + { + setSortOrderSessions(LLConversationFilter::SO_DATE); + } + if ("sort_participants_by_name" == command) + { + setSortOrderParticipants(LLConversationFilter::SO_NAME); + } + if ("sort_participants_by_recent" == command) + { + setSortOrderParticipants(LLConversationFilter::SO_DATE); + } + if ("sort_participants_by_distance" == command) + { + setSortOrderParticipants(LLConversationFilter::SO_DISTANCE); + } + if ("chat_preferences" == command) + { + LLFloaterPreference* floater_prefs = LLFloaterReg::showTypedInstance<LLFloaterPreference>("preferences"); + if (floater_prefs) + { + LLTabContainer* tab_container = floater_prefs->getChild<LLTabContainer>("pref core"); + LLPanel* chat_panel = tab_container->getPanelByName("chat"); + if (tab_container && chat_panel) + { + tab_container->selectTabPanel(chat_panel); + } + } + } +} + +BOOL LLFloaterIMContainer::isActionChecked(const LLSD& userdata) +{ + LLConversationSort order = mConversationViewModel.getSorter(); + std::string command = userdata.asString(); + if ("sort_sessions_by_type" == command) + { + return (order.getSortOrderSessions() == LLConversationFilter::SO_SESSION_TYPE); + } + if ("sort_sessions_by_name" == command) + { + return (order.getSortOrderSessions() == LLConversationFilter::SO_NAME); + } + if ("sort_sessions_by_recent" == command) + { + return (order.getSortOrderSessions() == LLConversationFilter::SO_DATE); + } + if ("sort_participants_by_name" == command) + { + return (order.getSortOrderParticipants() == LLConversationFilter::SO_NAME); + } + if ("sort_participants_by_recent" == command) + { + return (order.getSortOrderParticipants() == LLConversationFilter::SO_DATE); + } + if ("sort_participants_by_distance" == command) + { + return (order.getSortOrderParticipants() == LLConversationFilter::SO_DISTANCE); + } + + return FALSE; +} + +void LLFloaterIMContainer::setSortOrderSessions(const LLConversationFilter::ESortOrderType order) +{ + LLConversationSort old_order = mConversationViewModel.getSorter(); + if (order != old_order.getSortOrderSessions()) + { + old_order.setSortOrderSessions(order); + setSortOrder(old_order); + } +} + +void LLFloaterIMContainer::setSortOrderParticipants(const LLConversationFilter::ESortOrderType order) +{ + LLConversationSort old_order = mConversationViewModel.getSorter(); + if (order != old_order.getSortOrderParticipants()) + { + old_order.setSortOrderParticipants(order); + setSortOrder(old_order); + } +} + +void LLFloaterIMContainer::setSortOrder(const LLConversationSort& order) +{ + mConversationViewModel.setSorter(order); + mConversationsRoot->arrangeAll(); + // try to keep selection onscreen, even if it wasn't to start with + mConversationsRoot->scrollToShowSelection(); + + // Notify all conversation (torn off or not) of the change to the sort order + // Note: For the moment, the sort order is *unique* across all conversations. That might change in the future. + for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) + { + LLUUID session_id = it_session->first; + LLFloaterIMSessionTab *conversation_floater = (session_id.isNull() ? (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")) : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(session_id))); + if (conversation_floater) + { + conversation_floater->setSortOrder(order); + } + } + + gSavedSettings.setU32("ConversationSortOrder", (U32)order); +} + +void LLFloaterIMContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids) +{ + const std::set<LLFolderViewItem*> selectedItems = mConversationsRoot->getSelectionList(); + + std::set<LLFolderViewItem*>::const_iterator it = selectedItems.begin(); + const std::set<LLFolderViewItem*>::const_iterator it_end = selectedItems.end(); + LLConversationItem * conversationItem; + + for (; it != it_end; ++it) + { + conversationItem = static_cast<LLConversationItem *>((*it)->getViewModelItem()); + selected_uuids.push_back(conversationItem->getUUID()); + } +} + +const LLConversationItem * LLFloaterIMContainer::getCurSelectedViewModelItem() +{ + LLConversationItem * conversationItem = NULL; + + if(mConversationsRoot && + mConversationsRoot->getCurSelectedItem() && + mConversationsRoot->getCurSelectedItem()->getViewModelItem()) + { + conversationItem = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem()); + } + + return conversationItem; +} + +void LLFloaterIMContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) +{ + //Find the conversation floater associated with the selected id + const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); + + if(conversationItem->getType() == LLConversationItem::CONV_PARTICIPANT) + { + getSelectedUUIDs(selected_uuids); + } + //When a one-on-one conversation exists, retrieve the participant id from the conversation floater + else if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + { + LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(conversationItem->getUUID()); + LLUUID participantID = conversationFloater->getOtherParticipantUUID(); + selected_uuids.push_back(participantID); + } +} + +void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec_t& selectedIDS) +{ + if(selectedIDS.size() > 0) + { + const LLUUID& userID = selectedIDS.front(); + if(gAgent.getID() != userID) + { + if ("view_profile" == command) + { + LLAvatarActions::showProfile(userID); + } + else if("im" == command) + { + LLAvatarActions::startIM(userID); + } + else if("offer_teleport" == command) + { + LLAvatarActions::offerTeleport(selectedIDS); + } + else if("voice_call" == command) + { + LLAvatarActions::startCall(userID); + } + else if("chat_history" == command) + { + LLAvatarActions::viewChatHistory(userID); + } + else if("add_friend" == command) + { + LLAvatarActions::requestFriendshipDialog(userID); + } + else if("remove_friend" == command) + { + LLAvatarActions::removeFriendDialog(userID); + } + else if("invite_to_group" == command) + { + LLAvatarActions::inviteToGroup(userID); + } + else if("map" == command) + { + LLAvatarActions::showOnMap(userID); + } + else if("share" == command) + { + LLAvatarActions::share(userID); + } + else if("pay" == command) + { + LLAvatarActions::pay(userID); + } + else if("block_unblock" == command) + { + LLAvatarActions::toggleBlock(userID); + } + else if("selected" == command || "mute_all" == command || "unmute_all" == command) + { + moderateVoice(command, userID); + } + else if ("toggle_allow_text_chat" == command) + { + toggleAllowTextChat(userID); + } + } + } +} + +void LLFloaterIMContainer::doToSelectedConversation(const std::string& command, uuid_vec_t& selectedIDS) +{ + //Find the conversation floater associated with the selected id + const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); + LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(conversationItem->getUUID()); + + if(conversationFloater) + { + //Close the selected conversation + if("close_conversation" == command) + { + LLFloater::onClickClose(conversationFloater); + } + else if("open_voice_conversation" == command) + { + gIMMgr->startCall(conversationItem->getUUID()); + } + else if("disconnect_from_voice" == command) + { + gIMMgr->endCall(conversationItem->getUUID()); + } + else if("chat_history" == command) + { + const LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(conversationItem->getUUID()); + + if (NULL != session) + { + const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID; + LLFloaterReg::showInstance("preview_conversation", session_id, true); + } + } + else + { + doToParticipants(command, selectedIDS); + } + } +} + +void LLFloaterIMContainer::doToSelected(const LLSD& userdata) +{ + std::string command = userdata.asString(); + const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); + uuid_vec_t selected_uuids; + + if(conversationItem != NULL) + { + getParticipantUUIDs(selected_uuids); + + if(conversationItem->getType() == LLConversationItem::CONV_PARTICIPANT) + { + doToParticipants(command, selected_uuids); + } + else + { + doToSelectedConversation(command, selected_uuids); + } + } +} + +void LLFloaterIMContainer::doToSelectedGroup(const LLSD& userdata) +{ + std::string action = userdata.asString(); + LLUUID selected_group = getCurSelectedViewModelItem()->getUUID(); + + if (action == "group_profile") + { + LLGroupActions::show(selected_group); + } + else if (action == "activate_group") + { + LLGroupActions::activate(selected_group); + } + else if (action == "leave_group") + { + LLGroupActions::leave(selected_group); + } +} + +bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) +{ + std::string item = userdata.asString(); + uuid_vec_t uuids; + getParticipantUUIDs(uuids); + + if(item == std::string("can_activate_group")) + { + LLUUID selected_group_id = getCurSelectedViewModelItem()->getUUID(); + return gAgent.getGroupID() != selected_group_id; + } + + if(uuids.size() <= 0) + { + return false; + } + + // Note: can_block and can_delete is used only for one person selected menu + // so we don't need to go over all uuids. + + if (item == std::string("can_block")) + { + const LLUUID& id = uuids.front(); + return LLAvatarActions::canBlock(id); + } + else if (item == std::string("can_add")) + { + // We can add friends if: + // - there are selected people + // - and there are no friends among selection yet. + + //EXT-7389 - disable for more than 1 + if(uuids.size() > 1) + { + return false; + } + + bool result = true; + + uuid_vec_t::const_iterator + id = uuids.begin(), + uuids_end = uuids.end(); + + for (;id != uuids_end; ++id) + { + if ( LLAvatarActions::isFriend(*id) ) + { + result = false; + break; + } + } + + return result; + } + else if (item == std::string("can_delete")) + { + // We can remove friends if: + // - there are selected people + // - and there are only friends among selection. + + bool result = (uuids.size() > 0); + + uuid_vec_t::const_iterator + id = uuids.begin(), + uuids_end = uuids.end(); + + for (;id != uuids_end; ++id) + { + if ( !LLAvatarActions::isFriend(*id) ) + { + result = false; + break; + } + } + + return result; + } + else if (item == std::string("can_call")) + { + return LLAvatarActions::canCall(); + } + else if (item == std::string("can_show_on_map")) + { + const LLUUID& id = uuids.front(); + + return (LLAvatarTracker::instance().isBuddyOnline(id) && is_agent_mappable(id)) + || gAgent.isGodlike(); + } + else if(item == std::string("can_offer_teleport")) + { + return LLAvatarActions::canOfferTeleport(uuids); + } + else if("can_moderate_voice" == item || "can_allow_text_chat" == item || "can_mute" == item || "can_unmute" == item) + { + return enableModerateContextMenuItem(item); + } + + return false; +} + +bool LLFloaterIMContainer::checkContextMenuItem(const LLSD& userdata) +{ + std::string item = userdata.asString(); + uuid_vec_t mUUIDs; + getParticipantUUIDs(mUUIDs); + + if(mUUIDs.size() > 0 ) + { + if ("is_blocked" == item) + { + return LLAvatarActions::isBlocked(mUUIDs.front()); + } + else if ("is_allowed_text_chat" == item) + { + const LLSpeaker * speakerp = getSpeakerOfSelectedParticipant(getSpeakerMgrForSelectedParticipant()); + + if (NULL != speakerp) + { + return !speakerp->mModeratorMutedText; + } + } + } + + return false; +} + +void LLFloaterIMContainer::showConversation(const LLUUID& session_id) +{ + setVisibleAndFrontmost(false); + selectConversation(session_id); +} + +// Will select only the conversation item +void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) +{ + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); + if (widget) + { + (widget->getRoot())->setSelection(widget, FALSE, FALSE); + } +} + +// Synchronous select the conversation item and the conversation floater +BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget) +{ + BOOL handled = TRUE; + + /* widget processing */ + if (select_widget) + { + LLFolderViewItem* widget = mConversationsWidgets[session_id]; + if (widget && widget->getParentFolder()) + { + widget->getParentFolder()->setSelection(widget, FALSE, FALSE); + } + } + + /* floater processing */ + + if (session_id != getSelectedSession()) + { + // Store the active session + setSelectedSession(session_id); + + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); + + if (session_floater->getHost()) + { + // Always expand the message pane if the panel is hosted by the container + collapseMessagesPane(false); + // Switch to the conversation floater that is being selected + selectFloater(session_floater); + } + + // Set the focus on the selected floater + if (!session_floater->hasFocus()) + { + session_floater->setFocus(TRUE); + } + } + + return handled; +} + +void LLFloaterIMContainer::setTimeNow(const LLUUID& session_id, const LLUUID& participant_id) +{ + LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,session_id)); + if (item) + { + item->setTimeNow(participant_id); + mConversationViewModel.requestSortAll(); + mConversationsRoot->arrangeAll(); + } +} + +void LLFloaterIMContainer::setNearbyDistances() +{ + // Get the nearby chat session: that's the one with uuid nul + LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,LLUUID())); + if (item) + { + // Get the positions of the nearby avatars and their ids + std::vector<LLVector3d> positions; + uuid_vec_t avatar_ids; + LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); + // Get the position of the agent + const LLVector3d& me_pos = gAgent.getPositionGlobal(); + // For each nearby avatar, compute and update the distance + int avatar_count = positions.size(); + for (int i = 0; i < avatar_count; i++) + { + F64 dist = dist_vec_squared(positions[i], me_pos); + item->setDistance(avatar_ids[i],dist); + } + // Also does it for the agent itself + item->setDistance(gAgent.getID(),0.0f); + // Request resort + mConversationViewModel.requestSortAll(); + mConversationsRoot->arrangeAll(); + } +} + +LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/) +{ + bool is_nearby_chat = uuid.isNull(); + + // Stores the display name for the conversation line item + std::string display_name = is_nearby_chat ? LLTrans::getString("NearbyChatLabel") : LLIMModel::instance().getName(uuid); + + // Check if the item is not already in the list, exit (nothing to do) + // Note: this happens often, when reattaching a torn off conversation for instance + conversations_items_map::iterator item_it = mConversationsItems.find(uuid); + if (item_it != mConversationsItems.end()) + { + return item_it->second; + } + + // Remove the conversation item that might exist already: it'll be recreated anew further down anyway + // and nothing wrong will happen removing it if it doesn't exist + removeConversationListItem(uuid,false); + + // Create a conversation session model + LLConversationItemSession* item = NULL; + LLSpeakerMgr* speaker_manager = (is_nearby_chat ? (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()) : LLIMModel::getInstance()->getSpeakerManager(uuid)); + if (speaker_manager) + { + item = new LLParticipantList(speaker_manager, getRootViewModel()); + } + if (!item) + { + llwarns << "Couldn't create conversation session item : " << display_name << llendl; + return NULL; + } + item->renameItem(display_name); + item->updateParticipantName(NULL); + + mConversationsItems[uuid] = item; + + // Create a widget from it + LLConversationViewSession* widget = createConversationItemWidget(item); + mConversationsWidgets[uuid] = widget; + + // Add a new conversation widget to the root folder of the folder view + widget->addToFolder(mConversationsRoot); + widget->requestArrange(); + + LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(uuid); + + // Create the participants widgets now + // Note: usually, we do not get an updated avatar list at that point + if (uuid.isNull() || im_sessionp && !im_sessionp->isP2PSessionType()) + { + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); + while (current_participant_model != end_participant_model) + { + LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); + LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(widget); + current_participant_model++; + } + } + // Do that too for the conversation dialog + LLFloaterIMSessionTab *conversation_floater = (uuid.isNull() ? (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")) : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(uuid))); + if (conversation_floater) + { + conversation_floater->buildConversationViewParticipant(); + } + + // set the widget to minimized mode if conversations pane is collapsed + widget->toggleMinimizedMode(mConversationsPane->isCollapsed()); + + if (isWidgetSelected) + { + selectConversation(uuid); + // scroll to newly added item + mConversationsRoot->scrollToShowSelection(); + } + + return item; +} + +bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) +{ + // Delete the widget and the associated conversation item + // Note : since the mConversationsItems is also the listener to the widget, deleting + // the widget will also delete its listener + bool isWidgetSelected = false; + LLFolderViewItem* new_selection = NULL; + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); + if (widget) + { + isWidgetSelected = widget->isSelected(); + new_selection = mConversationsRoot->getNextFromChild(widget); + if(new_selection == NULL) + { + new_selection = mConversationsRoot->getPreviousFromChild(widget); + } + widget->destroyView(); + } + + // Suppress the conversation items and widgets from their respective maps + mConversationsItems.erase(uuid); + mConversationsWidgets.erase(uuid); + + // Don't let the focus fall IW, select and refocus on the first conversation in the list + if (change_focus) + { + setFocus(TRUE); + if(new_selection != NULL) + { + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem()); + if(vmi != NULL) + { + selectConversation(vmi->getUUID()); + } + } + } + return isWidgetSelected; +} + +LLConversationViewSession* LLFloaterIMContainer::createConversationItemWidget(LLConversationItem* item) +{ + LLConversationViewSession::Params params; + + params.name = item->getDisplayName(); + params.root = mConversationsRoot; + params.listener = item; + params.tool_tip = params.name; + params.container = this; + + return LLUICtrlFactory::create<LLConversationViewSession>(params); +} + +LLConversationViewParticipant* LLFloaterIMContainer::createConversationViewParticipant(LLConversationItem* item) +{ + LLConversationViewParticipant::Params params; + LLRect panel_rect = mConversationsListPanel->getRect(); + + params.name = item->getDisplayName(); + params.root = mConversationsRoot; + params.listener = item; + + //24 is the the current hight of an item (itemHeight) loaded from conversation_view_participant.xml. + params.rect = LLRect (0, 24, panel_rect.getWidth(), 0); + params.tool_tip = params.name; + params.participant_id = item->getUUID(); + params.folder_indentation = 42; + + return LLUICtrlFactory::create<LLConversationViewParticipant>(params); +} + +bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& userdata) +{ + // only group moderators can perform actions related to this "enable callback" + if (!isGroupModerator()) + { + return false; + } + + LLSpeaker * speakerp = getSpeakerOfSelectedParticipant(getSpeakerMgrForSelectedParticipant()); + if (NULL == speakerp) + { + return false; + } + + bool voice_channel = speakerp->isInVoiceChannel(); + + if ("can_moderate_voice" == userdata) + { + return voice_channel; + } + else if ("can_mute" == userdata) + { + return voice_channel && !isMuted(getCurSelectedViewModelItem()->getUUID()); + } + else if ("can_unmute" == userdata) + { + return voice_channel && isMuted(getCurSelectedViewModelItem()->getUUID()); + } + + // The last invoke is used to check whether the "can_allow_text_chat" will enabled + return LLVoiceClient::getInstance()->isParticipantAvatar(getCurSelectedViewModelItem()->getUUID()); +} + +bool LLFloaterIMContainer::isGroupModerator() +{ + LLSpeakerMgr * speaker_manager = getSpeakerMgrForSelectedParticipant(); + if (NULL == speaker_manager) + { + llwarns << "Speaker manager is missing" << llendl; + return false; + } + + // Is session a group call/chat? + if(gAgent.isInGroup(speaker_manager->getSessionID())) + { + LLSpeaker * speaker = speaker_manager->findSpeaker(gAgentID).get(); + + // Is agent a moderator? + return speaker && speaker->mIsModerator; + } + + return false; +} + +void LLFloaterIMContainer::moderateVoice(const std::string& command, const LLUUID& userID) +{ + if (!gAgent.getRegion()) return; + + if (command.compare("selected")) + { + moderateVoiceAllParticipants(command.compare("mute_all")); + } + else + { + moderateVoiceParticipant(userID, isMuted(userID)); + } +} + +bool LLFloaterIMContainer::isMuted(const LLUUID& avatar_id) +{ + const LLSpeaker * speakerp = getSpeakerOfSelectedParticipant(getSpeakerMgrForSelectedParticipant()); + return NULL == speakerp ? true : speakerp->mStatus == LLSpeaker::STATUS_MUTED; +} + +void LLFloaterIMContainer::moderateVoiceAllParticipants(bool unmute) +{ + LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr*>(getSpeakerMgrForSelectedParticipant()); + + if (NULL != speaker_managerp) + { + if (!unmute) + { + LLSD payload; + payload["session_id"] = speaker_managerp->getSessionID(); + LLNotificationsUtil::add("ConfirmMuteAll", LLSD(), payload, confirmMuteAllCallback); + return; + } + + speaker_managerp->moderateVoiceAllParticipants(unmute); + } +} + +// static +void LLFloaterIMContainer::confirmMuteAllCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + // if Cancel pressed + if (option == 1) + { + return; + } + + const LLSD& payload = notification["payload"]; + const LLUUID& session_id = payload["session_id"]; + + LLIMSpeakerMgr * speaker_manager = dynamic_cast<LLIMSpeakerMgr*> ( + LLIMModel::getInstance()->getSpeakerManager(session_id)); + if (speaker_manager) + { + speaker_manager->moderateVoiceAllParticipants(false); + } + + return; +} + +void LLFloaterIMContainer::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute) +{ + LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr *>(getSpeakerMgrForSelectedParticipant()); + + if (NULL != speaker_managerp) + { + speaker_managerp->moderateVoiceParticipant(avatar_id, unmute); + } +} + +LLSpeakerMgr * LLFloaterIMContainer::getSpeakerMgrForSelectedParticipant() +{ + LLFolderViewItem * selected_folder_itemp = mConversationsRoot->getCurSelectedItem(); + if (NULL == selected_folder_itemp) + { + llwarns << "Current selected item is null" << llendl; + return NULL; + } + + LLFolderViewFolder * conversation_itemp = selected_folder_itemp->getParentFolder(); + + conversations_widgets_map::const_iterator iter = mConversationsWidgets.begin(); + conversations_widgets_map::const_iterator end = mConversationsWidgets.end(); + const LLUUID * conversation_uuidp = NULL; + while(iter != end) + { + if (iter->second == conversation_itemp) + { + conversation_uuidp = &iter->first; + break; + } + ++iter; + } + if (NULL == conversation_uuidp) + { + llwarns << "Cannot find conversation item widget" << llendl; + return NULL; + } + + return conversation_uuidp->isNull() ? (LLSpeakerMgr *)LLLocalSpeakerMgr::getInstance() + : LLIMModel::getInstance()->getSpeakerManager(*conversation_uuidp); +} + +LLSpeaker * LLFloaterIMContainer::getSpeakerOfSelectedParticipant(LLSpeakerMgr * speaker_managerp) +{ + if (NULL == speaker_managerp) + { + llwarns << "Speaker manager is missing" << llendl; + return NULL; + } + + const LLConversationItem * participant_itemp = getCurSelectedViewModelItem(); + if (NULL == participant_itemp) + { + llwarns << "Cannot evaluate current selected view model item" << llendl; + return NULL; + } + + return speaker_managerp->findSpeaker(participant_itemp->getUUID()); +} + +void LLFloaterIMContainer::toggleAllowTextChat(const LLUUID& participant_uuid) +{ + LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr*>(getSpeakerMgrForSelectedParticipant()); + if (NULL != speaker_managerp) + { + speaker_managerp->toggleAllowTextChat(participant_uuid); + } +} + +void LLFloaterIMContainer::openNearbyChat() +{ + // If there's only one conversation in the container and that conversation is the nearby chat + //(which it should be...), open it so to make the list of participants visible. This happens to be the most common case when opening the Chat floater. + if(mConversationsItems.size() == 1) + { + LLConversationViewSession* nearby_chat = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[LLUUID()]); + if (nearby_chat) + { + nearby_chat->setOpen(TRUE); + } + } +} + +void LLFloaterIMContainer::onNearbyChatClosed() +{ + // If nearby chat is the only remaining conversation and it is closed, close whole conversation floater as well + if (mConversationsItems.size() == 1) + closeFloater(); +} + +// EOF diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h new file mode 100644 index 0000000000..f65e946dad --- /dev/null +++ b/indra/newview/llfloaterimcontainer.h @@ -0,0 +1,178 @@ +/** + * @file llfloaterimcontainer.h + * @brief Multifloater containing active IM sessions in separate tab container tabs + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERIMCONTAINER_H +#define LL_LLFLOATERIMCONTAINER_H + +#include <map> +#include <vector> + +#include "llimview.h" +#include "llevents.h" +#include "llfloater.h" +#include "llmultifloater.h" +#include "llavatarpropertiesprocessor.h" +#include "llgroupmgr.h" +#include "lltrans.h" +#include "llconversationmodel.h" +#include "llconversationview.h" + +class LLButton; +class LLLayoutPanel; +class LLLayoutStack; +class LLTabContainer; +class LLFloaterIMContainer; +class LLSpeaker; +class LLSpeakerMgr; + +class LLFloaterIMContainer + : public LLMultiFloater + , public LLIMSessionObserver +{ +public: + LLFloaterIMContainer(const LLSD& seed); + virtual ~LLFloaterIMContainer(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void draw(); + /*virtual*/ void setVisible(BOOL visible); + void onCloseFloater(LLUUID& id); + + /*virtual*/ void addFloater(LLFloater* floaterp, + BOOL select_added_floater, + LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); + + void showConversation(const LLUUID& session_id); + void selectConversation(const LLUUID& session_id); + BOOL selectConversationPair(const LLUUID& session_id, bool select_widget); + + /*virtual*/ void tabClose(); + + static LLFloater* getCurrentVoiceFloater(); + static LLFloaterIMContainer* findInstance(); + static LLFloaterIMContainer* getInstance(); + + static void onCurrentChannelChanged(const LLUUID& session_id); + + void collapseMessagesPane(bool collapse); + + // Callbacks + static void idle(void* user_data); + + // LLIMSessionObserver observe triggers + /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id); + /*virtual*/ void sessionRemoved(const LLUUID& session_id); + /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); + + LLConversationViewModel& getRootViewModel() { return mConversationViewModel; } + LLUUID getSelectedSession() { return mSelectedSession; } + void setSelectedSession(LLUUID sessionID) { mSelectedSession = sessionID; } + LLConversationItem* getSessionModel(const LLUUID& session_id) { return get_ptr_in_map(mConversationsItems,session_id); } + LLConversationSort& getSortOrder() { return mConversationViewModel.getSorter(); } + + void onNearbyChatClosed(); + +private: + typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; + avatarID_panel_map_t mSessions; + boost::signals2::connection mNewMessageConnection; + + /*virtual*/ void computeResizeLimits(S32& new_min_width, S32& new_min_height); + + void onNewMessageReceived(const LLSD& data); + + void onExpandCollapseButtonClicked(); + void processParticipantsStyleUpdate(); + + void collapseConversationsPane(bool collapse); + + void updateState(bool collapse, S32 delta_width); + + void onAddButtonClicked(); + void onAvatarPicked(const uuid_vec_t& ids); + + BOOL isActionChecked(const LLSD& userdata); + void onCustomAction (const LLSD& userdata); + void setSortOrderSessions(const LLConversationFilter::ESortOrderType order); + void setSortOrderParticipants(const LLConversationFilter::ESortOrderType order); + void setSortOrder(const LLConversationSort& order); + + void getSelectedUUIDs(uuid_vec_t& selected_uuids); + const LLConversationItem * getCurSelectedViewModelItem(); + void getParticipantUUIDs(uuid_vec_t& selected_uuids); + void doToSelected(const LLSD& userdata); + void doToSelectedConversation(const std::string& command, uuid_vec_t& selectedIDS); + void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS); + void doToSelectedGroup(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); + bool enableContextMenuItem(const LLSD& userdata); + + static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response); + bool enableModerateContextMenuItem(const std::string& userdata); + LLSpeaker * getSpeakerOfSelectedParticipant(LLSpeakerMgr * speaker_managerp); + LLSpeakerMgr * getSpeakerMgrForSelectedParticipant(); + bool isGroupModerator(); + bool isMuted(const LLUUID& avatar_id); + void moderateVoice(const std::string& command, const LLUUID& userID); + void moderateVoiceAllParticipants(bool unmute); + void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); + void toggleAllowTextChat(const LLUUID& participant_uuid); + void openNearbyChat(); + + LLButton* mExpandCollapseBtn; + LLLayoutPanel* mMessagesPane; + LLLayoutPanel* mConversationsPane; + LLLayoutStack* mConversationsStack; + + bool mInitialized; + + LLUUID mSelectedSession; + + // Conversation list implementation +public: + bool removeConversationListItem(const LLUUID& uuid, bool change_focus = true); + LLConversationItem* addConversationListItem(const LLUUID& uuid, bool isWidgetSelected = false); + void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); + void setNearbyDistances(); + +private: + LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); + LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item); + bool onConversationModelEvent(const LLSD& event); + + // Conversation list data + LLPanel* mConversationsListPanel; // This is the main widget we add conversation widget to + conversations_items_map mConversationsItems; + conversations_widgets_map mConversationsWidgets; + LLConversationViewModel mConversationViewModel; + LLFolderView* mConversationsRoot; + LLEventStream mConversationsEventStream; +}; + +#endif // LL_LLFLOATERIMCONTAINER_H diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp new file mode 100644 index 0000000000..5867eb3e84 --- /dev/null +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -0,0 +1,867 @@ +/** + * @file LLFloaterIMNearbyChat.cpp + * @brief LLFloaterIMNearbyChat class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "message.h" + +#include "lliconctrl.h" +#include "llappviewer.h" +#include "llchatentry.h" +#include "llfloaterreg.h" +#include "lltrans.h" +#include "llfloaterimcontainer.h" +#include "llfloatersidepanelcontainer.h" +#include "llfocusmgr.h" +#include "lllogchat.h" +#include "llresizebar.h" +#include "llresizehandle.h" +#include "lldraghandle.h" +#include "llmenugl.h" +#include "llviewermenu.h" // for gMenuHolder +#include "llfloaterimnearbychathandler.h" +#include "llchannelmanager.h" +#include "llchathistory.h" +#include "llstylemap.h" +#include "llavatarnamecache.h" +#include "llfloaterreg.h" +#include "lltrans.h" + +#include "llfirstuse.h" +#include "llfloaterimnearbychat.h" +#include "llagent.h" // gAgent +#include "llgesturemgr.h" +#include "llmultigesture.h" +#include "llkeyboard.h" +#include "llanimationstates.h" +#include "llviewerstats.h" +#include "llcommandhandler.h" +#include "llviewercontrol.h" +#include "llnavigationbar.h" +#include "llwindow.h" +#include "llviewerwindow.h" +#include "llrootview.h" +#include "llviewerchat.h" +#include "lltranslate.h" + +S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0; + +const S32 EXPANDED_HEIGHT = 266; +const S32 COLLAPSED_HEIGHT = 60; +const S32 EXPANDED_MIN_HEIGHT = 150; + +// legacy callback glue +void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); + +struct LLChatTypeTrigger { + std::string name; + EChatType type; +}; + +static LLChatTypeTrigger sChatTypeTriggers[] = { + { "/whisper" , CHAT_TYPE_WHISPER}, + { "/shout" , CHAT_TYPE_SHOUT} +}; + + +LLFloaterIMNearbyChat::LLFloaterIMNearbyChat(const LLSD& llsd) +: LLFloaterIMSessionTab(llsd), + //mOutputMonitor(NULL), + mSpeakerMgr(NULL), + mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) +{ + mIsP2PChat = false; + mIsNearbyChat = true; + setIsChrome(TRUE); + mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); + mSessionID = LLUUID(); +} + +//static +LLFloaterIMNearbyChat* LLFloaterIMNearbyChat::buildFloater(const LLSD& key) +{ + LLFloaterReg::getInstance("im_container"); + return new LLFloaterIMNearbyChat(key); +} + +//virtual +BOOL LLFloaterIMNearbyChat::postBuild() +{ + setIsSingleInstance(TRUE); + BOOL result = LLFloaterIMSessionTab::postBuild(); + mInputEditor->setCommitCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxCommit, this)); + mInputEditor->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this)); + mInputEditor->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); + mInputEditor->setFocusReceivedCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxFocusReceived, this)); + mInputEditor->setLabel(LLTrans::getString("NearbyChatTitle")); + +// mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); +// mOutputMonitor->setVisible(FALSE); + + // Register for font change notifications + LLViewerChat::setFontChangedCallback(boost::bind(&LLFloaterIMNearbyChat::onChatFontChange, this, _1)); + + // title must be defined BEFORE call addConversationListItem() because + // it is used for show the item's name in the conversations list + setTitle(LLTrans::getString("NearbyChatTitle")); + + //for menu + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + + enable_registrar.add("NearbyChat.Check", boost::bind(&LLFloaterIMNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); + registrar.add("NearbyChat.Action", boost::bind(&LLFloaterIMNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); + + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if(menu) + { + mPopupMenuHandle = menu->getHandle(); + } + + // obsolete, but may be needed for backward compatibility? + gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); + + if (gSavedPerAccountSettings.getBOOL("LogShowHistory")) + { + loadHistory(); + } + + return result; +} + +// virtual +void LLFloaterIMNearbyChat::refresh() +{ + displaySpeakingIndicator(); + updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); + + // *HACK: Update transparency type depending on whether our children have focus. + // This is needed because this floater is chrome and thus cannot accept focus, so + // the transparency type setting code from LLFloater::setFocus() isn't reached. + if (getTransparencyType() != TT_DEFAULT) + { + setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE); + } +} + +void LLFloaterIMNearbyChat::onNearbySpeakers() +{ + LLSD param; + param["people_panel_tab_name"] = "nearby_panel"; + LLFloaterSidePanelContainer::showPanel("people", "panel_people", param); +} + +void LLFloaterIMNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata) +{ +} + +bool LLFloaterIMNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata) +{ + std::string str = userdata.asString(); + if(str == "nearby_people") + onNearbySpeakers(); + return false; +} + + +BOOL LLFloaterIMNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask) +{ + //fix for EXT-6625 + //highlight NearbyChat history whenever mouseclick happen in NearbyChat + //setting focus to eidtor will force onFocusLost() call that in its turn will change + //background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. + + if(mChatHistory) + { + mChatHistory->setFocus(TRUE); + } + + BOOL handled = LLPanel::handleMouseDown(x, y, mask); + setFocus(handled); + return handled; +} + +void LLFloaterIMNearbyChat::reloadMessages() +{ + mChatHistory->clear(); + + LLSD do_not_log; + do_not_log["do_not_log"] = true; + for(std::vector<LLChat>::iterator it = mMessageArchive.begin();it!=mMessageArchive.end();++it) + { + // Update the messages without re-writing them to a log file. + addMessage(*it,false, do_not_log); + } +} + +void LLFloaterIMNearbyChat::loadHistory() +{ + LLSD do_not_log; + do_not_log["do_not_log"] = true; + + std::list<LLSD> history; + LLLogChat::loadChatHistory("chat", history); + + std::list<LLSD>::const_iterator it = history.begin(); + while (it != history.end()) + { + const LLSD& msg = *it; + + std::string from = msg[IM_FROM]; + LLUUID from_id; + if (msg[IM_FROM_ID].isDefined()) + { + from_id = msg[IM_FROM_ID].asUUID(); + } + else + { + std::string legacy_name = gCacheName->buildLegacyName(from); + gCacheName->getUUID(legacy_name, from_id); + } + + LLChat chat; + chat.mFromName = from; + chat.mFromID = from_id; + chat.mText = msg[IM_TEXT].asString(); + chat.mTimeStr = msg[IM_TIME].asString(); + chat.mChatStyle = CHAT_STYLE_HISTORY; + + chat.mSourceType = CHAT_SOURCE_AGENT; + if (from_id.isNull() && SYSTEM_FROM == from) + { + chat.mSourceType = CHAT_SOURCE_SYSTEM; + + } + else if (from_id.isNull()) + { + chat.mSourceType = isWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT; + } + + addMessage(chat, true, do_not_log); + + it++; + } +} + +void LLFloaterIMNearbyChat::removeScreenChat() +{ + LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); + if(chat_channel) + { + chat_channel->removeToastsFromChannel(); + } +} + + +void LLFloaterIMNearbyChat::setVisible(BOOL visible) +{ + LLFloaterIMSessionTab::setVisible(visible); + + if(visible) + { + removeScreenChat(); + } + setFocus(visible); +} + +// virtual +void LLFloaterIMNearbyChat::onTearOffClicked() +{ + LLFloaterIMSessionTab::onTearOffClicked(); + + // see CHUI-170: Save torn-off state of the nearby chat between sessions + BOOL in_the_multifloater = !isTornOff(); + gSavedSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater); +} + + +// virtual +void LLFloaterIMNearbyChat::onOpen(const LLSD& key) +{ + LLFloaterIMSessionTab::onOpen(key); + showTranslationCheckbox(LLTranslate::isTranslationConfigured()); +} + +// virtual +void LLFloaterIMNearbyChat::onClose(bool app_quitting) +{ + // Override LLFloaterIMSessionTab::onClose() so that Nearby Chat is not removed from the conversation floater +} + +// virtual +void LLFloaterIMNearbyChat::onClickCloseBtn() +{ + if (!isTornOff()) + return; + onTearOffClicked(); + + LLFloaterIMContainer *im_box = LLFloaterIMContainer::findInstance(); + if (im_box) + { + im_box->onNearbyChatClosed(); + } +} + +void LLFloaterIMNearbyChat::onChatFontChange(LLFontGL* fontp) +{ + // Update things with the new font whohoo + if (mInputEditor) + { + mInputEditor->setFont(fontp); + } +} + + +void LLFloaterIMNearbyChat::show() +{ + if (isChatMultiTab()) + { + openFloater(getKey()); + } +} + +bool LLFloaterIMNearbyChat::isChatVisible() const +{ + bool isVisible = false; + LLFloaterIMContainer* im_box = LLFloaterIMContainer::getInstance(); + // Is the IM floater container ever null? + llassert(im_box != NULL); + if (im_box != NULL) + { + isVisible = + isChatMultiTab() && gSavedSettings.getBOOL("NearbyChatIsNotTornOff")? + im_box->getVisible() && !im_box->isMinimized() : + getVisible() && !isMinimized(); + } + + return isVisible; +} + +void LLFloaterIMNearbyChat::showHistory() +{ + openFloater(); + setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); +} + +std::string LLFloaterIMNearbyChat::getCurrentChat() +{ + return mInputEditor ? mInputEditor->getText() : LLStringUtil::null; +} + +// virtual +BOOL LLFloaterIMNearbyChat::handleKeyHere( KEY key, MASK mask ) +{ + BOOL handled = FALSE; + + if( KEY_RETURN == key && mask == MASK_CONTROL) + { + // shout + sendChat(CHAT_TYPE_SHOUT); + handled = TRUE; + } + + return handled; +} + +BOOL LLFloaterIMNearbyChat::matchChatTypeTrigger(const std::string& in_str, std::string* out_str) +{ + U32 in_len = in_str.length(); + S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); + + bool string_was_found = false; + + for (S32 n = 0; n < cnt && !string_was_found; n++) + { + if (in_len <= sChatTypeTriggers[n].name.length()) + { + std::string trigger_trunc = sChatTypeTriggers[n].name; + LLStringUtil::truncate(trigger_trunc, in_len); + + if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) + { + *out_str = sChatTypeTriggers[n].name; + string_was_found = true; + } + } + } + + return string_was_found; +} + +void LLFloaterIMNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userdata) +{ + LLFirstUse::otherAvatarChatFirst(false); + + LLFloaterIMNearbyChat* self = (LLFloaterIMNearbyChat *)userdata; + + LLWString raw_text = self->mInputEditor->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 (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) + { + std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); + self->mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part + + // Select to end of line, starting from the character + // after the last one the user typed. + self->mInputEditor->selectNext(rest_of_match, false); + } + else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) + { + std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); + self->mInputEditor->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part + self->mInputEditor->endOfDoc(); + } + + //llinfos << "GESTUREDEBUG " << trigger + // << " len " << length + // << " outlen " << out_str.getLength() + // << llendl; + } +} + +// static +void LLFloaterIMNearbyChat::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) +{ + // stop typing animation + gAgent.stopTyping(); +} + +void LLFloaterIMNearbyChat::onChatBoxFocusReceived() +{ + mInputEditor->setEnabled(!gDisconnected); +} + +EChatType LLFloaterIMNearbyChat::processChatTypeTriggers(EChatType type, std::string &str) +{ + U32 length = str.length(); + S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); + + for (S32 n = 0; n < cnt; n++) + { + if (length >= sChatTypeTriggers[n].name.length()) + { + std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length()); + + if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name)) + { + U32 trigger_length = sChatTypeTriggers[n].name.length(); + + // It's to remove space after trigger name + if (length > trigger_length && str[trigger_length] == ' ') + trigger_length++; + + str = str.substr(trigger_length, length); + + if (CHAT_TYPE_NORMAL == type) + return sChatTypeTriggers[n].type; + else + break; + } + } + } + + return type; +} + +void LLFloaterIMNearbyChat::sendChat( EChatType type ) +{ + if (mInputEditor) + { + LLWString text = mInputEditor->getWText(); + LLWStringUtil::trim(text); + LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. + if (!text.empty()) + { + // 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 + LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); + } + else + { + utf8_revised_text = utf8text; + } + + utf8_revised_text = utf8str_trim(utf8_revised_text); + + type = processChatTypeTriggers(type, utf8_revised_text); + + if (!utf8_revised_text.empty()) + { + // Chat with animation + sendChatFromViewer(utf8_revised_text, type, TRUE); + } + } + + mInputEditor->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 LLFloaterIMNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +{ + appendMessage(chat, args); + + if(archive) + { + mMessageArchive.push_back(chat); + if(mMessageArchive.size()>200) + mMessageArchive.erase(mMessageArchive.begin()); + } + + // logging + if (!args["do_not_log"].asBoolean() + && gSavedPerAccountSettings.getBOOL("LogNearbyChat")) + { + std::string from_name = chat.mFromName; + + if (chat.mSourceType == CHAT_SOURCE_AGENT) + { + // if the chat is coming from an agent, log the complete name + LLAvatarName av_name; + LLAvatarNameCache::get(chat.mFromID, &av_name); + + if (!av_name.mIsDisplayNameDefault) + { + from_name = av_name.getCompleteName(); + } + } + + LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText); + } +} + + +void LLFloaterIMNearbyChat::onChatBoxCommit() +{ + if (mInputEditor->getText().length() > 0) + { + sendChat(CHAT_TYPE_NORMAL); + } + + gAgent.stopTyping(); +} + +void LLFloaterIMNearbyChat::displaySpeakingIndicator() +{ + LLSpeakerMgr::speaker_list_t speaker_list; + LLUUID id; + + id.setNull(); + mSpeakerMgr->update(TRUE); + mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); + + for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) + { + LLPointer<LLSpeaker> s = *i; + if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) + { + id = s->mID; + break; + } + } + + if (!id.isNull()) + { + //mOutputMonitor->setVisible(TRUE); + //mOutputMonitor->setSpeakerId(id); + } + else + { + //mOutputMonitor->setVisible(FALSE); + } +} + +void LLFloaterIMNearbyChat::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) +{ + sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate); +} + +void LLFloaterIMNearbyChat::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 +bool LLFloaterIMNearbyChat::isWordsName(const std::string& name) +{ + // checking to see if it's display name plus username in parentheses + S32 open_paren = name.find(" (", 0); + S32 close_paren = name.find(')', 0); + + if (open_paren != std::string::npos && + close_paren == name.length()-1) + { + return true; + } + else + { + //checking for a single space + S32 pos = name.find(' ', 0); + return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos; + } +} + +// static +void LLFloaterIMNearbyChat::startChat(const char* line) +{ + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); + if (nearby_chat) + { + nearby_chat->show(); + nearby_chat->setVisible(TRUE); + nearby_chat->setFocus(TRUE); + nearby_chat->mInputEditor->setFocus(TRUE); + + if (line) + { + std::string line_string(line); + nearby_chat->mInputEditor->setText(line_string); + } + + nearby_chat->mInputEditor->endOfDoc(); + } +} + +// Exit "chat mode" and do the appropriate focus changes +// static +void LLFloaterIMNearbyChat::stopChat() +{ + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); + if (nearby_chat) + { + nearby_chat->mInputEditor->setFocus(FALSE); + gAgent.stopTyping(); + } +} + +// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20. +// Otherwise returns input and channel 0. +LLWString LLFloaterIMNearbyChat::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 LLChatCommandHandler : public LLCommandHandler +{ +public: + // not allowed from outside the app + LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } + + // Your code here + bool handle(const LLSD& tokens, const LLSD& query_map, + LLMediaCtrl* web) + { + bool retval = false; + // Need at least 2 tokens to have a valid message. + if (tokens.size() < 2) + { + retval = false; + } + else + { + S32 channel = tokens[0].asInteger(); + // VWR-19499 Restrict function to chat channels greater than 0. + if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG)) + { + retval = true; + // Send unescaped message, see EXT-6353. + std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); + send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); + } + else + { + retval = false; + // Tell us this is an unsupported SLurl. + } + } + return retval; + } +}; + +// Creating the object registers with the dispatcher. +LLChatCommandHandler gChatHandler; diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h new file mode 100644 index 0000000000..1479746fbd --- /dev/null +++ b/indra/newview/llfloaterimnearbychat.h @@ -0,0 +1,125 @@ +/** + * @file llfloaterimnearbychat.h + * @brief LLFloaterIMNearbyChat class definition + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERIMNEARBYCHAT_H +#define LL_LLFLOATERIMNEARBYCHAT_H + +#include "llfloaterimsessiontab.h" +#include "llcombobox.h" +#include "llgesturemgr.h" +#include "llchat.h" +#include "llvoiceclient.h" +#include "lloutputmonitorctrl.h" +#include "llspeakers.h" +#include "llscrollbar.h" +#include "llviewerchat.h" +#include "llpanel.h" + +class LLResizeBar; + +class LLFloaterIMNearbyChat + : public LLFloaterIMSessionTab +{ +public: + // constructor for inline chat-bars (e.g. hosted in chat history window) + LLFloaterIMNearbyChat(const LLSD& key = LLSD(LLUUID())); + ~LLFloaterIMNearbyChat() {} + + static LLFloaterIMNearbyChat* buildFloater(const LLSD& key); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClose(bool app_quitting); + /*virtual*/ void setVisible(BOOL visible); + + void loadHistory(); + void reloadMessages(); + void removeScreenChat(); + + void addToHost(); + void show(); + bool isChatVisible() const; + + /** @param archive true - to save a message to the chat history log */ + void addMessage (const LLChat& message,bool archive = true, const LLSD &args = LLSD()); + void onNearbyChatContextMenuItemClicked(const LLSD& userdata); + bool onNearbyChatCheckContextMenuItem(const LLSD& userdata); + + LLChatEntry* getChatBox() { return mInputEditor; } + + std::string getCurrentChat(); + + virtual BOOL handleKeyHere( KEY key, MASK mask ); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + + 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); + + static bool isWordsName(const std::string& name); + + void showHistory(); + +protected: + static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); + static void onChatBoxKeystroke(LLTextEditor* caller, void* userdata); + static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); + void onChatBoxFocusReceived(); + + void sendChat( EChatType type ); + void onChatBoxCommit(); + void onChatFontChange(LLFontGL* fontp); + + /*virtual*/ void onTearOffClicked(); + /*virtual*/ void onClickCloseBtn(); + + static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); + EChatType processChatTypeTriggers(EChatType type, std::string &str); + + void displaySpeakingIndicator(); + + // Which non-zero channel did we last chat on? + static S32 sLastSpecialChatChannel; + + LLOutputMonitorCtrl* mOutputMonitor; + LLLocalSpeakerMgr* mSpeakerMgr; + + S32 mExpandedHeight; + +private: + + void onNearbySpeakers (); + + /*virtual*/ void refresh(); + + LLHandle<LLView> mPopupMenuHandle; + std::vector<LLChat> mMessageArchive; + +}; + +#endif // LL_LLFLOATERIMNEARBYCHAT_H diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp new file mode 100644 index 0000000000..0dfaa9174b --- /dev/null +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -0,0 +1,630 @@ +/** + * @file LLFloaterIMNearbyChatHandler.cpp + * @brief Nearby chat chat managment + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llagentdata.h" // for gAgentID +#include "llfloaterimnearbychathandler.h" + +#include "llchatitemscontainerctrl.h" +#include "llfirstuse.h" +#include "llfloaterscriptdebug.h" +#include "llhints.h" +#include "llfloaterimnearbychat.h" +#include "llrecentpeople.h" + +#include "llviewercontrol.h" + +#include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance +#include "llviewerwindow.h"//for screen channel position +#include "llfloaterimnearbychat.h" +#include "llrootview.h" +#include "lllayoutstack.h" + +//add LLFloaterIMNearbyChatHandler to LLNotificationsUI namespace +using namespace LLNotificationsUI; + +static LLFloaterIMNearbyChatToastPanel* createToastPanel() +{ + LLFloaterIMNearbyChatToastPanel* item = LLFloaterIMNearbyChatToastPanel::createInstance(); + return item; +} + + +//----------------------------------------------------------------------------------------------- +//LLFloaterIMNearbyChatScreenChannel +//----------------------------------------------------------------------------------------------- + +class LLFloaterIMNearbyChatScreenChannel: public LLScreenChannelBase +{ + LOG_CLASS(LLFloaterIMNearbyChatScreenChannel); +public: + typedef std::vector<LLHandle<LLToast> > toast_vec_t; + typedef std::list<LLHandle<LLToast> > toast_list_t; + + LLFloaterIMNearbyChatScreenChannel(const Params& p) + : LLScreenChannelBase(p) + { + mStopProcessing = false; + + LLControlVariable* ctrl = gSavedSettings.getControl("NearbyToastLifeTime").get(); + if (ctrl) + { + ctrl->getSignal()->connect(boost::bind(&LLFloaterIMNearbyChatScreenChannel::updateToastsLifetime, this)); + } + + ctrl = gSavedSettings.getControl("NearbyToastFadingTime").get(); + if (ctrl) + { + ctrl->getSignal()->connect(boost::bind(&LLFloaterIMNearbyChatScreenChannel::updateToastFadingTime, this)); + } + } + + void addChat (LLSD& chat); + void arrangeToasts (); + + typedef boost::function<LLFloaterIMNearbyChatToastPanel* (void )> create_toast_panel_callback_t; + void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;} + + void onToastDestroyed (LLToast* toast, bool app_quitting); + void onToastFade (LLToast* toast); + + void redrawToasts() + { + arrangeToasts(); + } + + // hide all toasts from screen, but not remove them from a channel + // removes all toasts from a channel + virtual void removeToastsFromChannel() + { + for(toast_vec_t::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it) + { + addToToastPool(it->get()); + } + m_active_toasts.clear(); + }; + + virtual void deleteAllChildren() + { + LL_DEBUGS("NearbyChat") << "Clearing toast pool" << llendl; + m_toast_pool.clear(); + m_active_toasts.clear(); + LLScreenChannelBase::deleteAllChildren(); + } + +protected: + void deactivateToast(LLToast* toast); + void addToToastPool(LLToast* toast) + { + if (!toast) return; + LL_DEBUGS("NearbyChat") << "Pooling toast" << llendl; + toast->setVisible(FALSE); + toast->stopTimer(); + toast->setIsHidden(true); + + // Nearby chat toasts that are hidden, not destroyed. They are collected to the toast pool, so that + // they can be used next time, this is done for performance. But if the toast lifetime was changed + // (from preferences floater (STORY-36)) while it was shown (at this moment toast isn't in the pool yet) + // changes don't take affect. + // So toast's lifetime should be updated each time it's added to the pool. Otherwise viewer would have + // to be restarted so that changes take effect. + toast->setLifetime(gSavedSettings.getS32("NearbyToastLifeTime")); + toast->setFadingTime(gSavedSettings.getS32("NearbyToastFadingTime")); + m_toast_pool.push_back(toast->getHandle()); + } + + void createOverflowToast(S32 bottom, F32 timer); + + void updateToastsLifetime(); + + void updateToastFadingTime(); + + create_toast_panel_callback_t m_create_toast_panel_callback_t; + + bool createPoolToast(); + + toast_vec_t m_active_toasts; + toast_list_t m_toast_pool; + + bool mStopProcessing; + bool mChannelRect; +}; + + + +//----------------------------------------------------------------------------------------------- +// LLFloaterIMNearbyChatToast +//----------------------------------------------------------------------------------------------- + +// We're deriving from LLToast to be able to override onClose() +// in order to handle closing nearby chat toasts properly. +class LLFloaterIMNearbyChatToast : public LLToast +{ + LOG_CLASS(LLFloaterIMNearbyChatToast); +public: + LLFloaterIMNearbyChatToast(const LLToast::Params& p, LLFloaterIMNearbyChatScreenChannel* nc_channelp) + : LLToast(p), + mNearbyChatScreenChannelp(nc_channelp) + { + } + + /*virtual*/ void onClose(bool app_quitting); + +private: + LLFloaterIMNearbyChatScreenChannel* mNearbyChatScreenChannelp; +}; + +//----------------------------------------------------------------------------------------------- +// LLFloaterIMNearbyChatScreenChannel +//----------------------------------------------------------------------------------------------- + +void LLFloaterIMNearbyChatScreenChannel::deactivateToast(LLToast* toast) +{ + toast_vec_t::iterator pos = std::find(m_active_toasts.begin(), m_active_toasts.end(), toast->getHandle()); + + if (pos == m_active_toasts.end()) + { + llassert(pos == m_active_toasts.end()); + return; + } + + LL_DEBUGS("NearbyChat") << "Deactivating toast" << llendl; + m_active_toasts.erase(pos); +} + +void LLFloaterIMNearbyChatScreenChannel::createOverflowToast(S32 bottom, F32 timer) +{ + //we don't need overflow toast in nearby chat +} + +void LLFloaterIMNearbyChatScreenChannel::onToastDestroyed(LLToast* toast, bool app_quitting) +{ + LL_DEBUGS("NearbyChat") << "Toast destroyed (app_quitting=" << app_quitting << ")" << llendl; + + if (app_quitting) + { + // Viewer is quitting. + // Immediately stop processing chat messages (EXT-1419). + mStopProcessing = true; +} + else + { + // The toast is being closed by user (STORM-192). + // Remove it from the list of active toasts to prevent + // further references to the invalid pointer. + deactivateToast(toast); + } +} + +void LLFloaterIMNearbyChatScreenChannel::onToastFade(LLToast* toast) +{ + LL_DEBUGS("NearbyChat") << "Toast fading" << llendl; + + //fade mean we put toast to toast pool + if(!toast) + return; + + deactivateToast(toast); + + addToToastPool(toast); + + arrangeToasts(); +} + +void LLFloaterIMNearbyChatScreenChannel::updateToastsLifetime() +{ + S32 seconds = gSavedSettings.getS32("NearbyToastLifeTime"); + toast_list_t::iterator it; + + for(it = m_toast_pool.begin(); it != m_toast_pool.end(); ++it) + { + (*it).get()->setLifetime(seconds); + } +} + +void LLFloaterIMNearbyChatScreenChannel::updateToastFadingTime() +{ + S32 seconds = gSavedSettings.getS32("NearbyToastFadingTime"); + toast_list_t::iterator it; + + for(it = m_toast_pool.begin(); it != m_toast_pool.end(); ++it) + { + (*it).get()->setFadingTime(seconds); + } +} + +bool LLFloaterIMNearbyChatScreenChannel::createPoolToast() +{ + LLFloaterIMNearbyChatToastPanel* panel= m_create_toast_panel_callback_t(); + if(!panel) + return false; + + LLToast::Params p; + p.panel = panel; + p.lifetime_secs = gSavedSettings.getS32("NearbyToastLifeTime"); + p.fading_time_secs = gSavedSettings.getS32("NearbyToastFadingTime"); + + LLToast* toast = new LLFloaterIMNearbyChatToast(p, this); + + + toast->setOnFadeCallback(boost::bind(&LLFloaterIMNearbyChatScreenChannel::onToastFade, this, _1)); + + // If the toast gets somehow prematurely destroyed, deactivate it to prevent crash (STORM-1352). + toast->setOnToastDestroyedCallback(boost::bind(&LLFloaterIMNearbyChatScreenChannel::onToastDestroyed, this, _1, false)); + + LL_DEBUGS("NearbyChat") << "Creating and pooling toast" << llendl; + m_toast_pool.push_back(toast->getHandle()); + return true; +} + +void LLFloaterIMNearbyChatScreenChannel::addChat(LLSD& chat) +{ + //look in pool. if there is any message + if(mStopProcessing) + return; + + /* + find last toast and check ID + */ + + if(m_active_toasts.size()) + { + LLUUID fromID = chat["from_id"].asUUID(); // agent id or object id + std::string from = chat["from"].asString(); + LLToast* toast = m_active_toasts[0].get(); + if (toast) + { + LLFloaterIMNearbyChatToastPanel* panel = dynamic_cast<LLFloaterIMNearbyChatToastPanel*>(toast->getPanel()); + + if(panel && panel->messageID() == fromID && panel->getFromName() == from && panel->canAddText()) + { + panel->addMessage(chat); + toast->reshapeToPanel(); + toast->startTimer(); + + arrangeToasts(); + return; + } + } + } + + + + if(m_toast_pool.empty()) + { + //"pool" is empty - create one more panel + LL_DEBUGS("NearbyChat") << "Empty pool" << llendl; + if(!createPoolToast())//created toast will go to pool. so next call will find it + return; + addChat(chat); + return; + } + + int chat_type = chat["chat_type"].asInteger(); + + if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG)) + { + if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) + return; + if(gSavedSettings.getS32("ShowScriptErrorsLocation")== 1) + return; + } + + + //take 1st element from pool, (re)initialize it, put it in active toasts + + LL_DEBUGS("NearbyChat") << "Getting toast from pool" << llendl; + LLToast* toast = m_toast_pool.back().get(); + + m_toast_pool.pop_back(); + + + LLFloaterIMNearbyChatToastPanel* panel = dynamic_cast<LLFloaterIMNearbyChatToastPanel*>(toast->getPanel()); + if(!panel) + return; + panel->init(chat); + + toast->reshapeToPanel(); + toast->startTimer(); + + m_active_toasts.push_back(toast->getHandle()); + + arrangeToasts(); +} + +static bool sort_toasts_predicate(LLHandle<LLToast> first, LLHandle<LLToast> second) +{ + if (!first.get() || !second.get()) return false; // STORM-1352 + + F32 v1 = first.get()->getTimeLeftToLive(); + F32 v2 = second.get()->getTimeLeftToLive(); + return v1 > v2; +} + +void LLFloaterIMNearbyChatScreenChannel::arrangeToasts() +{ + if(mStopProcessing || isHovering()) + return; + + if (mFloaterSnapRegion == NULL) + { + mFloaterSnapRegion = gViewerWindow->getRootView()->getChildView("floater_snap_region"); + } + + if (!getParent()) + { + // connect to floater snap region just to get resize events, we don't care about being a proper widget + mFloaterSnapRegion->addChild(this); + setFollows(FOLLOWS_ALL); + } + + LLRect toast_rect; + updateRect(); + + LLRect channel_rect; + mFloaterSnapRegion->localRectToOtherView(mFloaterSnapRegion->getLocalRect(), &channel_rect, gFloaterView); + channel_rect.mLeft += 10; + channel_rect.mRight = channel_rect.mLeft + 300; + + S32 channel_bottom = channel_rect.mBottom; + + S32 bottom = channel_bottom + 80; + S32 margin = gSavedSettings.getS32("ToastGap"); + + //sort active toasts + std::sort(m_active_toasts.begin(),m_active_toasts.end(),sort_toasts_predicate); + + //calc max visible item and hide other toasts. + + for(toast_vec_t::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it) + { + LLToast* toast = it->get(); + if (!toast) + { + llwarns << "NULL found in the active chat toasts list!" << llendl; + continue; + } + + S32 toast_top = bottom + toast->getRect().getHeight() + margin; + + if(toast_top > channel_rect.getHeight()) + { + while(it!=m_active_toasts.end()) + { + addToToastPool(it->get()); + it=m_active_toasts.erase(it); + } + break; + } + + toast_rect = toast->getRect(); + toast_rect.setLeftTopAndSize(channel_rect.mLeft , bottom + toast_rect.getHeight(), toast_rect.getWidth() ,toast_rect.getHeight()); + + toast->setRect(toast_rect); + bottom += toast_rect.getHeight() - toast->getTopPad() + margin; + } + + // use reverse order to provide correct z-order and avoid toast blinking + + for(toast_vec_t::reverse_iterator it = m_active_toasts.rbegin(); it != m_active_toasts.rend(); ++it) + { + LLToast* toast = it->get(); + if (toast) + { + toast->setIsHidden(false); + toast->setVisible(TRUE); + } + } + +} + + + +//----------------------------------------------------------------------------------------------- +//LLFloaterIMNearbyChatHandler +//----------------------------------------------------------------------------------------------- +boost::scoped_ptr<LLEventPump> LLFloaterIMNearbyChatHandler::sChatWatcher(new LLEventStream("LLChat")); + +LLFloaterIMNearbyChatHandler::LLFloaterIMNearbyChatHandler() +{ + // Getting a Channel for our notifications + LLFloaterIMNearbyChatScreenChannel::Params p; + p.id = LLUUID(gSavedSettings.getString("NearByChatChannelUUID")); + LLFloaterIMNearbyChatScreenChannel* channel = new LLFloaterIMNearbyChatScreenChannel(p); + + LLFloaterIMNearbyChatScreenChannel::create_toast_panel_callback_t callback = createToastPanel; + + channel->setCreatePanelCallback(callback); + + LLChannelManager::getInstance()->addChannel(channel); + + mChannel = channel->getHandle(); +} + +LLFloaterIMNearbyChatHandler::~LLFloaterIMNearbyChatHandler() +{ +} + + +void LLFloaterIMNearbyChatHandler::initChannel() +{ + //LLRect snap_rect = gFloaterView->getSnapRect(); + //mChannel->init(snap_rect.mLeft, snap_rect.mLeft + 200); +} + + + +void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, + const LLSD &args) +{ + if(chat_msg.mMuted == TRUE) + return; + + if(chat_msg.mText.empty()) + return;//don't process empty messages + + LLFloaterReg::getInstance("im_container"); + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); + + // Build notification data + LLSD chat; + chat["message"] = chat_msg.mText; + chat["from"] = chat_msg.mFromName; + chat["from_id"] = chat_msg.mFromID; + chat["time"] = chat_msg.mTime; + chat["source"] = (S32)chat_msg.mSourceType; + chat["chat_type"] = (S32)chat_msg.mChatType; + chat["chat_style"] = (S32)chat_msg.mChatStyle; + // Pass sender info so that it can be rendered properly (STORM-1021). + chat["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args); + + if (chat_msg.mChatType == CHAT_TYPE_DIRECT && + chat_msg.mText.length() > 0 && + chat_msg.mText[0] == '@') + { + // Send event on to LLEventStream and exit + sChatWatcher->post(chat); + return; + } + + // don't show toast and add message to chat history on receive debug message + // with disabled setting showing script errors or enabled setting to show script + // errors in separate window. + if (chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG) + { + if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) + return; + + // don't process debug messages from not owned objects, see EXT-7762 + if (gAgentID != chat_msg.mOwnerID) + { + return; + } + + if (gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)// show error in window //("ScriptErrorsAsChat")) + { + + LLColor4 txt_color; + + LLViewerChat::getChatColor(chat_msg,txt_color); + + LLFloaterScriptDebug::addScriptLine(chat_msg.mText, + chat_msg.mFromName, + txt_color, + chat_msg.mFromID); + return; + } + } + + nearby_chat->addMessage(chat_msg, true, args); + + if(chat_msg.mSourceType == CHAT_SOURCE_AGENT + && chat_msg.mFromID.notNull() + && chat_msg.mFromID != gAgentID) + { + LLFirstUse::otherAvatarChatFirst(); + + // Add sender to the recent people list. + LLRecentPeople::instance().add(chat_msg.mFromID); + + } + + // Send event on to LLEventStream + sChatWatcher->post(chat); + + if( nearby_chat->isInVisibleChain() + || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT + && gSavedSettings.getBOOL("UseChatBubbles") ) + || mChannel.isDead() + || !mChannel.get()->getShowToasts() ) // to prevent toasts in Do Not Disturb mode + return;//no need in toast if chat is visible or if bubble chat is enabled + + // arrange a channel on a screen + if(!mChannel.get()->getVisible()) + { + initChannel(); + } + + /* + //comment all this due to EXT-4432 + ..may clean up after some time... + + //only messages from AGENTS + if(CHAT_SOURCE_OBJECT == chat_msg.mSourceType) + { + if(chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG) + return;//ok for now we don't skip messeges from object, so skip only debug messages + } + */ + + LLFloaterIMNearbyChatScreenChannel* channel = dynamic_cast<LLFloaterIMNearbyChatScreenChannel*>(mChannel.get()); + + if(channel) + { + // Handle IRC styled messages. + std::string toast_msg; + if (chat_msg.mChatStyle == CHAT_STYLE_IRC) + { + if (!chat_msg.mFromName.empty()) + { + toast_msg += chat_msg.mFromName; + } + toast_msg += chat_msg.mText.substr(3); + } + else + { + toast_msg = chat_msg.mText; + } + + // Add a nearby chat toast. + LLUUID id; + id.generate(); + chat["id"] = id; + std::string r_color_name = "White"; + F32 r_color_alpha = 1.0f; + LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha); + + chat["text_color"] = r_color_name; + chat["color_alpha"] = r_color_alpha; + chat["font_size"] = (S32)LLViewerChat::getChatFontSize() ; + chat["message"] = toast_msg; + channel->addChat(chat); + } +} + + +//----------------------------------------------------------------------------------------------- +// LLFloaterIMNearbyChatToast +//----------------------------------------------------------------------------------------------- + +// virtual +void LLFloaterIMNearbyChatToast::onClose(bool app_quitting) +{ + mNearbyChatScreenChannelp->onToastDestroyed(this, app_quitting); +} + +// EOF diff --git a/indra/newview/llfloaterimnearbychathandler.h b/indra/newview/llfloaterimnearbychathandler.h new file mode 100644 index 0000000000..5e6f8cde30 --- /dev/null +++ b/indra/newview/llfloaterimnearbychathandler.h @@ -0,0 +1,54 @@ +/** + * @file llfloaterimnearbychathandler.h + * @brief nearby chat notify + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERIMNEARBYCHATHANDLER_H +#define LL_LLFLOATERIMNEARBYCHATHANDLER_H + +#include "llnotificationhandler.h" + +class LLEventPump; + +//add LLFloaterIMNearbyChatHandler to LLNotificationsUI namespace +namespace LLNotificationsUI{ + +class LLFloaterIMNearbyChatHandler : public LLChatHandler +{ +public: + LLFloaterIMNearbyChatHandler(); + virtual ~LLFloaterIMNearbyChatHandler(); + + + virtual void processChat(const LLChat& chat_msg, const LLSD &args); + +protected: + virtual void initChannel(); + + static boost::scoped_ptr<LLEventPump> sChatWatcher; +}; + +} + +#endif /* LL_LLFLOATERIMNEARBYCHATHANDLER_H */ diff --git a/indra/newview/llfloaterimnearbychatlistener.cpp b/indra/newview/llfloaterimnearbychatlistener.cpp new file mode 100644 index 0000000000..14a22bcd84 --- /dev/null +++ b/indra/newview/llfloaterimnearbychatlistener.cpp @@ -0,0 +1,100 @@ +/** + * @file llfloaterimnearbychatlistener.cpp + * @author Dave Simmons + * @date 2011-03-15 + * @brief Implementation for LLFloaterIMNearbyChatListener. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterimnearbychatlistener.h" +#include "llfloaterimnearbychat.h" + +#include "llagent.h" +#include "llchat.h" + + + +LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener(LLFloaterIMNearbyChat & chatbar) + : LLEventAPI("LLChatBar", + "LLChatBar listener to (e.g.) sendChat, etc."), + mChatbar(chatbar) +{ + add("sendChat", + "Send chat to the simulator:\n" + "[\"message\"] chat message text [required]\n" + "[\"channel\"] chat channel number [default = 0]\n" + "[\"type\"] chat type \"whisper\", \"normal\", \"shout\" [default = \"normal\"]", + &LLFloaterIMNearbyChatListener::sendChat); +} + + +// "sendChat" command +void LLFloaterIMNearbyChatListener::sendChat(LLSD const & chat_data) const +{ + // Extract the data + std::string chat_text = chat_data["message"].asString(); + + S32 channel = 0; + if (chat_data.has("channel")) + { + channel = chat_data["channel"].asInteger(); + if (channel < 0 || channel >= CHAT_CHANNEL_DEBUG) + { // Use 0 up to (but not including) CHAT_CHANNEL_DEBUG + channel = 0; + } + } + + EChatType type_o_chat = CHAT_TYPE_NORMAL; + if (chat_data.has("type")) + { + std::string type_string = chat_data["type"].asString(); + if (type_string == "whisper") + { + type_o_chat = CHAT_TYPE_WHISPER; + } + else if (type_string == "shout") + { + type_o_chat = CHAT_TYPE_SHOUT; + } + } + + // Have to prepend /42 style channel numbers + std::string chat_to_send; + if (channel == 0) + { + chat_to_send = chat_text; + } + else + { + chat_to_send += "/"; + chat_to_send += chat_data["channel"].asString(); + chat_to_send += " "; + chat_to_send += chat_text; + } + + // Send it as if it was typed in + mChatbar.sendChatFromViewer(chat_to_send, type_o_chat, (BOOL)(channel == 0)); +} + diff --git a/indra/newview/llfloaterimnearbychatlistener.h b/indra/newview/llfloaterimnearbychatlistener.h new file mode 100644 index 0000000000..1470a6dc1e --- /dev/null +++ b/indra/newview/llfloaterimnearbychatlistener.h @@ -0,0 +1,50 @@ +/** + * @file llfloaterimnearbychatlistener.h + * @author Dave Simmons + * @date 2011-03-15 + * @brief Class definition for LLFloaterIMNearbyChatListener. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +#ifndef LL_LLFLOATERIMNEARBYCHATLISTENER_H +#define LL_LLFLOATERIMNEARBYCHATLISTENER_H + +#include "lleventapi.h" + +class LLSD; +class LLFloaterIMNearbyChat; + +class LLFloaterIMNearbyChatListener : public LLEventAPI +{ +public: + LLFloaterIMNearbyChatListener(LLFloaterIMNearbyChat & chatbar); + +private: + void sendChat(LLSD const & chat_data) const; + + LLFloaterIMNearbyChat & mChatbar; +}; + +#endif // LL_LLFLOATERIMNEARBYCHATLISTENER_H + diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp new file mode 100644 index 0000000000..0c622e07c4 --- /dev/null +++ b/indra/newview/llfloaterimsession.cpp @@ -0,0 +1,1202 @@ +/** + * @file llfloaterimsession.cpp + * @brief LLFloaterIMSession class definition + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterimsession.h" + +#include "lldraghandle.h" +#include "llnotificationsutil.h" + +#include "llagent.h" +#include "llappviewer.h" +#include "llavataractions.h" +#include "llavatarnamecache.h" +#include "llbutton.h" +#include "llchannelmanager.h" +#include "llchiclet.h" +#include "llchicletbar.h" +#include "llfloaterreg.h" +#include "llfloateravatarpicker.h" +#include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container +#include "llinventoryfunctions.h" +//#include "lllayoutstack.h" +#include "llchatentry.h" +#include "lllogchat.h" +#include "llscreenchannel.h" +#include "llsyswellwindow.h" +#include "lltrans.h" +#include "llchathistory.h" +#include "llnotifications.h" +#include "llviewerwindow.h" +#include "lltransientfloatermgr.h" +#include "llinventorymodel.h" +#include "llrootview.h" +#include "llspeakers.h" +#include "llviewerchat.h" +#include "llnotificationmanager.h" +#include "llautoreplace.h" + +floater_showed_signal_t LLFloaterIMSession::sIMFloaterShowedSignal; + +LLFloaterIMSession::LLFloaterIMSession(const LLUUID& session_id) + : LLFloaterIMSessionTab(session_id), + mLastMessageIndex(-1), + mDialog(IM_NOTHING_SPECIAL), + mSavedTitle(), + mTypingStart(), + mShouldSendTypingState(false), + mMeTyping(false), + mOtherTyping(false), + mTypingTimer(), + mTypingTimeoutTimer(), + mPositioned(false), + mSessionInitialized(false), + mStartConferenceInSameFloater(false) +{ + mIsNearbyChat = false; + + initIMSession(session_id); + + setOverlapsScreenChannel(true); + + LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); + + setDocked(true); +} + + +// virtual +void LLFloaterIMSession::refresh() +{ + if (mMeTyping) +{ + // Time out if user hasn't typed for a while. + if (mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS) + { + setTyping(false); + } + } +} + +// virtual +void LLFloaterIMSession::onClickCloseBtn() +{ + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); + + if (session != NULL) + { + bool is_call_with_chat = session->isGroupSessionType() + || session->isAdHocSessionType() || session->isP2PSessionType(); + + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + + if (is_call_with_chat && voice_channel != NULL + && voice_channel->isActive()) + { + LLSD payload; + payload["session_id"] = mSessionID; + LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); + return; + } + } + else + { + llwarns << "Empty session with id: " << (mSessionID.asString()) << llendl; + return; + } + + LLFloaterIMSessionTab::onClickCloseBtn(); +} + +/* static */ +void LLFloaterIMSession::newIMCallback(const LLSD& data) +{ + if (data["num_unread"].asInteger() > 0 || data["from_id"].asUUID().isNull()) + { + LLUUID session_id = data["session_id"].asUUID(); + + LLFloaterIMSession* floater = LLFloaterReg::findTypedInstance<LLFloaterIMSession>("impanel", session_id); + + // update if visible, otherwise will be updated when opened + if (floater && floater->getVisible()) + { + floater->updateMessages(); + } + } +} + +void LLFloaterIMSession::onVisibilityChange(const LLSD& new_visibility) +{ + bool visible = new_visibility.asBoolean(); + + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + + if (visible && voice_channel && + voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED) + { + LLFloaterReg::showInstance("voice_call", mSessionID); + } + else + { + LLFloaterReg::hideInstance("voice_call", mSessionID); + } +} + +void LLFloaterIMSession::onSendMsg( LLUICtrl* ctrl, void* userdata ) +{ + LLFloaterIMSession* self = (LLFloaterIMSession*) userdata; + self->sendMsgFromInputEditor(); + self->setTyping(false); +} + +void LLFloaterIMSession::sendMsgFromInputEditor() +{ + if (gAgent.isGodlike() + || (mDialog != IM_NOTHING_SPECIAL) + || !mOtherParticipantUUID.isNull()) + { + if (mInputEditor) + { + LLWString text = mInputEditor->getWText(); + LLWStringUtil::trim(text); + LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. + if(!text.empty()) + { + // Truncate and convert to UTF8 for transport + std::string utf8_text = wstring_to_utf8str(text); + + sendMsg(utf8_text); + + mInputEditor->setText(LLStringUtil::null); + } + } + } + else + { + llinfos << "Cannot send IM to everyone unless you're a god." << llendl; + } +} + +void LLFloaterIMSession::sendMsg(const std::string& msg) +{ + const std::string utf8_text = utf8str_truncate(msg, MAX_MSG_BUF_SIZE - 1); + + if (mSessionInitialized) + { + LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog); + } + else + { + //queue up the message to send once the session is initialized + mQueuedMsgsForInit.append(utf8_text); + } + + updateMessages(); +} + +LLFloaterIMSession::~LLFloaterIMSession() +{ + mVoiceChannelStateChangeConnection.disconnect(); + if(LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->removeObserver(this); + } + + LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); +} + + +void LLFloaterIMSession::initIMSession(const LLUUID& session_id) +{ + // Change the floater key to bind it to a new session. + setKey(session_id); + + mSessionID = session_id; + mSession = LLIMModel::getInstance()->findIMSession(mSessionID); + + if (mSession) + { + mIsP2PChat = mSession->isP2PSessionType(); + mSessionInitialized = mSession->mSessionInitialized; + mDialog = mSession->mType; + } +} + +void LLFloaterIMSession::initIMFloater() +{ + const LLUUID& other_party_id = + LLIMModel::getInstance()->getOtherParticipantID(mSessionID); + if (other_party_id.notNull()) + { + mOtherParticipantUUID = other_party_id; + } + + boundVoiceChannel(); + + mTypingStart = LLTrans::getString("IM_typing_start_string"); + + // Show control panel in torn off floaters only. + mParticipantListPanel->setVisible(!getHost() && gSavedSettings.getBOOL("IMShowControlPanel")); + + // Disable input editor if session cannot accept text + if ( mSession && !mSession->mTextIMPossible ) + { + mInputEditor->setEnabled(FALSE); + mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label")); + } + + if (!mIsP2PChat) + { + std::string session_name(LLIMModel::instance().getName(mSessionID)); + updateSessionName(session_name); + } +} + +//virtual +BOOL LLFloaterIMSession::postBuild() +{ + BOOL result = LLFloaterIMSessionTab::postBuild(); + + mInputEditor->setMaxTextLength(1023); + // enable line history support for instant message bar + // XXX stinson TODO : resolve merge by adding autoreplace to text editors +#if 0 + // *TODO Establish LineEditor with autoreplace callback + mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); +#endif + + mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) ); + mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) ); + mInputEditor->setKeystrokeCallback( boost::bind(onInputEditorKeystroke, _1, this) ); + mInputEditor->setCommitCallback(boost::bind(onSendMsg, _1, this)); + + setDocked(true); + + LLButton* add_btn = getChild<LLButton>("add_btn"); + + // Allow to add chat participants depending on the session type + add_btn->setEnabled(isInviteAllowed()); + add_btn->setClickedCallback(boost::bind(&LLFloaterIMSession::onAddButtonClicked, this)); + + childSetAction("voice_call_btn", boost::bind(&LLFloaterIMSession::onCallButtonClicked, this)); + + LLVoiceClient::getInstance()->addObserver(this); + + //*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla" + //see LLFloaterIMPanel for how it is done (IB) + + initIMFloater(); + + return result; +} + +void LLFloaterIMSession::onAddButtonClicked() +{ + LLView * button = findChild<LLView>("toolbar_panel")->findChild<LLButton>("add_btn"); + LLFloater* root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterIMSession::addSessionParticipants, this, _1), TRUE, TRUE, FALSE, root_floater->getName(), button); + if (!picker) + { + return; + } + + // Need to disable 'ok' button when selected users are already in conversation. + picker->setOkBtnEnableCb(boost::bind(&LLFloaterIMSession::canAddSelectedToChat, this, _1)); + + if (root_floater) + { + root_floater->addDependentFloater(picker); + } +} + +bool LLFloaterIMSession::canAddSelectedToChat(const uuid_vec_t& uuids) +{ + if (!mSession + || mDialog == IM_SESSION_GROUP_START + || mDialog == IM_SESSION_INVITE && gAgent.isInGroup(mSessionID)) + { + return false; + } + + if (mIsP2PChat) + { + // For a P2P session just check if we are not adding the other participant. + + for (uuid_vec_t::const_iterator id = uuids.begin(); + id != uuids.end(); ++id) + { + if (*id == mOtherParticipantUUID) + { + return false; + } + } + } + else + { + // For a conference session we need to check against the list from LLSpeakerMgr, + // because this list may change when participants join or leave the session. + + LLSpeakerMgr::speaker_list_t speaker_list; + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + speaker_mgr->getSpeakerList(&speaker_list, true); + } + + for (uuid_vec_t::const_iterator id = uuids.begin(); + id != uuids.end(); ++id) + { + for (LLSpeakerMgr::speaker_list_t::const_iterator it = speaker_list.begin(); + it != speaker_list.end(); ++it) + { + const LLPointer<LLSpeaker>& speaker = *it; + if (*id == speaker->mID) + { + return false; + } + } + } + } + + return true; +} + +void LLFloaterIMSession::addSessionParticipants(const uuid_vec_t& uuids) +{ + if (mIsP2PChat) + { + LLSD payload; + LLSD args; + + LLNotificationsUtil::add("ConfirmAddingChatParticipants", args, payload, + boost::bind(&LLFloaterIMSession::addP2PSessionParticipants, this, _1, _2, uuids)); + } + else + { + // remember whom we have invited, to notify others later, when the invited ones actually join + mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); + + inviteToSession(uuids); + } +} + +void LLFloaterIMSession::addP2PSessionParticipants(const LLSD& notification, const LLSD& response, const uuid_vec_t& uuids) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) + { + return; + } + + mStartConferenceInSameFloater = true; + + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + + // first check whether this is a voice session + bool is_voice_call = voice_channel != NULL && voice_channel->isActive(); + + uuid_vec_t temp_ids; + + // Add the initial participant of a P2P session + temp_ids.push_back(mOtherParticipantUUID); + temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end()); + + // then we can close the current session + onClose(false); + + // we start a new session so reset the initialization flag + mSessionInitialized = false; + + // remember whom we have invited, to notify others later, when the invited ones actually join + mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); + + // Start a new ad hoc voice call if we invite new participants to a P2P call, + // or start a text chat otherwise. + if (is_voice_call) + { + LLAvatarActions::startAdhocCall(temp_ids, mSessionID); + } + else + { + LLAvatarActions::startConference(temp_ids, mSessionID); + } +} + +void LLFloaterIMSession::sendParticipantsAddedNotification(const uuid_vec_t& uuids) +{ + std::string names_string; + LLAvatarActions::buildResidentsString(uuids, names_string); + LLStringUtil::format_map_t args; + args["[NAME]"] = names_string; + + sendMsg(getString(uuids.size() > 1 ? "multiple_participants_added" : "participant_added", args)); +} + +void LLFloaterIMSession::boundVoiceChannel() +{ + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + if(voice_channel) + { + mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback( + boost::bind(&LLFloaterIMSession::onVoiceChannelStateChanged, this, _1, _2)); + + //call (either p2p, group or ad-hoc) can be already in started state + bool callIsActive = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED; + updateCallBtnState(callIsActive); + } +} + +void LLFloaterIMSession::onCallButtonClicked() +{ + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + if (voice_channel) + { + bool is_call_active = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED; + if (is_call_active) + { + gIMMgr->endCall(mSessionID); + } + else + { + gIMMgr->startCall(mSessionID); + } + } +} + +void LLFloaterIMSession::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + if(status != STATUS_JOINING && status != STATUS_LEFT_CHANNEL) + { + enableDisableCallBtn(); + } +} + +void LLFloaterIMSession::onVoiceChannelStateChanged( + const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) +{ + bool callIsActive = new_state >= LLVoiceChannel::STATE_CALL_STARTED; + updateCallBtnState(callIsActive); +} + +void LLFloaterIMSession::updateSessionName(const std::string& name) +{ + LLFloaterIMSessionTab::updateSessionName(name); + setTitle(name); + mTypingStart.setArg("[NAME]", name); +} + +//static +LLFloaterIMSession* LLFloaterIMSession::show(const LLUUID& session_id) +{ + closeHiddenIMToasts(); + + if (!gIMMgr->hasSession(session_id)) + return NULL; + + // Test the existence of the floater before we try to create it + bool exist = findInstance(session_id); + + // Get the floater: this will create the instance if it didn't exist + LLFloaterIMSession* floater = getInstance(session_id); + if (!floater) + return NULL; + + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + + // Do not add again existing floaters + if (!exist) + { + // LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; + // TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists + LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END; + if (floater_container) + { + floater_container->addFloater(floater, TRUE, i_pt); + } + } + + floater->openFloater(floater->getKey()); + + floater->setVisible(TRUE); + + return floater; +} +//static +LLFloaterIMSession* LLFloaterIMSession::findInstance(const LLUUID& session_id) +{ + LLFloaterIMSession* conversation = + LLFloaterReg::findTypedInstance<LLFloaterIMSession>("impanel", session_id); + + return conversation; +} + +LLFloaterIMSession* LLFloaterIMSession::getInstance(const LLUUID& session_id) +{ + LLFloaterIMSession* conversation = + LLFloaterReg::getTypedInstance<LLFloaterIMSession>("impanel", session_id); + + return conversation; +} + +void LLFloaterIMSession::onClose(bool app_quitting) +{ + setTyping(false); + + // The source of much argument and design thrashing + // Should the window hide or the session close when the X is clicked? + // + // Last change: + // EXT-3516 X Button should end IM session, _ button should hide + gIMMgr->leaveSession(mSessionID); + + // Clean up the conversation *after* the session has been ended + LLFloaterIMSessionTab::onClose(app_quitting); +} + +void LLFloaterIMSession::setDocked(bool docked, bool pop_on_undock) +{ + // update notification channel state + LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> + (LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + + if(!isChatMultiTab()) + { + LLTransientDockableFloater::setDocked(docked, pop_on_undock); + } + + // update notification channel state + if(channel) + { + channel->updateShowToastsState(); + channel->redrawToasts(); + } +} + +void LLFloaterIMSession::setVisible(BOOL visible) +{ + LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> + (LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + + LLFloaterIMSessionTab::setVisible(visible); + + // update notification channel state + if(channel) + { + channel->updateShowToastsState(); + channel->redrawToasts(); + } + + if(!visible) + { + LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(mSessionID); + if(chiclet) + { + chiclet->setToggleState(false); + } + } + + if (visible && isInVisibleChain()) + { + sIMFloaterShowedSignal(mSessionID); + + } + + setFocus(visible); +} + +BOOL LLFloaterIMSession::getVisible() +{ + bool visible; + + if(isChatMultiTab()) + { + LLFloaterIMContainer* im_container = + LLFloaterIMContainer::getInstance(); + + // Treat inactive floater as invisible. + bool is_active = im_container->getActiveFloater() == this; + + //torn off floater is always inactive + if (!is_active && getHost() != im_container) + { + visible = LLTransientDockableFloater::getVisible(); + } + else + { + // getVisible() returns TRUE when Tabbed IM window is minimized. + visible = is_active && !im_container->isMinimized() + && im_container->getVisible(); + } + } + else + { + visible = LLTransientDockableFloater::getVisible(); + } + + return visible; +} + +//static +bool LLFloaterIMSession::toggle(const LLUUID& session_id) +{ + if(!isChatMultiTab()) + { + LLFloaterIMSession* floater = LLFloaterReg::findTypedInstance<LLFloaterIMSession>( + "impanel", session_id); + if (floater && floater->getVisible() && floater->hasFocus()) + { + // clicking on chiclet to close floater just hides it to maintain existing + // scroll/text entry state + floater->setVisible(false); + return false; + } + else if(floater && (!floater->isDocked() || floater->getVisible() && !floater->hasFocus())) + { + floater->setVisible(TRUE); + floater->setFocus(TRUE); + return true; + } + } + + // ensure the list of messages is updated when floater is made visible + show(session_id); + return true; +} + +void LLFloaterIMSession::sessionInitReplyReceived(const LLUUID& im_session_id) +{ + mSessionInitialized = true; + + //will be different only for an ad-hoc im session + if (mSessionID != im_session_id) + { + initIMSession(im_session_id); + buildConversationViewParticipant(); + } + + initIMFloater(); + + //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) + + //need to send delayed messages collected while waiting for session initialization + if (mQueuedMsgsForInit.size()) + { + LLSD::array_iterator iter; + for ( iter = mQueuedMsgsForInit.beginArray(); + iter != mQueuedMsgsForInit.endArray(); ++iter) + { + LLIMModel::sendMessage(iter->asString(), mSessionID, + mOtherParticipantUUID, mDialog); + } + + mQueuedMsgsForInit.clear(); + } +} + +void LLFloaterIMSession::updateMessages() +{ + std::list<LLSD> messages; + + // we shouldn't reset unread message counters if IM floater doesn't have focus + LLIMModel::instance().getMessages( + mSessionID, messages, mLastMessageIndex + 1, hasFocus()); + + if (messages.size()) + { + std::ostringstream message; + std::list<LLSD>::const_reverse_iterator iter = messages.rbegin(); + std::list<LLSD>::const_reverse_iterator iter_end = messages.rend(); + for (; iter != iter_end; ++iter) + { + LLSD msg = *iter; + + std::string time = msg["time"].asString(); + LLUUID from_id = msg["from_id"].asUUID(); + std::string from = msg["from"].asString(); + std::string message = msg["message"].asString(); + bool is_history = msg["is_history"].asBoolean(); + + LLChat chat; + chat.mFromID = from_id; + chat.mSessionID = mSessionID; + chat.mFromName = from; + chat.mTimeStr = time; + chat.mChatStyle = is_history ? CHAT_STYLE_HISTORY : chat.mChatStyle; + + // process offer notification + if (msg.has("notification_id")) + { + chat.mNotifId = msg["notification_id"].asUUID(); + // if notification exists - embed it + if (LLNotificationsUtil::find(chat.mNotifId) != NULL) + { + // remove embedded notification from channel + LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> + (LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + if (getVisible()) + { + // toast will be automatically closed since it is not storable toast + channel->hideToast(chat.mNotifId); + } + } + // if notification doesn't exist - try to use next message which should be log entry + else + { + continue; + } + } + //process text message + else + { + chat.mText = message; + } + + // Add the message to the chat log + appendMessage(chat); + mLastMessageIndex = msg["index"].asInteger(); + + // if it is a notification - next message is a notification history log, so skip it + if (chat.mNotifId.notNull() && LLNotificationsUtil::find(chat.mNotifId) != NULL) + { + if (++iter == iter_end) + { + break; + } + else + { + mLastMessageIndex++; + } + } + } + } +} + +void LLFloaterIMSession::reloadMessages() +{ + mChatHistory->clear(); + mLastMessageIndex = -1; + updateMessages(); + mInputEditor->setFont(LLViewerChat::getChatFont()); +} + +// static +void LLFloaterIMSession::onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ) +{ + LLFloaterIMSession* self= (LLFloaterIMSession*) userdata; + + // Allow enabling the LLFloaterIMSession input editor only if session can accept text + LLIMModel::LLIMSession* im_session = + LLIMModel::instance().findIMSession(self->mSessionID); + //TODO: While disabled lllineeditor can receive focus we need to check if it is enabled (EK) + if( im_session && im_session->mTextIMPossible && self->mInputEditor->getEnabled()) + { + //in disconnected state IM input editor should be disabled + self->mInputEditor->setEnabled(!gDisconnected); + } +} + +// static +void LLFloaterIMSession::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata) +{ + LLFloaterIMSession* self = (LLFloaterIMSession*) userdata; + self->setTyping(false); +} + +// static +void LLFloaterIMSession::onInputEditorKeystroke(LLTextEditor* caller, void* userdata) +{ + LLFloaterIMSession* self = (LLFloaterIMSession*)userdata; + std::string text = self->mInputEditor->getText(); + + // Deleting all text counts as stopping typing. + self->setTyping(!text.empty()); +} + +void LLFloaterIMSession::setTyping(bool typing) +{ + if ( typing ) + { + // Started or proceeded typing, reset the typing timeout timer + mTypingTimeoutTimer.reset(); + } + + if ( mMeTyping != typing ) + { + // Typing state is changed + mMeTyping = typing; + // So, should send current state + mShouldSendTypingState = true; + // In case typing is started, send state after some delay + mTypingTimer.reset(); + } + + // Don't want to send typing indicators to multiple people, potentially too + // much network traffic. Only send in person-to-person IMs. + if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL ) + { + // Still typing, send 'start typing' notification or + // send 'stop typing' notification immediately + if (!mMeTyping || mTypingTimer.getElapsedTimeF32() > 1.f) + { + LLIMModel::instance().sendTypingState(mSessionID, + mOtherParticipantUUID, mMeTyping); + mShouldSendTypingState = false; + } + } + + if (!mIsNearbyChat) + { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); + } + } +} + +void LLFloaterIMSession::processIMTyping(const LLIMInfo* im_info, BOOL typing) +{ + if ( typing ) + { + // other user started typing + addTypingIndicator(im_info); + } + else + { + // other user stopped typing + removeTypingIndicator(im_info); + } +} + +void LLFloaterIMSession::processAgentListUpdates(const LLSD& body) +{ + uuid_vec_t joined_uuids; + + if (body.isMap() && body.has("agent_updates") && body["agent_updates"].isMap()) + { + LLSD::map_const_iterator update_it; + for(update_it = body["agent_updates"].beginMap(); + update_it != body["agent_updates"].endMap(); + ++update_it) + { + LLUUID agent_id(update_it->first); + LLSD agent_data = update_it->second; + + if (agent_data.isMap()) + { + // store the new participants in joined_uuids + if (agent_data.has("transition") && agent_data["transition"].asString() == "ENTER") + { + joined_uuids.push_back(agent_id); + } + + // process the moderator mutes + if (agent_id == gAgentID && agent_data.has("info") && agent_data["info"].has("mutes")) + { + BOOL moderator_muted_text = agent_data["info"]["mutes"]["text"].asBoolean(); + mInputEditor->setEnabled(!moderator_muted_text); + std::string label; + if (moderator_muted_text) + label = LLTrans::getString("IM_muted_text_label"); + else + label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID); + mInputEditor->setLabel(label); + + if (moderator_muted_text) + LLNotificationsUtil::add("TextChatIsMutedByModerator"); + } + } + } + } + + // the vectors need to be sorted for computing the intersection and difference + std::sort(mInvitedParticipants.begin(), mInvitedParticipants.end()); + std::sort(joined_uuids.begin(), joined_uuids.end()); + + uuid_vec_t intersection; // uuids of invited residents who have joined the conversation + std::set_intersection(mInvitedParticipants.begin(), mInvitedParticipants.end(), + joined_uuids.begin(), joined_uuids.end(), + std::back_inserter(intersection)); + + if (intersection.size() > 0) + { + sendParticipantsAddedNotification(intersection); + } + + // Remove all joined participants from invited array. + // The difference between the two vectors (the elements in mInvitedParticipants which are not in joined_uuids) + // is placed at the beginning of mInvitedParticipants, then all other elements are erased. + mInvitedParticipants.erase(std::set_difference(mInvitedParticipants.begin(), mInvitedParticipants.end(), + joined_uuids.begin(), joined_uuids.end(), + mInvitedParticipants.begin()), + mInvitedParticipants.end()); +} + +void LLFloaterIMSession::processSessionUpdate(const LLSD& session_update) +{ + // *TODO : verify following code when moderated mode will be implemented + if ( false && session_update.has("moderated_mode") && + session_update["moderated_mode"].has("voice") ) + { + BOOL voice_moderated = session_update["moderated_mode"]["voice"]; + const std::string session_label = LLIMModel::instance().getName(mSessionID); + + if (voice_moderated) + { + setTitle(session_label + std::string(" ") + + LLTrans::getString("IM_moderated_chat_label")); + } + else + { + setTitle(session_label); + } + + // *TODO : uncomment this when/if LLPanelActiveSpeakers panel will be added + //update the speakers dropdown too + //mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated); + } +} + +// virtual +BOOL LLFloaterIMSession::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + if (cargo_type == DAD_PERSON) + { + if (dropPerson(static_cast<LLUUID*>(cargo_data), drop)) + { + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + } + else if (mDialog == IM_NOTHING_SPECIAL) + { + LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, + cargo_type, cargo_data, accept); + } + + return TRUE; +} + +bool LLFloaterIMSession::dropPerson(LLUUID* person_id, bool drop) +{ + bool res = person_id && person_id->notNull(); + if(res) + { + uuid_vec_t ids; + ids.push_back(*person_id); + + res = canAddSelectedToChat(ids); + if(res && drop) + { + addSessionParticipants(ids); + } + } + + return res; +} + +BOOL LLFloaterIMSession::isInviteAllowed() const +{ + return ( (IM_SESSION_CONFERENCE_START == mDialog) + || (IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) + || mIsP2PChat); +} + +class LLSessionInviteResponder : public LLHTTPClient::Responder +{ +public: + LLSessionInviteResponder(const LLUUID& session_id) + { + mSessionID = session_id; + } + + void error(U32 statusNum, const std::string& reason) + { + llinfos << "Error inviting all agents to session" << llendl; + //throw something back to the viewer here? + } + +private: + LLUUID mSessionID; +}; + +BOOL LLFloaterIMSession::inviteToSession(const uuid_vec_t& ids) +{ + LLViewerRegion* region = gAgent.getRegion(); + bool is_region_exist = region != NULL; + + if (is_region_exist) + { + S32 count = ids.size(); + + if( isInviteAllowed() && (count > 0) ) + { + llinfos << "LLFloaterIMSession::inviteToSession() - inviting participants" << llendl; + + std::string url = region->getCapability("ChatSessionRequest"); + + LLSD data; + data["params"] = LLSD::emptyArray(); + for (int i = 0; i < count; i++) + { + data["params"].append(ids[i]); + } + data["method"] = "invite"; + data["session-id"] = mSessionID; + LLHTTPClient::post(url, data,new LLSessionInviteResponder(mSessionID)); + } + else + { + llinfos << "LLFloaterIMSession::inviteToSession -" + << " no need to invite agents for " + << mDialog << llendl; + // successful add, because everyone that needed to get added + // was added. + } + } + + return is_region_exist; +} + +void LLFloaterIMSession::addTypingIndicator(const LLIMInfo* im_info) +{ + // We may have lost a "stop-typing" packet, don't add it twice + if ( im_info && !mOtherTyping ) + { + mOtherTyping = true; + + // Save and set new title + mSavedTitle = getTitle(); + setTitle (mTypingStart); + + // Update speaker + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if ( speaker_mgr ) + { + speaker_mgr->setSpeakerTyping(im_info->mFromID, TRUE); + } + } +} + +void LLFloaterIMSession::removeTypingIndicator(const LLIMInfo* im_info) +{ + if ( mOtherTyping ) + { + mOtherTyping = false; + + // Revert the title to saved one + setTitle(mSavedTitle); + + if ( im_info ) + { + // Update speaker + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if ( speaker_mgr ) + { + speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE); + } + } + } +} + +// static +void LLFloaterIMSession::closeHiddenIMToasts() +{ + class IMToastMatcher: public LLNotificationsUI::LLScreenChannel::Matcher + { + public: + bool matches(const LLNotificationPtr notification) const + { + // "notifytoast" type of notifications is reserved for IM notifications + return "notifytoast" == notification->getType(); + } + }; + + LLNotificationsUI::LLScreenChannel* channel = + LLNotificationsUI::LLChannelManager::getNotificationScreenChannel(); + if (channel != NULL) + { + channel->closeHiddenToasts(IMToastMatcher()); + } +} +// static +void LLFloaterIMSession::confirmLeaveCallCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + const LLSD& payload = notification["payload"]; + LLUUID session_id = payload["session_id"]; + + LLFloater* im_floater = findInstance(session_id); + if (option == 0 && im_floater != NULL) + { + im_floater->closeFloater(); + } + + return; +} + +// static +void LLFloaterIMSession::sRemoveTypingIndicator(const LLSD& data) +{ + LLUUID session_id = data["session_id"]; + if (session_id.isNull()) + return; + + LLUUID from_id = data["from_id"]; + if (gAgentID == from_id || LLUUID::null == from_id) + return; + + LLFloaterIMSession* floater = LLFloaterIMSession::findInstance(session_id); + if (!floater) + return; + + if (IM_NOTHING_SPECIAL != floater->mDialog) + return; + + floater->removeTypingIndicator(); +} + +// static +void LLFloaterIMSession::onIMChicletCreated( const LLUUID& session_id ) +{ + LLFloaterIMSession::addToHost(session_id); +} + +boost::signals2::connection LLFloaterIMSession::setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb) +{ + return LLFloaterIMSession::sIMFloaterShowedSignal.connect(cb); +} diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h new file mode 100644 index 0000000000..f4ec2d457d --- /dev/null +++ b/indra/newview/llfloaterimsession.h @@ -0,0 +1,196 @@ +/** + * @file llfloaterimsession.h + * @brief LLFloaterIMSession class definition + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_FLOATERIMSESSION_H +#define LL_FLOATERIMSESSION_H + +#include "llimview.h" +#include "llfloaterimsessiontab.h" +#include "llinstantmessage.h" +#include "lllogchat.h" +#include "lltooldraganddrop.h" +#include "llvoicechannel.h" +#include "llvoiceclient.h" + +class LLAvatarName; +class LLButton; +class LLChatEntry; +class LLTextEditor; +class LLPanelChatControlPanel; +class LLChatHistory; +class LLInventoryItem; +class LLInventoryCategory; + +typedef boost::signals2::signal<void(const LLUUID& session_id)> floater_showed_signal_t; + +/** + * Individual IM window that appears at the bottom of the screen, + * optionally "docked" to the bottom tray. + */ +class LLFloaterIMSession + : public LLVoiceClientStatusObserver + , public LLFloaterIMSessionTab +{ + LOG_CLASS(LLFloaterIMSession); +public: + LLFloaterIMSession(const LLUUID& session_id); + + virtual ~LLFloaterIMSession(); + + void initIMSession(const LLUUID& session_id); + void initIMFloater(); + + // LLView overrides + /*virtual*/ BOOL postBuild(); + /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ BOOL getVisible(); + // Check typing timeout timer. + + static LLFloaterIMSession* findInstance(const LLUUID& session_id); + static LLFloaterIMSession* getInstance(const LLUUID& session_id); + + // LLFloater overrides + /*virtual*/ void onClose(bool app_quitting); + /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); + // Make IM conversion visible and update the message history + static LLFloaterIMSession* show(const LLUUID& session_id); + + // Toggle panel specified by session_id + // Returns true iff panel became visible + static bool toggle(const LLUUID& session_id); + + void sessionInitReplyReceived(const LLUUID& im_session_id); + + // get new messages from LLIMModel + /*virtual*/ void updateMessages(); + void reloadMessages(); + static void onSendMsg(LLUICtrl*, void*); + void sendMsgFromInputEditor(); + void sendMsg(const std::string& msg); + + // callback for LLIMModel on new messages + // route to specific floater if it is visible + static void newIMCallback(const LLSD& data); + + // called when docked floater's position has been set by chiclet + void setPositioned(bool b) { mPositioned = b; }; + + void onVisibilityChange(const LLSD& new_visibility); + + // Implements LLVoiceClientStatusObserver::onChange() to enable the call + // button when voice is available + void onChange(EStatusType status, const std::string &channelURI, + bool proximal); + + virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } + virtual void onVoiceChannelStateChanged( + const LLVoiceChannel::EState& old_state, + const LLVoiceChannel::EState& new_state); + + void processIMTyping(const LLIMInfo* im_info, BOOL typing); + void processAgentListUpdates(const LLSD& body); + void processSessionUpdate(const LLSD& session_update); + + /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + + + //used as a callback on receiving new IM message + static void sRemoveTypingIndicator(const LLSD& data); + static void onIMChicletCreated(const LLUUID& session_id); + + bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; } + const LLUUID& getOtherParticipantUUID() {return mOtherParticipantUUID;} + + static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); + static floater_showed_signal_t sIMFloaterShowedSignal; + +private: + + /*virtual*/ void refresh(); + + /*virtual*/ void onClickCloseBtn(); + + // Update the window title and input field help text + /*virtual*/ void updateSessionName(const std::string& name); + + bool dropPerson(LLUUID* person_id, bool drop); + + BOOL isInviteAllowed() const; + BOOL inviteToSession(const uuid_vec_t& agent_ids); + static void onInputEditorFocusReceived( LLFocusableElement* caller,void* userdata ); + static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); + static void onInputEditorKeystroke(LLTextEditor* caller, void* userdata); + void setTyping(bool typing); + void onAddButtonClicked(); + void addSessionParticipants(const uuid_vec_t& uuids); + void addP2PSessionParticipants(const LLSD& notification, const LLSD& response, const uuid_vec_t& uuids); + void sendParticipantsAddedNotification(const uuid_vec_t& uuids); + bool canAddSelectedToChat(const uuid_vec_t& uuids); + + void onCallButtonClicked(); + + void boundVoiceChannel(); + + // Add the "User is typing..." indicator. + void addTypingIndicator(const LLIMInfo* im_info); + + // Remove the "User is typing..." indicator. + void removeTypingIndicator(const LLIMInfo* im_info = NULL); + + static void closeHiddenIMToasts(); + + static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); + + S32 mLastMessageIndex; + + EInstantMessage mDialog; + LLUUID mOtherParticipantUUID; + bool mPositioned; + + std::string mSavedTitle; + LLUIString mTypingStart; + bool mMeTyping; + bool mOtherTyping; + bool mShouldSendTypingState; + LLFrameTimer mTypingTimer; + LLFrameTimer mTypingTimeoutTimer; + + bool mSessionInitialized; + LLSD mQueuedMsgsForInit; + + bool mStartConferenceInSameFloater; + + uuid_vec_t mInvitedParticipants; + + // connection to voice channel state change signal + boost::signals2::connection mVoiceChannelStateChangeConnection; +}; + +#endif // LL_FLOATERIMSESSION_H diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp new file mode 100644 index 0000000000..a47c9177a1 --- /dev/null +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -0,0 +1,743 @@ +/** + * @file llfloaterimsessiontab.cpp + * @brief LLFloaterIMSessionTab class implements the common behavior of LNearbyChatBar + * @brief and LLFloaterIMSession for hosting both in LLIMContainer + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterimsessiontab.h" + +#include "llagent.h" +#include "llavataractions.h" +#include "llchatentry.h" +#include "llchathistory.h" +#include "llchiclet.h" +#include "llchicletbar.h" +#include "lldraghandle.h" +#include "llfloaterreg.h" +#include "llfloaterimsession.h" +#include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container +#include "lllayoutstack.h" +#include "llfloaterimnearbychat.h" + +const F32 REFRESH_INTERVAL = 0.2f; + +LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) + : LLTransientDockableFloater(NULL, true, session_id) + , mIsP2PChat(false) + , mExpandCollapseBtn(NULL) + , mTearOffBtn(NULL) + , mCloseBtn(NULL) + , mSessionID(session_id.asUUID()) + , mConversationsRoot(NULL) + , mChatHistory(NULL) + , mInputEditor(NULL) + , mInputEditorTopPad(0) + , mRefreshTimer(new LLTimer()) + , mIsHostAttached(false) +{ + mSession = LLIMModel::getInstance()->findIMSession(mSessionID); + + mCommitCallbackRegistrar.add("IMSession.Menu.Action", + boost::bind(&LLFloaterIMSessionTab::onIMSessionMenuItemClicked, this, _2)); + mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", + boost::bind(&LLFloaterIMSessionTab::onIMCompactExpandedMenuItemCheck, this, _2)); + mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.CheckItem", + boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemCheck, this, _2)); + mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", + boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2)); + + // Zero expiry time is set only once to allow initial update. + mRefreshTimer->setTimerExpirySec(0); + mRefreshTimer->start(); +} + +LLFloaterIMSessionTab::~LLFloaterIMSessionTab() +{ + delete mRefreshTimer; +} + +//static +LLFloaterIMSessionTab* LLFloaterIMSessionTab::findConversation(const LLUUID& uuid) +{ + LLFloaterIMSessionTab* conv; + + if (uuid.isNull()) + { + conv = LLFloaterReg::findTypedInstance<LLFloaterIMSessionTab>("nearby_chat"); + } + else + { + conv = LLFloaterReg::findTypedInstance<LLFloaterIMSessionTab>("impanel", LLSD(uuid)); + } + + return conv; +}; + +//static +LLFloaterIMSessionTab* LLFloaterIMSessionTab::getConversation(const LLUUID& uuid) +{ + LLFloaterIMSessionTab* conv; + + if (uuid.isNull()) + { + conv = LLFloaterReg::getTypedInstance<LLFloaterIMSessionTab>("nearby_chat"); + } + else + { + conv = LLFloaterReg::getTypedInstance<LLFloaterIMSessionTab>("impanel", LLSD(uuid)); + } + + return conv; +}; + +void LLFloaterIMSessionTab::setVisible(BOOL visible) +{ + LLTransientDockableFloater::setVisible(visible); + + if(visible) + { + LLFloaterIMSessionTab::addToHost(mSessionID); + } + setFocus(visible); +} + +/*virtual*/ +void LLFloaterIMSessionTab::setFocus(BOOL focus) +{ + LLTransientDockableFloater::setFocus(focus); + + //Redirect focus to input editor + if (focus) + { + updateMessages(); + + if (mInputEditor) + { + mInputEditor->setFocus(TRUE); + } + } +} + + +void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id) +{ + if ((session_id.notNull() && !gIMMgr->hasSession(session_id)) + || !LLFloaterIMSessionTab::isChatMultiTab()) + { + return; + } + + // Get the floater: this will create the instance if it didn't exist + LLFloaterIMSessionTab* conversp = LLFloaterIMSessionTab::getConversation(session_id); + if (conversp) + { + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + + // Do not add again existing floaters + if (floater_container && !conversp->isHostAttached()) + { + conversp->setHostAttached(true); + + if (!conversp->isNearbyChat() + || gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) + { + floater_container->addFloater(conversp, TRUE, LLTabContainer::END); + } + else + { + // setting of the "potential" host for Nearby Chat: this sequence sets + // LLFloater::mHostHandle = NULL (a current host), but + // LLFloater::mLastHostHandle = floater_container (a "future" host) + conversp->setHost(floater_container); + conversp->setHost(NULL); + } + // Added floaters share some state (like sort order) with their host + conversp->setSortOrder(floater_container->getSortOrder()); + } + } +} + +BOOL LLFloaterIMSessionTab::postBuild() +{ + BOOL result; + + mCloseBtn = getChild<LLButton>("close_btn"); + mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); + + mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); + mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onSlide, this)); + + mTearOffBtn = getChild<LLButton>("tear_off_btn"); + mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this)); + + mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); + + // Create a root view folder for all participants + LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); + LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); + p.rect = LLRect(0, 0, getRect().getWidth(), 0); + p.parent_panel = mParticipantListPanel; + p.listener = base_item; + p.view_model = &mConversationViewModel; + p.root = NULL; + p.use_ellipses = true; + mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); + mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + + // Add a scroller for the folder (participant) view + LLRect scroller_view_rect = mParticipantListPanel->getRect(); + scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); + LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>()); + scroller_params.rect(scroller_view_rect); + LLScrollContainer* scroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); + scroller->setFollowsAll(); + + // Insert that scroller into the panel widgets hierarchy and folder view + mParticipantListPanel->addChild(scroller); + scroller->addChild(mConversationsRoot); + mConversationsRoot->setScrollContainer(scroller); + mConversationsRoot->setFollowsAll(); + mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); + + + mChatHistory = getChild<LLChatHistory>("chat_history"); + + mInputEditor = getChild<LLChatEntry>("chat_editor"); + mInputEditor->setTextExpandedCallback(boost::bind(&LLFloaterIMSessionTab::reshapeChatHistory, this)); + mInputEditor->setCommitOnFocusLost( FALSE ); + mInputEditor->setPassDelete(TRUE); + mInputEditor->setFont(LLViewerChat::getChatFont()); + + mInputEditorTopPad = mChatHistory->getRect().mBottom - mInputEditor->getRect().mTop; + + setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); + + buildConversationViewParticipant(); + + mSaveRect = isTornOff(); + initRectControl(); + + if (isChatMultiTab()) + { + result = LLFloater::postBuild(); + } + else + { + result = LLDockableFloater::postBuild(); + } + + refreshConversation(); + + return result; +} + +LLParticipantList* LLFloaterIMSessionTab::getParticipantList() +{ + return dynamic_cast<LLParticipantList*>(LLFloaterIMContainer::getInstance()->getSessionModel(mSessionID)); +} + +void LLFloaterIMSessionTab::draw() +{ + if (mRefreshTimer->hasExpired()) + { + if (getParticipantList()) + { + getParticipantList()->update(); + } + + refreshConversation(); + + // Restart the refresh timer + mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); + } + + LLTransientDockableFloater::draw(); +} + +void LLFloaterIMSessionTab::enableDisableCallBtn() +{ + getChildView("voice_call_btn")->setEnabled( + mSessionID.notNull() + && mSession + && mSession->mSessionInitialized + && LLVoiceClient::getInstance()->voiceEnabled() + && LLVoiceClient::getInstance()->isVoiceWorking() + && mSession->mCallBackEnabled); +} + +void LLFloaterIMSessionTab::onFocusReceived() +{ + setBackgroundOpaque(true); + + if (mSessionID.notNull() && isInVisibleChain()) + { + LLIMModel::instance().sendNoUnreadMessages(mSessionID); + } + + LLTransientDockableFloater::onFocusReceived(); + + LLFloaterIMContainer* container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + if (container) + { + container->selectConversationPair(mSessionID, true); + } +} + +void LLFloaterIMSessionTab::onFocusLost() +{ + setBackgroundOpaque(false); + LLTransientDockableFloater::onFocusLost(); +} + +std::string LLFloaterIMSessionTab::appendTime() +{ + time_t utc_time; + utc_time = time_corrected(); + std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" + +LLTrans::getString("TimeMin")+"]"; + + LLSD substitution; + + substitution["datetime"] = (S32) utc_time; + LLStringUtil::format (timeStr, substitution); + + return timeStr; +} + +void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD &args) +{ + // Update the participant activity time + LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); + if (im_box) + { + im_box->setTimeNow(mSessionID,chat.mFromID); + } + + + LLChat& tmp_chat = const_cast<LLChat&>(chat); + + if(tmp_chat.mTimeStr.empty()) + tmp_chat.mTimeStr = appendTime(); + + if (!chat.mMuted) + { + tmp_chat.mFromName = chat.mFromName; + LLSD chat_args; + if (args) chat_args = args; + chat_args["use_plain_text_chat_history"] = + gSavedSettings.getBOOL("PlainTextChatHistory"); + chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); + chat_args["show_names_for_p2p_conv"] = + !mIsP2PChat || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + + if (mChatHistory) + { + mChatHistory->appendMessage(chat, chat_args); + } + } +} + + +void LLFloaterIMSessionTab::buildConversationViewParticipant() +{ + // Clear the widget list since we are rebuilding afresh from the model + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + while (widget_it != mConversationsWidgets.end()) + { + removeConversationViewParticipant(widget_it->first); + // Iterators are invalidated by erase so we need to pick begin again + widget_it = mConversationsWidgets.begin(); + } + + // Get the model list + LLParticipantList* item = getParticipantList(); + if (!item) + { + // Nothing to do if the model list is empty + return; + } + + // Create the participants widgets now + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); + while (current_participant_model != end_participant_model) + { + LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); + addConversationViewParticipant(participant_model); + current_participant_model++; + } +} + +void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* participant_model) +{ + // Check if the model already has an associated view + LLUUID uuid = participant_model->getUUID(); + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); + + // If not already present, create the participant view and attach it to the root, otherwise, just refresh it + if (widget) + { + updateConversationViewParticipant(uuid); // overkill? + } + else + { + LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); + mConversationsWidgets[uuid] = participant_view; + participant_view->addToFolder(mConversationsRoot); + participant_view->setVisible(TRUE); + refreshConversation(); + } +} + +void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& participant_id) +{ + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); + if (widget) + { + mConversationsRoot->extractItem(widget); + delete widget; + mConversationsWidgets.erase(participant_id); + refreshConversation(); + } +} + +void LLFloaterIMSessionTab::updateConversationViewParticipant(const LLUUID& participant_id) +{ + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); + if (widget) + { + widget->refresh(); + } + refreshConversation(); +} + +void LLFloaterIMSessionTab::refreshConversation() +{ + // Note: We collect participants names to change the session name only in the case of ad-hoc conversations + bool is_ad_hoc = (mSession ? mSession->isAdHocSessionType() : false); + uuid_vec_t participants_uuids; // uuids vector for building the added participants name string + // For P2P chat, we still need to update the session name who may have changed (switch display name for instance) + if (mIsP2PChat && mSession) + { + participants_uuids.push_back(mSession->mOtherParticipantID); + } + + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + while (widget_it != mConversationsWidgets.end()) + { + // Add the participant to the list except if it's the agent itself (redundant) + if (is_ad_hoc && (widget_it->first != gAgentID)) + { + participants_uuids.push_back(widget_it->first); + } + widget_it->second->refresh(); + widget_it->second->setVisible(TRUE); + ++widget_it; + } + if (is_ad_hoc || mIsP2PChat) + { + // Build the session name and update it + std::string session_name; + if (participants_uuids.size() != 0) + { + LLAvatarActions::buildResidentsString(participants_uuids, session_name); + } + else + { + session_name = LLIMModel::instance().getName(mSessionID); + } + updateSessionName(session_name); + } + mConversationViewModel.requestSortAll(); + mConversationsRoot->arrangeAll(); + mConversationsRoot->update(); + updateHeaderAndToolbar(); + refresh(); +} + +// Copied from LLFloaterIMContainer::createConversationViewParticipant(). Refactor opportunity! +LLConversationViewParticipant* LLFloaterIMSessionTab::createConversationViewParticipant(LLConversationItem* item) +{ + LLRect panel_rect = mParticipantListPanel->getRect(); + + LLConversationViewParticipant::Params params; + params.name = item->getDisplayName(); + params.root = mConversationsRoot; + params.listener = item; + params.rect = LLRect (0, 24, panel_rect.getWidth(), 0); // *TODO: use conversation_view_participant.xml itemHeight value in lieu of 24 + params.tool_tip = params.name; + params.participant_id = item->getUUID(); + + return LLUICtrlFactory::create<LLConversationViewParticipant>(params); +} + +void LLFloaterIMSessionTab::setSortOrder(const LLConversationSort& order) +{ + mConversationViewModel.setSorter(order); + mConversationsRoot->arrangeAll(); + refreshConversation(); +} + +void LLFloaterIMSessionTab::onIMSessionMenuItemClicked(const LLSD& userdata) +{ + std::string item = userdata.asString(); + + if (item == "compact_view" || item == "expanded_view") + { + gSavedSettings.setBOOL("PlainTextChatHistory", item == "compact_view"); + } + else + { + bool prev_value = gSavedSettings.getBOOL(item); + gSavedSettings.setBOOL(item, !prev_value); + } + + LLFloaterIMSessionTab::processChatHistoryStyleUpdate(); +} + + +bool LLFloaterIMSessionTab::onIMCompactExpandedMenuItemCheck(const LLSD& userdata) +{ + std::string item = userdata.asString(); + bool is_plain_text_mode = gSavedSettings.getBOOL("PlainTextChatHistory"); + + return is_plain_text_mode? item == "compact_view" : item == "expanded_view"; +} + + +bool LLFloaterIMSessionTab::onIMShowModesMenuItemCheck(const LLSD& userdata) +{ + return gSavedSettings.getBOOL(userdata.asString()); +} + +// enable/disable states for the "show time" and "show names" items of the show-modes menu +bool LLFloaterIMSessionTab::onIMShowModesMenuItemEnable(const LLSD& userdata) +{ + std::string item = userdata.asString(); + bool plain_text = gSavedSettings.getBOOL("PlainTextChatHistory"); + bool is_not_names = (item != "IMShowNamesForP2PConv"); + return (plain_text && (is_not_names || mIsP2PChat)); +} + +void LLFloaterIMSessionTab::hideOrShowTitle() +{ + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; + LLView* floater_contents = getChild<LLView>("contents_view"); + + LLRect floater_rect = getLocalRect(); + S32 top_border_of_contents = floater_rect.mTop - (isTornOff()? floater_header_size : 0); + LLRect handle_rect (0, floater_rect.mTop, floater_rect.mRight, top_border_of_contents); + LLRect contents_rect (0, top_border_of_contents, floater_rect.mRight, floater_rect.mBottom); + mDragHandle->setShape(handle_rect); + mDragHandle->setVisible(isTornOff()); + floater_contents->setShape(contents_rect); +} + +void LLFloaterIMSessionTab::updateSessionName(const std::string& name) +{ + mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + name); +} + +void LLFloaterIMSessionTab::hideAllStandardButtons() +{ + for (S32 i = 0; i < BUTTON_COUNT; i++) + { + if (mButtons[i]) + { + // Hide the standard header buttons in a docked IM floater. + mButtons[i]->setVisible(false); + } + } +} + +void LLFloaterIMSessionTab::updateHeaderAndToolbar() +{ + // prevent start conversation before its container + LLFloaterIMContainer::getInstance(); + + bool is_torn_off = checkIfTornOff(); + if (!is_torn_off) + { + hideAllStandardButtons(); + } + + hideOrShowTitle(); + + // Participant list should be visible only in torn off floaters. + bool is_participant_list_visible = + is_torn_off + && gSavedSettings.getBOOL("IMShowControlPanel") + && !mIsP2PChat; + + mParticipantListPanel->setVisible(is_participant_list_visible); + + // Display collapse image (<<) if the floater is hosted + // or if it is torn off but has an open control panel. + bool is_expanded = !is_torn_off || is_participant_list_visible; + mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); + + // toggle floater's drag handle and title visibility + if (mDragHandle) + { + mDragHandle->setTitleVisible(is_torn_off); + } + + // The button (>>) should be disabled for torn off P2P conversations. + mExpandCollapseBtn->setEnabled(!is_torn_off || !mIsP2PChat); + + mTearOffBtn->setImageOverlay(getString(is_torn_off? "return_icon" : "tear_off_icon")); + mTearOffBtn->setToolTip(getString(!is_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window")); + + mCloseBtn->setVisible(!is_torn_off && !mIsNearbyChat); + + enableDisableCallBtn(); + + showTranslationCheckbox(); +} + +void LLFloaterIMSessionTab::reshapeChatHistory() +{ + LLRect chat_rect = mChatHistory->getRect(); + LLRect input_rect = mInputEditor->getRect(); + + int delta_height = chat_rect.mBottom - (input_rect.mTop + mInputEditorTopPad); + + chat_rect.setLeftTopAndSize(chat_rect.mLeft, chat_rect.mTop, chat_rect.getWidth(), chat_rect.getHeight() + delta_height); + mChatHistory->setShape(chat_rect); +} + +void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show) +{ + getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(mIsNearbyChat? show : FALSE); +} + +// static +void LLFloaterIMSessionTab::processChatHistoryStyleUpdate() +{ + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); + iter != inst_list.end(); ++iter) + { + LLFloaterIMSession* floater = dynamic_cast<LLFloaterIMSession*>(*iter); + if (floater) + { + floater->reloadMessages(); + } + } + + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); + if (nearby_chat) + { + nearby_chat->reloadMessages(); + } +} + +void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive) +{ + getChild<LLButton>("voice_call_btn")->setImageOverlay( + callIsActive? getString("call_btn_stop") : getString("call_btn_start")); + enableDisableCallBtn(); + +} + +void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self) +{ + LLFloaterIMContainer* host_floater = dynamic_cast<LLFloaterIMContainer*>(self->getHost()); + if (host_floater) + { + // Hide the messages pane if a floater is hosted in the Conversations + host_floater->collapseMessagesPane(true); + } + else ///< floater is torn off + { + if (!self->mIsP2PChat) + { + bool expand = !self->mParticipantListPanel->getVisible(); + + // Expand/collapse the IM control panel + self->mParticipantListPanel->setVisible(expand); + + gSavedSettings.setBOOL("IMShowControlPanel", expand); + + self->mExpandCollapseBtn->setImageOverlay(self->getString(expand ? "collapse_icon" : "expand_icon")); + } + } +} + +/*virtual*/ +void LLFloaterIMSessionTab::onOpen(const LLSD& key) +{ + if (!checkIfTornOff()) + { + LLFloaterIMContainer* host_floater = dynamic_cast<LLFloaterIMContainer*>(getHost()); + // Show the messages pane when opening a floater hosted in the Conversations + host_floater->collapseMessagesPane(false); + } +} + +// virtual +void LLFloaterIMSessionTab::onClose(bool app_quitting) +{ + // Always suppress the IM from the conversations list on close if present for any reason + if (LLFloaterIMSessionTab::isChatMultiTab()) + { + LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); + if (im_box) + { + im_box->removeConversationListItem(mKey); + } + } +} + +void LLFloaterIMSessionTab::onTearOffClicked() +{ + setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); + mSaveRect = isTornOff(); + initRectControl(); + LLFloater::onClickTearOff(this); + refreshConversation(); +} + +// static +bool LLFloaterIMSessionTab::isChatMultiTab() +{ + // Restart is required in order to change chat window type. + return true; +} + +bool LLFloaterIMSessionTab::checkIfTornOff() +{ + bool isTorn = !getHost(); + + if (isTorn != isTornOff()) + { + setTornOff(isTorn); + refreshConversation(); + } + + return isTorn; +} diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h new file mode 100644 index 0000000000..94854ee9ee --- /dev/null +++ b/indra/newview/llfloaterimsessiontab.h @@ -0,0 +1,176 @@ +/** + * @file llfloaterimsessiontab.h + * @brief LLFloaterIMSessionTab class implements the common behavior of LNearbyChatBar + * @brief and LLFloaterIMSession for hosting both in LLIMContainer + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_FLOATERIMSESSIONTAB_H +#define LL_FLOATERIMSESSIONTAB_H + +#include "lllayoutstack.h" +#include "llparticipantlist.h" +#include "lltransientdockablefloater.h" +#include "llviewercontrol.h" +#include "lleventtimer.h" +#include "llimview.h" +#include "llconversationmodel.h" +#include "llconversationview.h" +#include "lltexteditor.h" + +class LLPanelChatControlPanel; +class LLChatEntry; +class LLChatHistory; + +class LLFloaterIMSessionTab + : public LLTransientDockableFloater +{ + +public: + LOG_CLASS(LLFloaterIMSessionTab); + + LLFloaterIMSessionTab(const LLSD& session_id); + ~LLFloaterIMSessionTab(); + + // reload all message with new settings of visual modes + static void processChatHistoryStyleUpdate(); + + /** + * Returns true if chat is displayed in multi tabbed floater + * false if chat is displayed in multiple windows + */ + static bool isChatMultiTab(); + + // add conversation to container + static void addToHost(const LLUUID& session_id); + + bool isHostAttached() {return mIsHostAttached;} + void setHostAttached(bool is_attached) {mIsHostAttached = is_attached;} + + static LLFloaterIMSessionTab* findConversation(const LLUUID& uuid); + static LLFloaterIMSessionTab* getConversation(const LLUUID& uuid); + + // show/hide the translation check box + void showTranslationCheckbox(const BOOL visible = FALSE); + + bool isNearbyChat() {return mIsNearbyChat;} + + // LLFloater overrides + /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClose(bool app_quitting); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); + /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ void setFocus(BOOL focus); + + // Handle the left hand participant list widgets + void addConversationViewParticipant(LLConversationItem* item); + void removeConversationViewParticipant(const LLUUID& participant_id); + void updateConversationViewParticipant(const LLUUID& participant_id); + void refreshConversation(); + void buildConversationViewParticipant(); + + void setSortOrder(const LLConversationSort& order); + + virtual void updateMessages() {} + +protected: + + // callback for click on any items of the visual states menu + void onIMSessionMenuItemClicked(const LLSD& userdata); + + // callback for check/uncheck of the expanded/collapse mode's switcher + bool onIMCompactExpandedMenuItemCheck(const LLSD& userdata); + + // + bool onIMShowModesMenuItemCheck(const LLSD& userdata); + bool onIMShowModesMenuItemEnable(const LLSD& userdata); + static void onSlide(LLFloaterIMSessionTab *self); + virtual void onTearOffClicked(); + + // refresh a visual state of the Call button + void updateCallBtnState(bool callIsActive); + + void hideOrShowTitle(); // toggle the floater's drag handle + void hideAllStandardButtons(); + + /// Update floater header and toolbar buttons when hosted/torn off state is toggled. + void updateHeaderAndToolbar(); + + // Update the input field help text and other places that need the session name + virtual void updateSessionName(const std::string& name); + + // set the enable/disable state for the Call button + virtual void enableDisableCallBtn(); + + // process focus events to set a currently active session + /* virtual */ void onFocusLost(); + /* virtual */ void onFocusReceived(); + + // prepare chat's params and out one message to chatHistory + void appendMessage(const LLChat& chat, const LLSD &args = 0); + + std::string appendTime(); + + bool mIsNearbyChat; + bool mIsP2PChat; + + LLIMModel::LLIMSession* mSession; + + // Participants list: model and view + LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item); + + LLUUID mSessionID; + LLLayoutPanel* mParticipantListPanel; // add the widgets to that see mConversationsListPanel + LLParticipantList* getParticipantList(); + conversations_widgets_map mConversationsWidgets; + LLConversationViewModel mConversationViewModel; + LLFolderView* mConversationsRoot; + + LLChatHistory* mChatHistory; + LLChatEntry* mInputEditor; + int mInputEditorTopPad; // padding between input field and chat history + + LLButton* mExpandCollapseBtn; + LLButton* mTearOffBtn; + LLButton* mCloseBtn; + +private: + /// Refreshes the floater at a constant rate. + virtual void refresh() = 0; + + /** + * Adjusts chat history height to fit vertically with input chat field + * and avoid overlapping, since input chat field can be vertically expanded. + * Implementation: chat history bottom "follows" top+top_pad of input chat field + */ + void reshapeChatHistory(); + + bool checkIfTornOff(); + bool mIsHostAttached; + + LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. +}; + + +#endif /* LL_FLOATERIMSESSIONTAB_H */ diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index b60af1a635..7c5e0776a7 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -51,11 +51,11 @@ #include "llfloaterabout.h" #include "llfloaterhardwaresettings.h" #include "llfloatersidepanelcontainer.h" -#include "llimfloater.h" +#include "llfloaterimsession.h" #include "llkeyboard.h" #include "llmodaldialog.h" #include "llnavigationbar.h" -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llnotificationtemplate.h" @@ -425,7 +425,7 @@ void LLFloaterPreference::saveAvatarProperties( void ) BOOL LLFloaterPreference::postBuild() { - gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); + gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate)); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLViewerChat::signalChatFontChanged)); diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 29d7732a68..6a9236ce0c 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -29,7 +29,7 @@ #include "llfloatertranslationsettings.h" // Viewer includes -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" #include "lltranslate.h" #include "llviewercontrol.h" // for gSavedSettings @@ -293,7 +293,7 @@ void LLFloaterTranslationSettings::onBtnOK() gSavedSettings.setString("TranslationService", getSelectedService()); gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey()); gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); - (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> + (LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))-> showTranslationCheckbox(LLTranslate::isTranslationConfigured()); closeFloater(false); } diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 0996af6125..f307505ff8 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -52,7 +52,7 @@ #include "llviewermessage.h" #include "llvoavatarself.h" #include "llviewerstats.h" -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" #include "llappearancemgr.h" #include "llgesturelistener.h" @@ -998,7 +998,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) const BOOL animate = FALSE; - (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> + (LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))-> sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); gesture->mCurrentStep++; diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index 15eca39bce..a0f2918bd7 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -36,7 +36,7 @@ #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" #include "llgroupmgr.h" -#include "llimfloatercontainer.h" +#include "llfloaterimcontainer.h" #include "llimview.h" // for gIMMgr #include "llnotificationsutil.h" #include "llstatusbar.h" // can_afford_transaction() @@ -335,7 +335,7 @@ LLUUID LLGroupActions::startIM(const LLUUID& group_id) group_id); if (session_id != LLUUID::null) { - LLIMFloaterContainer::getInstance()->showConversation(session_id); + LLFloaterIMContainer::getInstance()->showConversation(session_id); } make_ui_sound("UISndStartIM"); return session_id; diff --git a/indra/newview/llgroupiconctrl.cpp b/indra/newview/llgroupiconctrl.cpp index 2f9810775b..188c4bcf25 100644 --- a/indra/newview/llgroupiconctrl.cpp +++ b/indra/newview/llgroupiconctrl.cpp @@ -38,7 +38,7 @@ #include "llcachename.h" #include "llagentdata.h" -#include "llimfloater.h" +#include "llfloaterimsession.h" */ static LLDefaultChildRegistry::Register<LLGroupIconCtrl> g_i("group_icon"); diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp deleted file mode 100644 index a321b3545a..0000000000 --- a/indra/newview/llimconversation.cpp +++ /dev/null @@ -1,743 +0,0 @@ -/** - * @file llimconversation.cpp - * @brief LLIMConversation class implements the common behavior of LNearbyChatBar - * @brief and LLIMFloater for hosting both in LLIMContainer - * - * $LicenseInfo:firstyear=2012&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llimconversation.h" - -#include "llagent.h" -#include "llavataractions.h" -#include "llchatentry.h" -#include "llchathistory.h" -#include "llchiclet.h" -#include "llchicletbar.h" -#include "lldraghandle.h" -#include "llfloaterreg.h" -#include "llimfloater.h" -#include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container -#include "lllayoutstack.h" -#include "llnearbychat.h" - -const F32 REFRESH_INTERVAL = 0.2f; - -LLIMConversation::LLIMConversation(const LLSD& session_id) - : LLTransientDockableFloater(NULL, true, session_id) - , mIsP2PChat(false) - , mExpandCollapseBtn(NULL) - , mTearOffBtn(NULL) - , mCloseBtn(NULL) - , mSessionID(session_id.asUUID()) - , mConversationsRoot(NULL) - , mChatHistory(NULL) - , mInputEditor(NULL) - , mInputEditorTopPad(0) - , mRefreshTimer(new LLTimer()) - , mIsHostAttached(false) -{ - mSession = LLIMModel::getInstance()->findIMSession(mSessionID); - - mCommitCallbackRegistrar.add("IMSession.Menu.Action", - boost::bind(&LLIMConversation::onIMSessionMenuItemClicked, this, _2)); - mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", - boost::bind(&LLIMConversation::onIMCompactExpandedMenuItemCheck, this, _2)); - mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.CheckItem", - boost::bind(&LLIMConversation::onIMShowModesMenuItemCheck, this, _2)); - mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", - boost::bind(&LLIMConversation::onIMShowModesMenuItemEnable, this, _2)); - - // Zero expiry time is set only once to allow initial update. - mRefreshTimer->setTimerExpirySec(0); - mRefreshTimer->start(); -} - -LLIMConversation::~LLIMConversation() -{ - delete mRefreshTimer; -} - -//static -LLIMConversation* LLIMConversation::findConversation(const LLUUID& uuid) -{ - LLIMConversation* conv; - - if (uuid.isNull()) - { - conv = LLFloaterReg::findTypedInstance<LLIMConversation>("nearby_chat"); - } - else - { - conv = LLFloaterReg::findTypedInstance<LLIMConversation>("impanel", LLSD(uuid)); - } - - return conv; -}; - -//static -LLIMConversation* LLIMConversation::getConversation(const LLUUID& uuid) -{ - LLIMConversation* conv; - - if (uuid.isNull()) - { - conv = LLFloaterReg::getTypedInstance<LLIMConversation>("nearby_chat"); - } - else - { - conv = LLFloaterReg::getTypedInstance<LLIMConversation>("impanel", LLSD(uuid)); - } - - return conv; -}; - -void LLIMConversation::setVisible(BOOL visible) -{ - LLTransientDockableFloater::setVisible(visible); - - if(visible) - { - LLIMConversation::addToHost(mSessionID); - } - setFocus(visible); -} - -/*virtual*/ -void LLIMConversation::setFocus(BOOL focus) -{ - LLTransientDockableFloater::setFocus(focus); - - //Redirect focus to input editor - if (focus) - { - updateMessages(); - - if (mInputEditor) - { - mInputEditor->setFocus(TRUE); - } - } -} - - -void LLIMConversation::addToHost(const LLUUID& session_id) -{ - if ((session_id.notNull() && !gIMMgr->hasSession(session_id)) - || !LLIMConversation::isChatMultiTab()) - { - return; - } - - // Get the floater: this will create the instance if it didn't exist - LLIMConversation* conversp = LLIMConversation::getConversation(session_id); - if (conversp) - { - LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); - - // Do not add again existing floaters - if (floater_container && !conversp->isHostAttached()) - { - conversp->setHostAttached(true); - - if (!conversp->isNearbyChat() - || gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) - { - floater_container->addFloater(conversp, TRUE, LLTabContainer::END); - } - else - { - // setting of the "potential" host for Nearby Chat: this sequence sets - // LLFloater::mHostHandle = NULL (a current host), but - // LLFloater::mLastHostHandle = floater_container (a "future" host) - conversp->setHost(floater_container); - conversp->setHost(NULL); - } - // Added floaters share some state (like sort order) with their host - conversp->setSortOrder(floater_container->getSortOrder()); - } - } -} - -BOOL LLIMConversation::postBuild() -{ - BOOL result; - - mCloseBtn = getChild<LLButton>("close_btn"); - mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); - - mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); - mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this)); - - mTearOffBtn = getChild<LLButton>("tear_off_btn"); - mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); - - mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); - - // Create a root view folder for all participants - LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); - LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); - p.rect = LLRect(0, 0, getRect().getWidth(), 0); - p.parent_panel = mParticipantListPanel; - p.listener = base_item; - p.view_model = &mConversationViewModel; - p.root = NULL; - p.use_ellipses = true; - mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); - mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); - - // Add a scroller for the folder (participant) view - LLRect scroller_view_rect = mParticipantListPanel->getRect(); - scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); - LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>()); - scroller_params.rect(scroller_view_rect); - LLScrollContainer* scroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); - scroller->setFollowsAll(); - - // Insert that scroller into the panel widgets hierarchy and folder view - mParticipantListPanel->addChild(scroller); - scroller->addChild(mConversationsRoot); - mConversationsRoot->setScrollContainer(scroller); - mConversationsRoot->setFollowsAll(); - mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); - - - mChatHistory = getChild<LLChatHistory>("chat_history"); - - mInputEditor = getChild<LLChatEntry>("chat_editor"); - mInputEditor->setTextExpandedCallback(boost::bind(&LLIMConversation::reshapeChatHistory, this)); - mInputEditor->setCommitOnFocusLost( FALSE ); - mInputEditor->setPassDelete(TRUE); - mInputEditor->setFont(LLViewerChat::getChatFont()); - - mInputEditorTopPad = mChatHistory->getRect().mBottom - mInputEditor->getRect().mTop; - - setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); - - buildConversationViewParticipant(); - - mSaveRect = isTornOff(); - initRectControl(); - - if (isChatMultiTab()) - { - result = LLFloater::postBuild(); - } - else - { - result = LLDockableFloater::postBuild(); - } - - refreshConversation(); - - return result; -} - -LLParticipantList* LLIMConversation::getParticipantList() -{ - return dynamic_cast<LLParticipantList*>(LLIMFloaterContainer::getInstance()->getSessionModel(mSessionID)); -} - -void LLIMConversation::draw() -{ - if (mRefreshTimer->hasExpired()) - { - if (getParticipantList()) - { - getParticipantList()->update(); - } - - refreshConversation(); - - // Restart the refresh timer - mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); - } - - LLTransientDockableFloater::draw(); -} - -void LLIMConversation::enableDisableCallBtn() -{ - getChildView("voice_call_btn")->setEnabled( - mSessionID.notNull() - && mSession - && mSession->mSessionInitialized - && LLVoiceClient::getInstance()->voiceEnabled() - && LLVoiceClient::getInstance()->isVoiceWorking() - && mSession->mCallBackEnabled); -} - -void LLIMConversation::onFocusReceived() -{ - setBackgroundOpaque(true); - - if (mSessionID.notNull() && isInVisibleChain()) - { - LLIMModel::instance().sendNoUnreadMessages(mSessionID); - } - - LLTransientDockableFloater::onFocusReceived(); - - LLIMFloaterContainer* container = LLFloaterReg::getTypedInstance<LLIMFloaterContainer>("im_container"); - if (container) - { - container->selectConversationPair(mSessionID, true); - } -} - -void LLIMConversation::onFocusLost() -{ - setBackgroundOpaque(false); - LLTransientDockableFloater::onFocusLost(); -} - -std::string LLIMConversation::appendTime() -{ - time_t utc_time; - utc_time = time_corrected(); - std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" - +LLTrans::getString("TimeMin")+"]"; - - LLSD substitution; - - substitution["datetime"] = (S32) utc_time; - LLStringUtil::format (timeStr, substitution); - - return timeStr; -} - -void LLIMConversation::appendMessage(const LLChat& chat, const LLSD &args) -{ - // Update the participant activity time - LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); - if (im_box) - { - im_box->setTimeNow(mSessionID,chat.mFromID); - } - - - LLChat& tmp_chat = const_cast<LLChat&>(chat); - - if(tmp_chat.mTimeStr.empty()) - tmp_chat.mTimeStr = appendTime(); - - if (!chat.mMuted) - { - tmp_chat.mFromName = chat.mFromName; - LLSD chat_args; - if (args) chat_args = args; - chat_args["use_plain_text_chat_history"] = - gSavedSettings.getBOOL("PlainTextChatHistory"); - chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); - chat_args["show_names_for_p2p_conv"] = - !mIsP2PChat || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); - - if (mChatHistory) - { - mChatHistory->appendMessage(chat, chat_args); - } - } -} - - -void LLIMConversation::buildConversationViewParticipant() -{ - // Clear the widget list since we are rebuilding afresh from the model - conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); - while (widget_it != mConversationsWidgets.end()) - { - removeConversationViewParticipant(widget_it->first); - // Iterators are invalidated by erase so we need to pick begin again - widget_it = mConversationsWidgets.begin(); - } - - // Get the model list - LLParticipantList* item = getParticipantList(); - if (!item) - { - // Nothing to do if the model list is empty - return; - } - - // Create the participants widgets now - LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); - LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); - while (current_participant_model != end_participant_model) - { - LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); - addConversationViewParticipant(participant_model); - current_participant_model++; - } -} - -void LLIMConversation::addConversationViewParticipant(LLConversationItem* participant_model) -{ - // Check if the model already has an associated view - LLUUID uuid = participant_model->getUUID(); - LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); - - // If not already present, create the participant view and attach it to the root, otherwise, just refresh it - if (widget) - { - updateConversationViewParticipant(uuid); // overkill? - } - else - { - LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); - mConversationsWidgets[uuid] = participant_view; - participant_view->addToFolder(mConversationsRoot); - participant_view->setVisible(TRUE); - refreshConversation(); - } -} - -void LLIMConversation::removeConversationViewParticipant(const LLUUID& participant_id) -{ - LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); - if (widget) - { - mConversationsRoot->extractItem(widget); - delete widget; - mConversationsWidgets.erase(participant_id); - refreshConversation(); - } -} - -void LLIMConversation::updateConversationViewParticipant(const LLUUID& participant_id) -{ - LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); - if (widget) - { - widget->refresh(); - } - refreshConversation(); -} - -void LLIMConversation::refreshConversation() -{ - // Note: We collect participants names to change the session name only in the case of ad-hoc conversations - bool is_ad_hoc = (mSession ? mSession->isAdHocSessionType() : false); - uuid_vec_t participants_uuids; // uuids vector for building the added participants name string - // For P2P chat, we still need to update the session name who may have changed (switch display name for instance) - if (mIsP2PChat && mSession) - { - participants_uuids.push_back(mSession->mOtherParticipantID); - } - - conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); - while (widget_it != mConversationsWidgets.end()) - { - // Add the participant to the list except if it's the agent itself (redundant) - if (is_ad_hoc && (widget_it->first != gAgentID)) - { - participants_uuids.push_back(widget_it->first); - } - widget_it->second->refresh(); - widget_it->second->setVisible(TRUE); - ++widget_it; - } - if (is_ad_hoc || mIsP2PChat) - { - // Build the session name and update it - std::string session_name; - if (participants_uuids.size() != 0) - { - LLAvatarActions::buildResidentsString(participants_uuids, session_name); - } - else - { - session_name = LLIMModel::instance().getName(mSessionID); - } - updateSessionName(session_name); - } - mConversationViewModel.requestSortAll(); - mConversationsRoot->arrangeAll(); - mConversationsRoot->update(); - updateHeaderAndToolbar(); - refresh(); -} - -// Copied from LLIMFloaterContainer::createConversationViewParticipant(). Refactor opportunity! -LLConversationViewParticipant* LLIMConversation::createConversationViewParticipant(LLConversationItem* item) -{ - LLRect panel_rect = mParticipantListPanel->getRect(); - - LLConversationViewParticipant::Params params; - params.name = item->getDisplayName(); - params.root = mConversationsRoot; - params.listener = item; - params.rect = LLRect (0, 24, panel_rect.getWidth(), 0); // *TODO: use conversation_view_participant.xml itemHeight value in lieu of 24 - params.tool_tip = params.name; - params.participant_id = item->getUUID(); - - return LLUICtrlFactory::create<LLConversationViewParticipant>(params); -} - -void LLIMConversation::setSortOrder(const LLConversationSort& order) -{ - mConversationViewModel.setSorter(order); - mConversationsRoot->arrangeAll(); - refreshConversation(); -} - -void LLIMConversation::onIMSessionMenuItemClicked(const LLSD& userdata) -{ - std::string item = userdata.asString(); - - if (item == "compact_view" || item == "expanded_view") - { - gSavedSettings.setBOOL("PlainTextChatHistory", item == "compact_view"); - } - else - { - bool prev_value = gSavedSettings.getBOOL(item); - gSavedSettings.setBOOL(item, !prev_value); - } - - LLIMConversation::processChatHistoryStyleUpdate(); -} - - -bool LLIMConversation::onIMCompactExpandedMenuItemCheck(const LLSD& userdata) -{ - std::string item = userdata.asString(); - bool is_plain_text_mode = gSavedSettings.getBOOL("PlainTextChatHistory"); - - return is_plain_text_mode? item == "compact_view" : item == "expanded_view"; -} - - -bool LLIMConversation::onIMShowModesMenuItemCheck(const LLSD& userdata) -{ - return gSavedSettings.getBOOL(userdata.asString()); -} - -// enable/disable states for the "show time" and "show names" items of the show-modes menu -bool LLIMConversation::onIMShowModesMenuItemEnable(const LLSD& userdata) -{ - std::string item = userdata.asString(); - bool plain_text = gSavedSettings.getBOOL("PlainTextChatHistory"); - bool is_not_names = (item != "IMShowNamesForP2PConv"); - return (plain_text && (is_not_names || mIsP2PChat)); -} - -void LLIMConversation::hideOrShowTitle() -{ - const LLFloater::Params& default_params = LLFloater::getDefaultParams(); - S32 floater_header_size = default_params.header_height; - LLView* floater_contents = getChild<LLView>("contents_view"); - - LLRect floater_rect = getLocalRect(); - S32 top_border_of_contents = floater_rect.mTop - (isTornOff()? floater_header_size : 0); - LLRect handle_rect (0, floater_rect.mTop, floater_rect.mRight, top_border_of_contents); - LLRect contents_rect (0, top_border_of_contents, floater_rect.mRight, floater_rect.mBottom); - mDragHandle->setShape(handle_rect); - mDragHandle->setVisible(isTornOff()); - floater_contents->setShape(contents_rect); -} - -void LLIMConversation::updateSessionName(const std::string& name) -{ - mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + name); -} - -void LLIMConversation::hideAllStandardButtons() -{ - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - if (mButtons[i]) - { - // Hide the standard header buttons in a docked IM floater. - mButtons[i]->setVisible(false); - } - } -} - -void LLIMConversation::updateHeaderAndToolbar() -{ - // prevent start conversation before its container - LLIMFloaterContainer::getInstance(); - - bool is_torn_off = checkIfTornOff(); - if (!is_torn_off) - { - hideAllStandardButtons(); - } - - hideOrShowTitle(); - - // Participant list should be visible only in torn off floaters. - bool is_participant_list_visible = - is_torn_off - && gSavedSettings.getBOOL("IMShowControlPanel") - && !mIsP2PChat; - - mParticipantListPanel->setVisible(is_participant_list_visible); - - // Display collapse image (<<) if the floater is hosted - // or if it is torn off but has an open control panel. - bool is_expanded = !is_torn_off || is_participant_list_visible; - mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); - - // toggle floater's drag handle and title visibility - if (mDragHandle) - { - mDragHandle->setTitleVisible(is_torn_off); - } - - // The button (>>) should be disabled for torn off P2P conversations. - mExpandCollapseBtn->setEnabled(!is_torn_off || !mIsP2PChat); - - mTearOffBtn->setImageOverlay(getString(is_torn_off? "return_icon" : "tear_off_icon")); - mTearOffBtn->setToolTip(getString(!is_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window")); - - mCloseBtn->setVisible(!is_torn_off && !mIsNearbyChat); - - enableDisableCallBtn(); - - showTranslationCheckbox(); -} - -void LLIMConversation::reshapeChatHistory() -{ - LLRect chat_rect = mChatHistory->getRect(); - LLRect input_rect = mInputEditor->getRect(); - - int delta_height = chat_rect.mBottom - (input_rect.mTop + mInputEditorTopPad); - - chat_rect.setLeftTopAndSize(chat_rect.mLeft, chat_rect.mTop, chat_rect.getWidth(), chat_rect.getHeight() + delta_height); - mChatHistory->setShape(chat_rect); -} - -void LLIMConversation::showTranslationCheckbox(BOOL show) -{ - getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(mIsNearbyChat? show : FALSE); -} - -// static -void LLIMConversation::processChatHistoryStyleUpdate() -{ - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); - iter != inst_list.end(); ++iter) - { - LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); - if (floater) - { - floater->reloadMessages(); - } - } - - LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); - if (nearby_chat) - { - nearby_chat->reloadMessages(); - } -} - -void LLIMConversation::updateCallBtnState(bool callIsActive) -{ - getChild<LLButton>("voice_call_btn")->setImageOverlay( - callIsActive? getString("call_btn_stop") : getString("call_btn_start")); - enableDisableCallBtn(); - -} - -void LLIMConversation::onSlide(LLIMConversation* self) -{ - LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(self->getHost()); - if (host_floater) - { - // Hide the messages pane if a floater is hosted in the Conversations - host_floater->collapseMessagesPane(true); - } - else ///< floater is torn off - { - if (!self->mIsP2PChat) - { - bool expand = !self->mParticipantListPanel->getVisible(); - - // Expand/collapse the IM control panel - self->mParticipantListPanel->setVisible(expand); - - gSavedSettings.setBOOL("IMShowControlPanel", expand); - - self->mExpandCollapseBtn->setImageOverlay(self->getString(expand ? "collapse_icon" : "expand_icon")); - } - } -} - -/*virtual*/ -void LLIMConversation::onOpen(const LLSD& key) -{ - if (!checkIfTornOff()) - { - LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); - // Show the messages pane when opening a floater hosted in the Conversations - host_floater->collapseMessagesPane(false); - } -} - -// virtual -void LLIMConversation::onClose(bool app_quitting) -{ - // Always suppress the IM from the conversations list on close if present for any reason - if (LLIMConversation::isChatMultiTab()) - { - LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); - if (im_box) - { - im_box->removeConversationListItem(mKey); - } - } -} - -void LLIMConversation::onTearOffClicked() -{ - setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); - mSaveRect = isTornOff(); - initRectControl(); - LLFloater::onClickTearOff(this); - refreshConversation(); -} - -// static -bool LLIMConversation::isChatMultiTab() -{ - // Restart is required in order to change chat window type. - return true; -} - -bool LLIMConversation::checkIfTornOff() -{ - bool isTorn = !getHost(); - - if (isTorn != isTornOff()) - { - setTornOff(isTorn); - refreshConversation(); - } - - return isTorn; -} diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h deleted file mode 100644 index 93a1ab847e..0000000000 --- a/indra/newview/llimconversation.h +++ /dev/null @@ -1,176 +0,0 @@ -/** - * @file llimconversation.h - * @brief LLIMConversation class implements the common behavior of LNearbyChatBar - * @brief and LLIMFloater for hosting both in LLIMContainer - * - * $LicenseInfo:firstyear=2012&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_IMCONVERSATION_H -#define LL_IMCONVERSATION_H - -#include "lllayoutstack.h" -#include "llparticipantlist.h" -#include "lltransientdockablefloater.h" -#include "llviewercontrol.h" -#include "lleventtimer.h" -#include "llimview.h" -#include "llconversationmodel.h" -#include "llconversationview.h" -#include "lltexteditor.h" - -class LLPanelChatControlPanel; -class LLChatEntry; -class LLChatHistory; - -class LLIMConversation - : public LLTransientDockableFloater -{ - -public: - LOG_CLASS(LLIMConversation); - - LLIMConversation(const LLSD& session_id); - ~LLIMConversation(); - - // reload all message with new settings of visual modes - static void processChatHistoryStyleUpdate(); - - /** - * Returns true if chat is displayed in multi tabbed floater - * false if chat is displayed in multiple windows - */ - static bool isChatMultiTab(); - - // add conversation to container - static void addToHost(const LLUUID& session_id); - - bool isHostAttached() {return mIsHostAttached;} - void setHostAttached(bool is_attached) {mIsHostAttached = is_attached;} - - static LLIMConversation* findConversation(const LLUUID& uuid); - static LLIMConversation* getConversation(const LLUUID& uuid); - - // show/hide the translation check box - void showTranslationCheckbox(const BOOL visible = FALSE); - - bool isNearbyChat() {return mIsNearbyChat;} - - // LLFloater overrides - /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void onClose(bool app_quitting); - /*virtual*/ BOOL postBuild(); - /*virtual*/ void draw(); - /*virtual*/ void setVisible(BOOL visible); - /*virtual*/ void setFocus(BOOL focus); - - // Handle the left hand participant list widgets - void addConversationViewParticipant(LLConversationItem* item); - void removeConversationViewParticipant(const LLUUID& participant_id); - void updateConversationViewParticipant(const LLUUID& participant_id); - void refreshConversation(); - void buildConversationViewParticipant(); - - void setSortOrder(const LLConversationSort& order); - - virtual void updateMessages() {} - -protected: - - // callback for click on any items of the visual states menu - void onIMSessionMenuItemClicked(const LLSD& userdata); - - // callback for check/uncheck of the expanded/collapse mode's switcher - bool onIMCompactExpandedMenuItemCheck(const LLSD& userdata); - - // - bool onIMShowModesMenuItemCheck(const LLSD& userdata); - bool onIMShowModesMenuItemEnable(const LLSD& userdata); - static void onSlide(LLIMConversation *self); - virtual void onTearOffClicked(); - - // refresh a visual state of the Call button - void updateCallBtnState(bool callIsActive); - - void hideOrShowTitle(); // toggle the floater's drag handle - void hideAllStandardButtons(); - - /// Update floater header and toolbar buttons when hosted/torn off state is toggled. - void updateHeaderAndToolbar(); - - // Update the input field help text and other places that need the session name - virtual void updateSessionName(const std::string& name); - - // set the enable/disable state for the Call button - virtual void enableDisableCallBtn(); - - // process focus events to set a currently active session - /* virtual */ void onFocusLost(); - /* virtual */ void onFocusReceived(); - - // prepare chat's params and out one message to chatHistory - void appendMessage(const LLChat& chat, const LLSD &args = 0); - - std::string appendTime(); - - bool mIsNearbyChat; - bool mIsP2PChat; - - LLIMModel::LLIMSession* mSession; - - // Participants list: model and view - LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item); - - LLUUID mSessionID; - LLLayoutPanel* mParticipantListPanel; // add the widgets to that see mConversationsListPanel - LLParticipantList* getParticipantList(); - conversations_widgets_map mConversationsWidgets; - LLConversationViewModel mConversationViewModel; - LLFolderView* mConversationsRoot; - - LLChatHistory* mChatHistory; - LLChatEntry* mInputEditor; - int mInputEditorTopPad; // padding between input field and chat history - - LLButton* mExpandCollapseBtn; - LLButton* mTearOffBtn; - LLButton* mCloseBtn; - -private: - /// Refreshes the floater at a constant rate. - virtual void refresh() = 0; - - /** - * Adjusts chat history height to fit vertically with input chat field - * and avoid overlapping, since input chat field can be vertically expanded. - * Implementation: chat history bottom "follows" top+top_pad of input chat field - */ - void reshapeChatHistory(); - - bool checkIfTornOff(); - bool mIsHostAttached; - - LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. -}; - - -#endif // LL_IMCONVERSATION_H diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp deleted file mode 100644 index 73c7be37eb..0000000000 --- a/indra/newview/llimfloater.cpp +++ /dev/null @@ -1,1202 +0,0 @@ -/** - * @file llimfloater.cpp - * @brief LLIMFloater class definition - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llimfloater.h" - -#include "lldraghandle.h" -#include "llnotificationsutil.h" - -#include "llagent.h" -#include "llappviewer.h" -#include "llavataractions.h" -#include "llavatarnamecache.h" -#include "llbutton.h" -#include "llchannelmanager.h" -#include "llchiclet.h" -#include "llchicletbar.h" -#include "llfloaterreg.h" -#include "llfloateravatarpicker.h" -#include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container -#include "llinventoryfunctions.h" -//#include "lllayoutstack.h" -#include "llchatentry.h" -#include "lllogchat.h" -#include "llscreenchannel.h" -#include "llsyswellwindow.h" -#include "lltrans.h" -#include "llchathistory.h" -#include "llnotifications.h" -#include "llviewerwindow.h" -#include "lltransientfloatermgr.h" -#include "llinventorymodel.h" -#include "llrootview.h" -#include "llspeakers.h" -#include "llviewerchat.h" -#include "llnotificationmanager.h" -#include "llautoreplace.h" - -floater_showed_signal_t LLIMFloater::sIMFloaterShowedSignal; - -LLIMFloater::LLIMFloater(const LLUUID& session_id) - : LLIMConversation(session_id), - mLastMessageIndex(-1), - mDialog(IM_NOTHING_SPECIAL), - mSavedTitle(), - mTypingStart(), - mShouldSendTypingState(false), - mMeTyping(false), - mOtherTyping(false), - mTypingTimer(), - mTypingTimeoutTimer(), - mPositioned(false), - mSessionInitialized(false), - mStartConferenceInSameFloater(false) -{ - mIsNearbyChat = false; - - initIMSession(session_id); - - setOverlapsScreenChannel(true); - - LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); - - setDocked(true); -} - - -// virtual -void LLIMFloater::refresh() -{ - if (mMeTyping) -{ - // Time out if user hasn't typed for a while. - if (mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS) - { - setTyping(false); - } - } -} - -// virtual -void LLIMFloater::onClickCloseBtn() -{ - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); - - if (session != NULL) - { - bool is_call_with_chat = session->isGroupSessionType() - || session->isAdHocSessionType() || session->isP2PSessionType(); - - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - - if (is_call_with_chat && voice_channel != NULL - && voice_channel->isActive()) - { - LLSD payload; - payload["session_id"] = mSessionID; - LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); - return; - } - } - else - { - llwarns << "Empty session with id: " << (mSessionID.asString()) << llendl; - return; - } - - LLIMConversation::onClickCloseBtn(); -} - -/* static */ -void LLIMFloater::newIMCallback(const LLSD& data) -{ - if (data["num_unread"].asInteger() > 0 || data["from_id"].asUUID().isNull()) - { - LLUUID session_id = data["session_id"].asUUID(); - - LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); - - // update if visible, otherwise will be updated when opened - if (floater && floater->getVisible()) - { - floater->updateMessages(); - } - } -} - -void LLIMFloater::onVisibilityChange(const LLSD& new_visibility) -{ - bool visible = new_visibility.asBoolean(); - - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - - if (visible && voice_channel && - voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED) - { - LLFloaterReg::showInstance("voice_call", mSessionID); - } - else - { - LLFloaterReg::hideInstance("voice_call", mSessionID); - } -} - -void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata ) -{ - LLIMFloater* self = (LLIMFloater*) userdata; - self->sendMsgFromInputEditor(); - self->setTyping(false); -} - -void LLIMFloater::sendMsgFromInputEditor() -{ - if (gAgent.isGodlike() - || (mDialog != IM_NOTHING_SPECIAL) - || !mOtherParticipantUUID.isNull()) - { - if (mInputEditor) - { - LLWString text = mInputEditor->getWText(); - LLWStringUtil::trim(text); - LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. - if(!text.empty()) - { - // Truncate and convert to UTF8 for transport - std::string utf8_text = wstring_to_utf8str(text); - - sendMsg(utf8_text); - - mInputEditor->setText(LLStringUtil::null); - } - } - } - else - { - llinfos << "Cannot send IM to everyone unless you're a god." << llendl; - } -} - -void LLIMFloater::sendMsg(const std::string& msg) -{ - const std::string utf8_text = utf8str_truncate(msg, MAX_MSG_BUF_SIZE - 1); - - if (mSessionInitialized) - { - LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog); - } - else - { - //queue up the message to send once the session is initialized - mQueuedMsgsForInit.append(utf8_text); - } - - updateMessages(); -} - -LLIMFloater::~LLIMFloater() -{ - mVoiceChannelStateChangeConnection.disconnect(); - if(LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->removeObserver(this); - } - - LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); -} - - -void LLIMFloater::initIMSession(const LLUUID& session_id) -{ - // Change the floater key to bind it to a new session. - setKey(session_id); - - mSessionID = session_id; - mSession = LLIMModel::getInstance()->findIMSession(mSessionID); - - if (mSession) - { - mIsP2PChat = mSession->isP2PSessionType(); - mSessionInitialized = mSession->mSessionInitialized; - mDialog = mSession->mType; - } -} - -void LLIMFloater::initIMFloater() -{ - const LLUUID& other_party_id = - LLIMModel::getInstance()->getOtherParticipantID(mSessionID); - if (other_party_id.notNull()) - { - mOtherParticipantUUID = other_party_id; - } - - boundVoiceChannel(); - - mTypingStart = LLTrans::getString("IM_typing_start_string"); - - // Show control panel in torn off floaters only. - mParticipantListPanel->setVisible(!getHost() && gSavedSettings.getBOOL("IMShowControlPanel")); - - // Disable input editor if session cannot accept text - if ( mSession && !mSession->mTextIMPossible ) - { - mInputEditor->setEnabled(FALSE); - mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label")); - } - - if (!mIsP2PChat) - { - std::string session_name(LLIMModel::instance().getName(mSessionID)); - updateSessionName(session_name); - } -} - -//virtual -BOOL LLIMFloater::postBuild() -{ - BOOL result = LLIMConversation::postBuild(); - - mInputEditor->setMaxTextLength(1023); - // enable line history support for instant message bar - // XXX stinson TODO : resolve merge by adding autoreplace to text editors -#if 0 - // *TODO Establish LineEditor with autoreplace callback - mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); -#endif - - mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) ); - mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) ); - mInputEditor->setKeystrokeCallback( boost::bind(onInputEditorKeystroke, _1, this) ); - mInputEditor->setCommitCallback(boost::bind(onSendMsg, _1, this)); - - setDocked(true); - - LLButton* add_btn = getChild<LLButton>("add_btn"); - - // Allow to add chat participants depending on the session type - add_btn->setEnabled(isInviteAllowed()); - add_btn->setClickedCallback(boost::bind(&LLIMFloater::onAddButtonClicked, this)); - - childSetAction("voice_call_btn", boost::bind(&LLIMFloater::onCallButtonClicked, this)); - - LLVoiceClient::getInstance()->addObserver(this); - - //*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla" - //see LLFloaterIMPanel for how it is done (IB) - - initIMFloater(); - - return result; -} - -void LLIMFloater::onAddButtonClicked() -{ - LLView * button = findChild<LLView>("toolbar_panel")->findChild<LLButton>("add_btn"); - LLFloater* root_floater = gFloaterView->getParentFloater(this); - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE, FALSE, root_floater->getName(), button); - if (!picker) - { - return; - } - - // Need to disable 'ok' button when selected users are already in conversation. - picker->setOkBtnEnableCb(boost::bind(&LLIMFloater::canAddSelectedToChat, this, _1)); - - if (root_floater) - { - root_floater->addDependentFloater(picker); - } -} - -bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) -{ - if (!mSession - || mDialog == IM_SESSION_GROUP_START - || mDialog == IM_SESSION_INVITE && gAgent.isInGroup(mSessionID)) - { - return false; - } - - if (mIsP2PChat) - { - // For a P2P session just check if we are not adding the other participant. - - for (uuid_vec_t::const_iterator id = uuids.begin(); - id != uuids.end(); ++id) - { - if (*id == mOtherParticipantUUID) - { - return false; - } - } - } - else - { - // For a conference session we need to check against the list from LLSpeakerMgr, - // because this list may change when participants join or leave the session. - - LLSpeakerMgr::speaker_list_t speaker_list; - LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if (speaker_mgr) - { - speaker_mgr->getSpeakerList(&speaker_list, true); - } - - for (uuid_vec_t::const_iterator id = uuids.begin(); - id != uuids.end(); ++id) - { - for (LLSpeakerMgr::speaker_list_t::const_iterator it = speaker_list.begin(); - it != speaker_list.end(); ++it) - { - const LLPointer<LLSpeaker>& speaker = *it; - if (*id == speaker->mID) - { - return false; - } - } - } - } - - return true; -} - -void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) -{ - if (mIsP2PChat) - { - LLSD payload; - LLSD args; - - LLNotificationsUtil::add("ConfirmAddingChatParticipants", args, payload, - boost::bind(&LLIMFloater::addP2PSessionParticipants, this, _1, _2, uuids)); - } - else - { - // remember whom we have invited, to notify others later, when the invited ones actually join - mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); - - inviteToSession(uuids); - } -} - -void LLIMFloater::addP2PSessionParticipants(const LLSD& notification, const LLSD& response, const uuid_vec_t& uuids) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) - { - return; - } - - mStartConferenceInSameFloater = true; - - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - - // first check whether this is a voice session - bool is_voice_call = voice_channel != NULL && voice_channel->isActive(); - - uuid_vec_t temp_ids; - - // Add the initial participant of a P2P session - temp_ids.push_back(mOtherParticipantUUID); - temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end()); - - // then we can close the current session - onClose(false); - - // we start a new session so reset the initialization flag - mSessionInitialized = false; - - // remember whom we have invited, to notify others later, when the invited ones actually join - mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end()); - - // Start a new ad hoc voice call if we invite new participants to a P2P call, - // or start a text chat otherwise. - if (is_voice_call) - { - LLAvatarActions::startAdhocCall(temp_ids, mSessionID); - } - else - { - LLAvatarActions::startConference(temp_ids, mSessionID); - } -} - -void LLIMFloater::sendParticipantsAddedNotification(const uuid_vec_t& uuids) -{ - std::string names_string; - LLAvatarActions::buildResidentsString(uuids, names_string); - LLStringUtil::format_map_t args; - args["[NAME]"] = names_string; - - sendMsg(getString(uuids.size() > 1 ? "multiple_participants_added" : "participant_added", args)); -} - -void LLIMFloater::boundVoiceChannel() -{ - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - if(voice_channel) - { - mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback( - boost::bind(&LLIMFloater::onVoiceChannelStateChanged, this, _1, _2)); - - //call (either p2p, group or ad-hoc) can be already in started state - bool callIsActive = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED; - updateCallBtnState(callIsActive); - } -} - -void LLIMFloater::onCallButtonClicked() -{ - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - if (voice_channel) - { - bool is_call_active = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED; - if (is_call_active) - { - gIMMgr->endCall(mSessionID); - } - else - { - gIMMgr->startCall(mSessionID); - } - } -} - -void LLIMFloater::onChange(EStatusType status, const std::string &channelURI, bool proximal) -{ - if(status != STATUS_JOINING && status != STATUS_LEFT_CHANNEL) - { - enableDisableCallBtn(); - } -} - -void LLIMFloater::onVoiceChannelStateChanged( - const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) -{ - bool callIsActive = new_state >= LLVoiceChannel::STATE_CALL_STARTED; - updateCallBtnState(callIsActive); -} - -void LLIMFloater::updateSessionName(const std::string& name) -{ - LLIMConversation::updateSessionName(name); - setTitle(name); - mTypingStart.setArg("[NAME]", name); -} - -//static -LLIMFloater* LLIMFloater::show(const LLUUID& session_id) -{ - closeHiddenIMToasts(); - - if (!gIMMgr->hasSession(session_id)) - return NULL; - - // Test the existence of the floater before we try to create it - bool exist = findInstance(session_id); - - // Get the floater: this will create the instance if it didn't exist - LLIMFloater* floater = getInstance(session_id); - if (!floater) - return NULL; - - LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); - - // Do not add again existing floaters - if (!exist) - { - // LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; - // TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists - LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END; - if (floater_container) - { - floater_container->addFloater(floater, TRUE, i_pt); - } - } - - floater->openFloater(floater->getKey()); - - floater->setVisible(TRUE); - - return floater; -} -//static -LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id) -{ - LLIMFloater* conversation = - LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); - - return conversation; -} - -LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) -{ - LLIMFloater* conversation = - LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id); - - return conversation; -} - -void LLIMFloater::onClose(bool app_quitting) -{ - setTyping(false); - - // The source of much argument and design thrashing - // Should the window hide or the session close when the X is clicked? - // - // Last change: - // EXT-3516 X Button should end IM session, _ button should hide - gIMMgr->leaveSession(mSessionID); - - // Clean up the conversation *after* the session has been ended - LLIMConversation::onClose(app_quitting); -} - -void LLIMFloater::setDocked(bool docked, bool pop_on_undock) -{ - // update notification channel state - LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> - (LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); - - if(!isChatMultiTab()) - { - LLTransientDockableFloater::setDocked(docked, pop_on_undock); - } - - // update notification channel state - if(channel) - { - channel->updateShowToastsState(); - channel->redrawToasts(); - } -} - -void LLIMFloater::setVisible(BOOL visible) -{ - LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> - (LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); - - LLIMConversation::setVisible(visible); - - // update notification channel state - if(channel) - { - channel->updateShowToastsState(); - channel->redrawToasts(); - } - - if(!visible) - { - LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(mSessionID); - if(chiclet) - { - chiclet->setToggleState(false); - } - } - - if (visible && isInVisibleChain()) - { - sIMFloaterShowedSignal(mSessionID); - - } - - setFocus(visible); -} - -BOOL LLIMFloater::getVisible() -{ - bool visible; - - if(isChatMultiTab()) - { - LLIMFloaterContainer* im_container = - LLIMFloaterContainer::getInstance(); - - // Treat inactive floater as invisible. - bool is_active = im_container->getActiveFloater() == this; - - //torn off floater is always inactive - if (!is_active && getHost() != im_container) - { - visible = LLTransientDockableFloater::getVisible(); - } - else - { - // getVisible() returns TRUE when Tabbed IM window is minimized. - visible = is_active && !im_container->isMinimized() - && im_container->getVisible(); - } - } - else - { - visible = LLTransientDockableFloater::getVisible(); - } - - return visible; -} - -//static -bool LLIMFloater::toggle(const LLUUID& session_id) -{ - if(!isChatMultiTab()) - { - LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>( - "impanel", session_id); - if (floater && floater->getVisible() && floater->hasFocus()) - { - // clicking on chiclet to close floater just hides it to maintain existing - // scroll/text entry state - floater->setVisible(false); - return false; - } - else if(floater && (!floater->isDocked() || floater->getVisible() && !floater->hasFocus())) - { - floater->setVisible(TRUE); - floater->setFocus(TRUE); - return true; - } - } - - // ensure the list of messages is updated when floater is made visible - show(session_id); - return true; -} - -void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) -{ - mSessionInitialized = true; - - //will be different only for an ad-hoc im session - if (mSessionID != im_session_id) - { - initIMSession(im_session_id); - buildConversationViewParticipant(); - } - - initIMFloater(); - - //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) - - //need to send delayed messages collected while waiting for session initialization - if (mQueuedMsgsForInit.size()) - { - LLSD::array_iterator iter; - for ( iter = mQueuedMsgsForInit.beginArray(); - iter != mQueuedMsgsForInit.endArray(); ++iter) - { - LLIMModel::sendMessage(iter->asString(), mSessionID, - mOtherParticipantUUID, mDialog); - } - - mQueuedMsgsForInit.clear(); - } -} - -void LLIMFloater::updateMessages() -{ - std::list<LLSD> messages; - - // we shouldn't reset unread message counters if IM floater doesn't have focus - LLIMModel::instance().getMessages( - mSessionID, messages, mLastMessageIndex + 1, hasFocus()); - - if (messages.size()) - { - std::ostringstream message; - std::list<LLSD>::const_reverse_iterator iter = messages.rbegin(); - std::list<LLSD>::const_reverse_iterator iter_end = messages.rend(); - for (; iter != iter_end; ++iter) - { - LLSD msg = *iter; - - std::string time = msg["time"].asString(); - LLUUID from_id = msg["from_id"].asUUID(); - std::string from = msg["from"].asString(); - std::string message = msg["message"].asString(); - bool is_history = msg["is_history"].asBoolean(); - - LLChat chat; - chat.mFromID = from_id; - chat.mSessionID = mSessionID; - chat.mFromName = from; - chat.mTimeStr = time; - chat.mChatStyle = is_history ? CHAT_STYLE_HISTORY : chat.mChatStyle; - - // process offer notification - if (msg.has("notification_id")) - { - chat.mNotifId = msg["notification_id"].asUUID(); - // if notification exists - embed it - if (LLNotificationsUtil::find(chat.mNotifId) != NULL) - { - // remove embedded notification from channel - LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> - (LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); - if (getVisible()) - { - // toast will be automatically closed since it is not storable toast - channel->hideToast(chat.mNotifId); - } - } - // if notification doesn't exist - try to use next message which should be log entry - else - { - continue; - } - } - //process text message - else - { - chat.mText = message; - } - - // Add the message to the chat log - appendMessage(chat); - mLastMessageIndex = msg["index"].asInteger(); - - // if it is a notification - next message is a notification history log, so skip it - if (chat.mNotifId.notNull() && LLNotificationsUtil::find(chat.mNotifId) != NULL) - { - if (++iter == iter_end) - { - break; - } - else - { - mLastMessageIndex++; - } - } - } - } -} - -void LLIMFloater::reloadMessages() -{ - mChatHistory->clear(); - mLastMessageIndex = -1; - updateMessages(); - mInputEditor->setFont(LLViewerChat::getChatFont()); -} - -// static -void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ) -{ - LLIMFloater* self= (LLIMFloater*) userdata; - - // Allow enabling the LLIMFloater input editor only if session can accept text - LLIMModel::LLIMSession* im_session = - LLIMModel::instance().findIMSession(self->mSessionID); - //TODO: While disabled lllineeditor can receive focus we need to check if it is enabled (EK) - if( im_session && im_session->mTextIMPossible && self->mInputEditor->getEnabled()) - { - //in disconnected state IM input editor should be disabled - self->mInputEditor->setEnabled(!gDisconnected); - } -} - -// static -void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata) -{ - LLIMFloater* self = (LLIMFloater*) userdata; - self->setTyping(false); -} - -// static -void LLIMFloater::onInputEditorKeystroke(LLTextEditor* caller, void* userdata) -{ - LLIMFloater* self = (LLIMFloater*)userdata; - std::string text = self->mInputEditor->getText(); - - // Deleting all text counts as stopping typing. - self->setTyping(!text.empty()); -} - -void LLIMFloater::setTyping(bool typing) -{ - if ( typing ) - { - // Started or proceeded typing, reset the typing timeout timer - mTypingTimeoutTimer.reset(); - } - - if ( mMeTyping != typing ) - { - // Typing state is changed - mMeTyping = typing; - // So, should send current state - mShouldSendTypingState = true; - // In case typing is started, send state after some delay - mTypingTimer.reset(); - } - - // Don't want to send typing indicators to multiple people, potentially too - // much network traffic. Only send in person-to-person IMs. - if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL ) - { - // Still typing, send 'start typing' notification or - // send 'stop typing' notification immediately - if (!mMeTyping || mTypingTimer.getElapsedTimeF32() > 1.f) - { - LLIMModel::instance().sendTypingState(mSessionID, - mOtherParticipantUUID, mMeTyping); - mShouldSendTypingState = false; - } - } - - if (!mIsNearbyChat) - { - LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if (speaker_mgr) - { - speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); - } - } -} - -void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) -{ - if ( typing ) - { - // other user started typing - addTypingIndicator(im_info); - } - else - { - // other user stopped typing - removeTypingIndicator(im_info); - } -} - -void LLIMFloater::processAgentListUpdates(const LLSD& body) -{ - uuid_vec_t joined_uuids; - - if (body.isMap() && body.has("agent_updates") && body["agent_updates"].isMap()) - { - LLSD::map_const_iterator update_it; - for(update_it = body["agent_updates"].beginMap(); - update_it != body["agent_updates"].endMap(); - ++update_it) - { - LLUUID agent_id(update_it->first); - LLSD agent_data = update_it->second; - - if (agent_data.isMap()) - { - // store the new participants in joined_uuids - if (agent_data.has("transition") && agent_data["transition"].asString() == "ENTER") - { - joined_uuids.push_back(agent_id); - } - - // process the moderator mutes - if (agent_id == gAgentID && agent_data.has("info") && agent_data["info"].has("mutes")) - { - BOOL moderator_muted_text = agent_data["info"]["mutes"]["text"].asBoolean(); - mInputEditor->setEnabled(!moderator_muted_text); - std::string label; - if (moderator_muted_text) - label = LLTrans::getString("IM_muted_text_label"); - else - label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID); - mInputEditor->setLabel(label); - - if (moderator_muted_text) - LLNotificationsUtil::add("TextChatIsMutedByModerator"); - } - } - } - } - - // the vectors need to be sorted for computing the intersection and difference - std::sort(mInvitedParticipants.begin(), mInvitedParticipants.end()); - std::sort(joined_uuids.begin(), joined_uuids.end()); - - uuid_vec_t intersection; // uuids of invited residents who have joined the conversation - std::set_intersection(mInvitedParticipants.begin(), mInvitedParticipants.end(), - joined_uuids.begin(), joined_uuids.end(), - std::back_inserter(intersection)); - - if (intersection.size() > 0) - { - sendParticipantsAddedNotification(intersection); - } - - // Remove all joined participants from invited array. - // The difference between the two vectors (the elements in mInvitedParticipants which are not in joined_uuids) - // is placed at the beginning of mInvitedParticipants, then all other elements are erased. - mInvitedParticipants.erase(std::set_difference(mInvitedParticipants.begin(), mInvitedParticipants.end(), - joined_uuids.begin(), joined_uuids.end(), - mInvitedParticipants.begin()), - mInvitedParticipants.end()); -} - -void LLIMFloater::processSessionUpdate(const LLSD& session_update) -{ - // *TODO : verify following code when moderated mode will be implemented - if ( false && session_update.has("moderated_mode") && - session_update["moderated_mode"].has("voice") ) - { - BOOL voice_moderated = session_update["moderated_mode"]["voice"]; - const std::string session_label = LLIMModel::instance().getName(mSessionID); - - if (voice_moderated) - { - setTitle(session_label + std::string(" ") - + LLTrans::getString("IM_moderated_chat_label")); - } - else - { - setTitle(session_label); - } - - // *TODO : uncomment this when/if LLPanelActiveSpeakers panel will be added - //update the speakers dropdown too - //mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated); - } -} - -// virtual -BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - if (cargo_type == DAD_PERSON) - { - if (dropPerson(static_cast<LLUUID*>(cargo_data), drop)) - { - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - } - else if (mDialog == IM_NOTHING_SPECIAL) - { - LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, - cargo_type, cargo_data, accept); - } - - return TRUE; -} - -bool LLIMFloater::dropPerson(LLUUID* person_id, bool drop) -{ - bool res = person_id && person_id->notNull(); - if(res) - { - uuid_vec_t ids; - ids.push_back(*person_id); - - res = canAddSelectedToChat(ids); - if(res && drop) - { - addSessionParticipants(ids); - } - } - - return res; -} - -BOOL LLIMFloater::isInviteAllowed() const -{ - return ( (IM_SESSION_CONFERENCE_START == mDialog) - || (IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) - || mIsP2PChat); -} - -class LLSessionInviteResponder : public LLHTTPClient::Responder -{ -public: - LLSessionInviteResponder(const LLUUID& session_id) - { - mSessionID = session_id; - } - - void error(U32 statusNum, const std::string& reason) - { - llinfos << "Error inviting all agents to session" << llendl; - //throw something back to the viewer here? - } - -private: - LLUUID mSessionID; -}; - -BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) -{ - LLViewerRegion* region = gAgent.getRegion(); - bool is_region_exist = region != NULL; - - if (is_region_exist) - { - S32 count = ids.size(); - - if( isInviteAllowed() && (count > 0) ) - { - llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl; - - std::string url = region->getCapability("ChatSessionRequest"); - - LLSD data; - data["params"] = LLSD::emptyArray(); - for (int i = 0; i < count; i++) - { - data["params"].append(ids[i]); - } - data["method"] = "invite"; - data["session-id"] = mSessionID; - LLHTTPClient::post(url, data,new LLSessionInviteResponder(mSessionID)); - } - else - { - llinfos << "LLIMFloater::inviteToSession -" - << " no need to invite agents for " - << mDialog << llendl; - // successful add, because everyone that needed to get added - // was added. - } - } - - return is_region_exist; -} - -void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info) -{ - // We may have lost a "stop-typing" packet, don't add it twice - if ( im_info && !mOtherTyping ) - { - mOtherTyping = true; - - // Save and set new title - mSavedTitle = getTitle(); - setTitle (mTypingStart); - - // Update speaker - LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if ( speaker_mgr ) - { - speaker_mgr->setSpeakerTyping(im_info->mFromID, TRUE); - } - } -} - -void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info) -{ - if ( mOtherTyping ) - { - mOtherTyping = false; - - // Revert the title to saved one - setTitle(mSavedTitle); - - if ( im_info ) - { - // Update speaker - LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if ( speaker_mgr ) - { - speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE); - } - } - } -} - -// static -void LLIMFloater::closeHiddenIMToasts() -{ - class IMToastMatcher: public LLNotificationsUI::LLScreenChannel::Matcher - { - public: - bool matches(const LLNotificationPtr notification) const - { - // "notifytoast" type of notifications is reserved for IM notifications - return "notifytoast" == notification->getType(); - } - }; - - LLNotificationsUI::LLScreenChannel* channel = - LLNotificationsUI::LLChannelManager::getNotificationScreenChannel(); - if (channel != NULL) - { - channel->closeHiddenToasts(IMToastMatcher()); - } -} -// static -void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - const LLSD& payload = notification["payload"]; - LLUUID session_id = payload["session_id"]; - - LLFloater* im_floater = findInstance(session_id); - if (option == 0 && im_floater != NULL) - { - im_floater->closeFloater(); - } - - return; -} - -// static -void LLIMFloater::sRemoveTypingIndicator(const LLSD& data) -{ - LLUUID session_id = data["session_id"]; - if (session_id.isNull()) - return; - - LLUUID from_id = data["from_id"]; - if (gAgentID == from_id || LLUUID::null == from_id) - return; - - LLIMFloater* floater = LLIMFloater::findInstance(session_id); - if (!floater) - return; - - if (IM_NOTHING_SPECIAL != floater->mDialog) - return; - - floater->removeTypingIndicator(); -} - -// static -void LLIMFloater::onIMChicletCreated( const LLUUID& session_id ) -{ - LLIMFloater::addToHost(session_id); -} - -boost::signals2::connection LLIMFloater::setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb) -{ - return LLIMFloater::sIMFloaterShowedSignal.connect(cb); -} diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h deleted file mode 100644 index 6ba31657dc..0000000000 --- a/indra/newview/llimfloater.h +++ /dev/null @@ -1,196 +0,0 @@ -/** - * @file llimfloater.h - * @brief LLIMFloater class definition - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_IMFLOATER_H -#define LL_IMFLOATER_H - -#include "llimview.h" -#include "llimconversation.h" -#include "llinstantmessage.h" -#include "lllogchat.h" -#include "lltooldraganddrop.h" -#include "llvoicechannel.h" -#include "llvoiceclient.h" - -class LLAvatarName; -class LLButton; -class LLChatEntry; -class LLTextEditor; -class LLPanelChatControlPanel; -class LLChatHistory; -class LLInventoryItem; -class LLInventoryCategory; - -typedef boost::signals2::signal<void(const LLUUID& session_id)> floater_showed_signal_t; - -/** - * Individual IM window that appears at the bottom of the screen, - * optionally "docked" to the bottom tray. - */ -class LLIMFloater - : public LLVoiceClientStatusObserver - , public LLIMConversation -{ - LOG_CLASS(LLIMFloater); -public: - LLIMFloater(const LLUUID& session_id); - - virtual ~LLIMFloater(); - - void initIMSession(const LLUUID& session_id); - void initIMFloater(); - - // LLView overrides - /*virtual*/ BOOL postBuild(); - /*virtual*/ void setVisible(BOOL visible); - /*virtual*/ BOOL getVisible(); - // Check typing timeout timer. - - static LLIMFloater* findInstance(const LLUUID& session_id); - static LLIMFloater* getInstance(const LLUUID& session_id); - - // LLFloater overrides - /*virtual*/ void onClose(bool app_quitting); - /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); - // Make IM conversion visible and update the message history - static LLIMFloater* show(const LLUUID& session_id); - - // Toggle panel specified by session_id - // Returns true iff panel became visible - static bool toggle(const LLUUID& session_id); - - void sessionInitReplyReceived(const LLUUID& im_session_id); - - // get new messages from LLIMModel - /*virtual*/ void updateMessages(); - void reloadMessages(); - static void onSendMsg(LLUICtrl*, void*); - void sendMsgFromInputEditor(); - void sendMsg(const std::string& msg); - - // callback for LLIMModel on new messages - // route to specific floater if it is visible - static void newIMCallback(const LLSD& data); - - // called when docked floater's position has been set by chiclet - void setPositioned(bool b) { mPositioned = b; }; - - void onVisibilityChange(const LLSD& new_visibility); - - // Implements LLVoiceClientStatusObserver::onChange() to enable the call - // button when voice is available - void onChange(EStatusType status, const std::string &channelURI, - bool proximal); - - virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } - virtual void onVoiceChannelStateChanged( - const LLVoiceChannel::EState& old_state, - const LLVoiceChannel::EState& new_state); - - void processIMTyping(const LLIMInfo* im_info, BOOL typing); - void processAgentListUpdates(const LLSD& body); - void processSessionUpdate(const LLSD& session_update); - - /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - - - //used as a callback on receiving new IM message - static void sRemoveTypingIndicator(const LLSD& data); - static void onIMChicletCreated(const LLUUID& session_id); - - bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; } - const LLUUID& getOtherParticipantUUID() {return mOtherParticipantUUID;} - - static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); - static floater_showed_signal_t sIMFloaterShowedSignal; - -private: - - /*virtual*/ void refresh(); - - /*virtual*/ void onClickCloseBtn(); - - // Update the window title and input field help text - /*virtual*/ void updateSessionName(const std::string& name); - - bool dropPerson(LLUUID* person_id, bool drop); - - BOOL isInviteAllowed() const; - BOOL inviteToSession(const uuid_vec_t& agent_ids); - static void onInputEditorFocusReceived( LLFocusableElement* caller,void* userdata ); - static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); - static void onInputEditorKeystroke(LLTextEditor* caller, void* userdata); - void setTyping(bool typing); - void onAddButtonClicked(); - void addSessionParticipants(const uuid_vec_t& uuids); - void addP2PSessionParticipants(const LLSD& notification, const LLSD& response, const uuid_vec_t& uuids); - void sendParticipantsAddedNotification(const uuid_vec_t& uuids); - bool canAddSelectedToChat(const uuid_vec_t& uuids); - - void onCallButtonClicked(); - - void boundVoiceChannel(); - - // Add the "User is typing..." indicator. - void addTypingIndicator(const LLIMInfo* im_info); - - // Remove the "User is typing..." indicator. - void removeTypingIndicator(const LLIMInfo* im_info = NULL); - - static void closeHiddenIMToasts(); - - static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); - - S32 mLastMessageIndex; - - EInstantMessage mDialog; - LLUUID mOtherParticipantUUID; - bool mPositioned; - - std::string mSavedTitle; - LLUIString mTypingStart; - bool mMeTyping; - bool mOtherTyping; - bool mShouldSendTypingState; - LLFrameTimer mTypingTimer; - LLFrameTimer mTypingTimeoutTimer; - - bool mSessionInitialized; - LLSD mQueuedMsgsForInit; - - bool mStartConferenceInSameFloater; - - uuid_vec_t mInvitedParticipants; - - // connection to voice channel state change signal - boost::signals2::connection mVoiceChannelStateChangeConnection; -}; - -#endif // LL_IMFLOATER_H diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp deleted file mode 100644 index 9c1f5d7593..0000000000 --- a/indra/newview/llimfloatercontainer.cpp +++ /dev/null @@ -1,1557 +0,0 @@ -/** - * @file llimfloatercontainer.cpp - * @brief Multifloater containing active IM sessions in separate tab container tabs - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - - -#include "llviewerprecompiledheaders.h" - -#include "llimfloater.h" -#include "llimfloatercontainer.h" - -#include "llfloaterreg.h" -#include "lllayoutstack.h" -#include "llnearbychat.h" - -#include "llagent.h" -#include "llavataractions.h" -#include "llavatariconctrl.h" -#include "llavatarnamecache.h" -#include "llcallbacklist.h" -#include "llgroupactions.h" -#include "llgroupiconctrl.h" -#include "llfloateravatarpicker.h" -#include "llfloaterpreference.h" -#include "llimview.h" -#include "llnotificationsutil.h" -#include "lltransientfloatermgr.h" -#include "llviewercontrol.h" -#include "llconversationview.h" -#include "llcallbacklist.h" -#include "llworld.h" - -#include "llsdserialize.h" -// -// LLIMFloaterContainer -// -LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) -: LLMultiFloater(seed), - mExpandCollapseBtn(NULL), - mConversationsRoot(NULL), - mConversationsEventStream("ConversationsEvents"), - mInitialized(false) -{ - mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLIMFloaterContainer::isActionChecked, this, _2)); - mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLIMFloaterContainer::onCustomAction, this, _2)); - - mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLIMFloaterContainer::checkContextMenuItem, this, _2)); - mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLIMFloaterContainer::enableContextMenuItem, this, _2)); - mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLIMFloaterContainer::doToSelected, this, _2)); - - mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&LLIMFloaterContainer::doToSelectedGroup, this, _2)); - - // Firstly add our self to IMSession observers, so we catch session events - LLIMMgr::getInstance()->addSessionObserver(this); - - mAutoResize = FALSE; - LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); -} - -LLIMFloaterContainer::~LLIMFloaterContainer() -{ - mConversationsEventStream.stopListening("ConversationsRefresh"); - - gIdleCallbacks.deleteFunction(idle, this); - - mNewMessageConnection.disconnect(); - LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); - - gSavedPerAccountSettings.setBOOL("ConversationsListPaneCollapsed", mConversationsPane->isCollapsed()); - gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed()); - - if (!LLSingleton<LLIMMgr>::destroyed()) - { - LLIMMgr::getInstance()->removeSessionObserver(this); - } -} - -void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) -{ - addConversationListItem(session_id); - LLIMConversation::addToHost(session_id); -} - -void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) -{ - selectConversation(session_id); -} - -void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) -{ - addConversationListItem(session_id); - LLIMConversation::addToHost(session_id); -} - -void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) -{ - // *TODO: We should do this *without* delete and recreate - addConversationListItem(new_session_id, removeConversationListItem(old_session_id)); -} - -void LLIMFloaterContainer::sessionRemoved(const LLUUID& session_id) -{ - removeConversationListItem(session_id); -} - -// static -void LLIMFloaterContainer::onCurrentChannelChanged(const LLUUID& session_id) -{ - if (session_id != LLUUID::null) - { - LLIMFloaterContainer::getInstance()->showConversation(session_id); - } -} - - -BOOL LLIMFloaterContainer::postBuild() -{ - mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLIMFloaterContainer::onNewMessageReceived, this, _1)); - // Do not call base postBuild to not connect to mCloseSignal to not close all floaters via Close button - // mTabContainer will be initialized in LLMultiFloater::addChild() - - setTabContainer(getChild<LLTabContainer>("im_box_tab_container")); - - mConversationsStack = getChild<LLLayoutStack>("conversations_stack"); - mConversationsPane = getChild<LLLayoutPanel>("conversations_layout_panel"); - mMessagesPane = getChild<LLLayoutPanel>("messages_layout_panel"); - - mConversationsListPanel = getChild<LLPanel>("conversations_list_panel"); - - // Open IM session with selected participant on double click event - mConversationsListPanel->setDoubleClickCallback(boost::bind(&LLIMFloaterContainer::doToSelected, this, LLSD("im"))); - - // Create the root model and view for all conversation sessions - LLConversationItem* base_item = new LLConversationItem(getRootViewModel()); - - LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); - p.name = getName(); - p.title = getLabel(); - p.rect = LLRect(0, 0, getRect().getWidth(), 0); - p.parent_panel = mConversationsListPanel; - p.tool_tip = p.name; - p.listener = base_item; - p.view_model = &mConversationViewModel; - p.root = NULL; - p.use_ellipses = true; - p.options_menu = "menu_conversation.xml"; - mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); - mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); - - // Add listener to conversation model events - mConversationsEventStream.listen("ConversationsRefresh", boost::bind(&LLIMFloaterContainer::onConversationModelEvent, this, _1)); - - // a scroller for folder view - LLRect scroller_view_rect = mConversationsListPanel->getRect(); - scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); - LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>()); - scroller_params.rect(scroller_view_rect); - - LLScrollContainer* scroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); - scroller->setFollowsAll(); - mConversationsListPanel->addChild(scroller); - scroller->addChild(mConversationsRoot); - mConversationsRoot->setScrollContainer(scroller); - mConversationsRoot->setFollowsAll(); - mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); - - addConversationListItem(LLUUID()); // manually add nearby chat - - mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); - mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this)); - - childSetAction("add_btn", boost::bind(&LLIMFloaterContainer::onAddButtonClicked, this)); - - collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); - collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); - LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); - - if (! mMessagesPane->isCollapsed()) - { - S32 list_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"); - LLRect list_size = mConversationsPane->getRect(); - S32 left_pad = mConversationsListPanel->getRect().mLeft; - list_size.mRight = list_size.mLeft + list_width - left_pad; - - mConversationsPane->handleReshape(list_size, TRUE); - } - - // Init the sort order now that the root had been created - setSortOrder(LLConversationSort(gSavedSettings.getU32("ConversationSortOrder"))); - - mInitialized = true; - - // Add callbacks: - // We'll take care of view updates on idle - gIdleCallbacks.addFunction(idle, this); - // When display name option change, we need to reload all participant names - LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLIMFloaterContainer::processParticipantsStyleUpdate, this)); - - return TRUE; -} - -void LLIMFloaterContainer::onOpen(const LLSD& key) -{ - LLMultiFloater::onOpen(key); - openNearbyChat(); -} - -// virtual -void LLIMFloaterContainer::addFloater(LLFloater* floaterp, - BOOL select_added_floater, - LLTabContainer::eInsertionPoint insertion_point) -{ - if(!floaterp) return; - - // already here - if (floaterp->getHost() == this) - { - openFloater(floaterp->getKey()); - return; - } - - // Make sure the message panel is open when adding a floater or it stays mysteriously hidden - collapseMessagesPane(false); - - // Add the floater - LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); - - LLUUID session_id = floaterp->getKey(); - - LLIconCtrl* icon = 0; - - if(gAgent.isInGroup(session_id, TRUE)) - { - LLGroupIconCtrl::Params icon_params; - icon_params.group_id = session_id; - icon = LLUICtrlFactory::instance().create<LLGroupIconCtrl>(icon_params); - - mSessions[session_id] = floaterp; - floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, session_id)); - } - else - { LLUUID avatar_id = session_id.notNull()? - LLIMModel::getInstance()->getOtherParticipantID(session_id) : LLUUID(); - - LLAvatarIconCtrl::Params icon_params; - icon_params.avatar_id = avatar_id; - icon = LLUICtrlFactory::instance().create<LLAvatarIconCtrl>(icon_params); - - mSessions[session_id] = floaterp; - floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, session_id)); - } - - // forced resize of the floater - LLRect wrapper_rect = this->mTabContainer->getLocalRect(); - floaterp->setRect(wrapper_rect); - - mTabContainer->setTabImage(floaterp, icon); -} - - -void LLIMFloaterContainer::onCloseFloater(LLUUID& id) -{ - mSessions.erase(id); - setFocus(TRUE); -} - -// virtual -void LLIMFloaterContainer::computeResizeLimits(S32& new_min_width, S32& new_min_height) -{ - // possibly increase floater's minimum height according to children's minimums - for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) - { - LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getPanelByIndex(tab_idx)); - if (floaterp) - { - new_min_height = llmax(new_min_height, floaterp->getMinHeight()); - } - } - - S32 conversations_pane_min_dim = mConversationsPane->getRelevantMinDim(); - S32 messages_pane_min_dim = mMessagesPane->getRelevantMinDim(); - - // set floater's minimum width according to relevant minimal children's dimensionals - new_min_width = conversations_pane_min_dim + messages_pane_min_dim + LLPANEL_BORDER_WIDTH*2; -} - -void LLIMFloaterContainer::onNewMessageReceived(const LLSD& data) -{ - LLUUID session_id = data["session_id"].asUUID(); - LLFloater* floaterp = get_ptr_in_map(mSessions, session_id); - LLFloater* current_floater = LLMultiFloater::getActiveFloater(); - - if(floaterp && current_floater && floaterp != current_floater) - { - if(LLMultiFloater::isFloaterFlashing(floaterp)) - LLMultiFloater::setFloaterFlashing(floaterp, FALSE); - LLMultiFloater::setFloaterFlashing(floaterp, TRUE); - } -} - -void LLIMFloaterContainer::onExpandCollapseButtonClicked() -{ - if (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed() - && gSavedPerAccountSettings.getBOOL("ConversationsExpandMessagePaneFirst")) - { - // Expand the messages pane from ultra minimized state - // if it was collapsed last in order. - collapseMessagesPane(false); - } - else - { - collapseConversationsPane(!mConversationsPane->isCollapsed()); - } - selectConversation(mSelectedSession); -} - -LLIMFloaterContainer* LLIMFloaterContainer::findInstance() -{ - return LLFloaterReg::findTypedInstance<LLIMFloaterContainer>("im_container"); -} - -LLIMFloaterContainer* LLIMFloaterContainer::getInstance() -{ - return LLFloaterReg::getTypedInstance<LLIMFloaterContainer>("im_container"); -} - -// Update all participants in the conversation lists -void LLIMFloaterContainer::processParticipantsStyleUpdate() -{ - // On each session in mConversationsItems - for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) - { - // Get the current session descriptors - LLConversationItem* session_model = it_session->second; - // Iterate through each model participant child - LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = session_model->getChildrenBegin(); - LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = session_model->getChildrenEnd(); - while (current_participant_model != end_participant_model) - { - LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); - // Get the avatar name for this participant id from the cache and update the model - participant_model->fetchAvatarName(); - // Next participant - current_participant_model++; - } - } -} - -// static -void LLIMFloaterContainer::idle(void* user_data) -{ - LLIMFloaterContainer* self = static_cast<LLIMFloaterContainer*>(user_data); - - // Update the distance to agent in the nearby chat session if required - // Note: it makes no sense of course to update the distance in other session - if (self->mConversationViewModel.getSorter().getSortOrderParticipants() == LLConversationFilter::SO_DISTANCE) - { - self->setNearbyDistances(); - } - self->mConversationsRoot->update(); -} - -bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) -{ - // For debug only - //std::ostringstream llsd_value; - //llsd_value << LLSDOStreamer<LLSDNotationFormatter>(event) << std::endl; - //llinfos << "LLIMFloaterContainer::onConversationModelEvent, event = " << llsd_value.str() << llendl; - // end debug - - // Note: In conversations, the model is not responsible for creating the view, which is a good thing. This means that - // the model could change substantially and the view could echo only a portion of this model (though currently the - // conversation view does echo the conversation model 1 to 1). - // Consequently, the participant views need to be created either by the session view or by the container panel. - // For the moment, we create them here, at the container level, to conform to the pattern implemented in llinventorypanel.cpp - // (see LLInventoryPanel::buildNewViews()). - - std::string type = event.get("type").asString(); - LLUUID session_id = event.get("session_uuid").asUUID(); - LLUUID participant_id = event.get("participant_uuid").asUUID(); - - LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,session_id)); - if (!session_view) - { - // We skip events that are not associated with a session - return false; - } - LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); - LLIMConversation *conversation_floater = (session_id.isNull() ? (LLIMConversation*)(LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")) : (LLIMConversation*)(LLIMFloater::findInstance(session_id))); - - if (type == "remove_participant") - { - // Remove a participant view from the hierarchical conversation list - if (participant_view) - { - session_view->extractItem(participant_view); - delete participant_view; - session_view->refresh(); - mConversationsRoot->arrangeAll(); - } - // Remove a participant view from the conversation floater - if (conversation_floater) - { - conversation_floater->removeConversationViewParticipant(participant_id); - } - } - else if (type == "add_participant") - { - LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]); - LLConversationItemParticipant* participant_model = (session_model ? session_model->findParticipant(participant_id) : NULL); - if (!participant_view && session_model && participant_model) - { - LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(session_id); - if (session_id.isNull() || (im_sessionp && !im_sessionp->isP2PSessionType())) - { - participant_view = createConversationViewParticipant(participant_model); - participant_view->addToFolder(session_view); - participant_view->setVisible(TRUE); - } - } - // Add a participant view to the conversation floater - if (conversation_floater && participant_model) - { - conversation_floater->addConversationViewParticipant(participant_model); - } - } - else if (type == "update_participant") - { - // Update the participant view in the hierarchical conversation list - if (participant_view) - { - participant_view->refresh(); - } - // Update the participant view in the conversation floater - if (conversation_floater) - { - conversation_floater->updateConversationViewParticipant(participant_id); - } - } - else if (type == "update_session") - { - session_view->refresh(); - if (conversation_floater) - { - conversation_floater->refreshConversation(); - } - } - - mConversationViewModel.requestSortAll(); - mConversationsRoot->arrangeAll(); - - return false; -} - -void LLIMFloaterContainer::draw() -{ - if (mTabContainer->getTabCount() == 0) - { - // Do not close the container when every conversation is torn off because the user - // still needs the conversation list. Simply collapse the message pane in that case. - collapseMessagesPane(true); - } - LLFloater::draw(); -} - -void LLIMFloaterContainer::tabClose() -{ - if (mTabContainer->getTabCount() == 0) - { - // Do not close the container when every conversation is torn off because the user - // still needs the conversation list. Simply collapse the message pane in that case. - collapseMessagesPane(true); - } -} - -void LLIMFloaterContainer::setVisible(BOOL visible) -{ LLNearbyChat* nearby_chat; - if (visible) - { - // Make sure we have the Nearby Chat present when showing the conversation container - nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); - if (nearby_chat == NULL) - { - // If not found, force the creation of the nearby chat conversation panel - // *TODO: find a way to move this to XML as a default panel or something like that - LLSD name("nearby_chat"); - LLFloaterReg::toggleInstanceOrBringToFront(name); - } - openNearbyChat(); - } - - nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); - if (nearby_chat) - { - LLIMConversation::addToHost(LLUUID()); - } - - // We need to show/hide all the associated conversations that have been torn off - // (and therefore, are not longer managed by the multifloater), - // so that they show/hide with the conversations manager. - conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); - for (;widget_it != mConversationsWidgets.end(); ++widget_it) - { - LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); - if (widget) - { - widget->setVisibleIfDetached(visible); - } - } - - // Now, do the normal multifloater show/hide - LLMultiFloater::setVisible(visible); - -} - -void LLIMFloaterContainer::collapseMessagesPane(bool collapse) -{ - if (mMessagesPane->isCollapsed() == collapse) - { - return; - } - - if (collapse) - { - // Save the messages pane width before collapsing it. - gSavedPerAccountSettings.setS32("ConversationsMessagePaneWidth", mMessagesPane->getRect().getWidth()); - - // Save the order in which the panels are closed to reverse user's last action. - gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", mConversationsPane->isCollapsed()); - } - - // Save left pane rectangle before collapsing/expanding right pane. - LLRect prevRect = mConversationsPane->getRect(); - - // Show/hide the messages pane. - mConversationsStack->collapsePanel(mMessagesPane, collapse); - - if (!collapse) - { - // Make sure layout is updated before resizing conversation pane. - mConversationsStack->updateLayout(); - } - - updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); - if (!collapse) - { - // Restore conversation's pane previous width after expanding messages pane. - mConversationsPane->setTargetDim(prevRect.getWidth()); - } -} -void LLIMFloaterContainer::collapseConversationsPane(bool collapse) -{ - if (mConversationsPane->isCollapsed() == collapse) - { - return; - } - - LLView* button_panel = getChild<LLView>("conversations_pane_buttons_expanded"); - button_panel->setVisible(!collapse); - mExpandCollapseBtn->setImageOverlay(getString(collapse ? "expand_icon" : "collapse_icon")); - - if (collapse) - { - // Save the conversations pane width before collapsing it. - gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", mConversationsPane->getRect().getWidth()); - - // Save the order in which the panels are closed to reverse user's last action. - gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", !mMessagesPane->isCollapsed()); - } - - mConversationsStack->collapsePanel(mConversationsPane, collapse); - - S32 collapsed_width = mConversationsPane->getMinDim(); - updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - collapsed_width); - - for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); - widget_it != mConversationsWidgets.end(); ++widget_it) - { - LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); - if (widget) - { - widget->toggleMinimizedMode(collapse); - - // force closing all open conversations when collapsing to minimized state - if (collapse) - { - widget->setOpen(false); - } -} - } -} - -void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) -{ - LLRect floater_rect = getRect(); - floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); - - // Set by_user = true so that reshaped rect is saved in user_settings. - setShape(floater_rect, true); - - updateResizeLimits(); - - bool is_left_pane_expanded = !mConversationsPane->isCollapsed(); - bool is_right_pane_expanded = !mMessagesPane->isCollapsed(); - - setCanResize(is_left_pane_expanded || is_right_pane_expanded); - setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); - - // force set correct size for the title after show/hide minimize button - LLRect cur_rect = getRect(); - LLRect force_rect = cur_rect; - force_rect.mRight = cur_rect.mRight + 1; - setRect(force_rect); - setRect(cur_rect); - - // restore floater's resize limits (prevent collapse when left panel is expanded) - if (is_left_pane_expanded && !is_right_pane_expanded) - { - S32 expanded_min_size = mConversationsPane->getExpandedMinDim(); - setResizeLimits(expanded_min_size, expanded_min_size); - } - -} - -void LLIMFloaterContainer::onAddButtonClicked() -{ - LLView * button = findChild<LLView>("conversations_pane_buttons_expanded")->findChild<LLButton>("add_btn"); - LLFloater* root_floater = gFloaterView->getParentFloater(this); - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloaterContainer::onAvatarPicked, this, _1), TRUE, TRUE, TRUE, root_floater->getName(), button); - - if (picker && root_floater) - { - root_floater->addDependentFloater(picker); - } -} - -void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) -{ - if (ids.size() == 1) - { - LLAvatarActions::startIM(ids.back()); - } - else - { - LLAvatarActions::startConference(ids); - } -} - -void LLIMFloaterContainer::onCustomAction(const LLSD& userdata) -{ - std::string command = userdata.asString(); - - if ("sort_sessions_by_type" == command) - { - setSortOrderSessions(LLConversationFilter::SO_SESSION_TYPE); - } - if ("sort_sessions_by_name" == command) - { - setSortOrderSessions(LLConversationFilter::SO_NAME); - } - if ("sort_sessions_by_recent" == command) - { - setSortOrderSessions(LLConversationFilter::SO_DATE); - } - if ("sort_participants_by_name" == command) - { - setSortOrderParticipants(LLConversationFilter::SO_NAME); - } - if ("sort_participants_by_recent" == command) - { - setSortOrderParticipants(LLConversationFilter::SO_DATE); - } - if ("sort_participants_by_distance" == command) - { - setSortOrderParticipants(LLConversationFilter::SO_DISTANCE); - } - if ("chat_preferences" == command) - { - LLFloaterPreference* floater_prefs = LLFloaterReg::showTypedInstance<LLFloaterPreference>("preferences"); - if (floater_prefs) - { - LLTabContainer* tab_container = floater_prefs->getChild<LLTabContainer>("pref core"); - LLPanel* chat_panel = tab_container->getPanelByName("chat"); - if (tab_container && chat_panel) - { - tab_container->selectTabPanel(chat_panel); - } - } - } -} - -BOOL LLIMFloaterContainer::isActionChecked(const LLSD& userdata) -{ - LLConversationSort order = mConversationViewModel.getSorter(); - std::string command = userdata.asString(); - if ("sort_sessions_by_type" == command) - { - return (order.getSortOrderSessions() == LLConversationFilter::SO_SESSION_TYPE); - } - if ("sort_sessions_by_name" == command) - { - return (order.getSortOrderSessions() == LLConversationFilter::SO_NAME); - } - if ("sort_sessions_by_recent" == command) - { - return (order.getSortOrderSessions() == LLConversationFilter::SO_DATE); - } - if ("sort_participants_by_name" == command) - { - return (order.getSortOrderParticipants() == LLConversationFilter::SO_NAME); - } - if ("sort_participants_by_recent" == command) - { - return (order.getSortOrderParticipants() == LLConversationFilter::SO_DATE); - } - if ("sort_participants_by_distance" == command) - { - return (order.getSortOrderParticipants() == LLConversationFilter::SO_DISTANCE); - } - - return FALSE; -} - -void LLIMFloaterContainer::setSortOrderSessions(const LLConversationFilter::ESortOrderType order) -{ - LLConversationSort old_order = mConversationViewModel.getSorter(); - if (order != old_order.getSortOrderSessions()) - { - old_order.setSortOrderSessions(order); - setSortOrder(old_order); - } -} - -void LLIMFloaterContainer::setSortOrderParticipants(const LLConversationFilter::ESortOrderType order) -{ - LLConversationSort old_order = mConversationViewModel.getSorter(); - if (order != old_order.getSortOrderParticipants()) - { - old_order.setSortOrderParticipants(order); - setSortOrder(old_order); - } -} - -void LLIMFloaterContainer::setSortOrder(const LLConversationSort& order) -{ - mConversationViewModel.setSorter(order); - mConversationsRoot->arrangeAll(); - // try to keep selection onscreen, even if it wasn't to start with - mConversationsRoot->scrollToShowSelection(); - - // Notify all conversation (torn off or not) of the change to the sort order - // Note: For the moment, the sort order is *unique* across all conversations. That might change in the future. - for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) - { - LLUUID session_id = it_session->first; - LLIMConversation *conversation_floater = (session_id.isNull() ? (LLIMConversation*)(LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")) : (LLIMConversation*)(LLIMFloater::findInstance(session_id))); - if (conversation_floater) - { - conversation_floater->setSortOrder(order); - } - } - - gSavedSettings.setU32("ConversationSortOrder", (U32)order); -} - -void LLIMFloaterContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids) -{ - const std::set<LLFolderViewItem*> selectedItems = mConversationsRoot->getSelectionList(); - - std::set<LLFolderViewItem*>::const_iterator it = selectedItems.begin(); - const std::set<LLFolderViewItem*>::const_iterator it_end = selectedItems.end(); - LLConversationItem * conversationItem; - - for (; it != it_end; ++it) - { - conversationItem = static_cast<LLConversationItem *>((*it)->getViewModelItem()); - selected_uuids.push_back(conversationItem->getUUID()); - } -} - -const LLConversationItem * LLIMFloaterContainer::getCurSelectedViewModelItem() -{ - LLConversationItem * conversationItem = NULL; - - if(mConversationsRoot && - mConversationsRoot->getCurSelectedItem() && - mConversationsRoot->getCurSelectedItem()->getViewModelItem()) - { - conversationItem = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem()); - } - - return conversationItem; -} - -void LLIMFloaterContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) -{ - //Find the conversation floater associated with the selected id - const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); - - if(conversationItem->getType() == LLConversationItem::CONV_PARTICIPANT) - { - getSelectedUUIDs(selected_uuids); - } - //When a one-on-one conversation exists, retrieve the participant id from the conversation floater - else if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) - { - LLIMFloater *conversationFloater = LLIMFloater::findInstance(conversationItem->getUUID()); - LLUUID participantID = conversationFloater->getOtherParticipantUUID(); - selected_uuids.push_back(participantID); - } -} - -void LLIMFloaterContainer::doToParticipants(const std::string& command, uuid_vec_t& selectedIDS) -{ - if(selectedIDS.size() > 0) - { - const LLUUID& userID = selectedIDS.front(); - if(gAgent.getID() != userID) - { - if ("view_profile" == command) - { - LLAvatarActions::showProfile(userID); - } - else if("im" == command) - { - LLAvatarActions::startIM(userID); - } - else if("offer_teleport" == command) - { - LLAvatarActions::offerTeleport(selectedIDS); - } - else if("voice_call" == command) - { - LLAvatarActions::startCall(userID); - } - else if("chat_history" == command) - { - LLAvatarActions::viewChatHistory(userID); - } - else if("add_friend" == command) - { - LLAvatarActions::requestFriendshipDialog(userID); - } - else if("remove_friend" == command) - { - LLAvatarActions::removeFriendDialog(userID); - } - else if("invite_to_group" == command) - { - LLAvatarActions::inviteToGroup(userID); - } - else if("map" == command) - { - LLAvatarActions::showOnMap(userID); - } - else if("share" == command) - { - LLAvatarActions::share(userID); - } - else if("pay" == command) - { - LLAvatarActions::pay(userID); - } - else if("block_unblock" == command) - { - LLAvatarActions::toggleBlock(userID); - } - else if("selected" == command || "mute_all" == command || "unmute_all" == command) - { - moderateVoice(command, userID); - } - else if ("toggle_allow_text_chat" == command) - { - toggleAllowTextChat(userID); - } - } - } -} - -void LLIMFloaterContainer::doToSelectedConversation(const std::string& command, uuid_vec_t& selectedIDS) -{ - //Find the conversation floater associated with the selected id - const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); - LLIMFloater *conversationFloater = LLIMFloater::findInstance(conversationItem->getUUID()); - - if(conversationFloater) - { - //Close the selected conversation - if("close_conversation" == command) - { - LLFloater::onClickClose(conversationFloater); - } - else if("open_voice_conversation" == command) - { - gIMMgr->startCall(conversationItem->getUUID()); - } - else if("disconnect_from_voice" == command) - { - gIMMgr->endCall(conversationItem->getUUID()); - } - else if("chat_history" == command) - { - const LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(conversationItem->getUUID()); - - if (NULL != session) - { - const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID; - LLFloaterReg::showInstance("preview_conversation", session_id, true); - } - } - else - { - doToParticipants(command, selectedIDS); - } - } -} - -void LLIMFloaterContainer::doToSelected(const LLSD& userdata) -{ - std::string command = userdata.asString(); - const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); - uuid_vec_t selected_uuids; - - if(conversationItem != NULL) - { - getParticipantUUIDs(selected_uuids); - - if(conversationItem->getType() == LLConversationItem::CONV_PARTICIPANT) - { - doToParticipants(command, selected_uuids); - } - else - { - doToSelectedConversation(command, selected_uuids); - } - } -} - -void LLIMFloaterContainer::doToSelectedGroup(const LLSD& userdata) -{ - std::string action = userdata.asString(); - LLUUID selected_group = getCurSelectedViewModelItem()->getUUID(); - - if (action == "group_profile") - { - LLGroupActions::show(selected_group); - } - else if (action == "activate_group") - { - LLGroupActions::activate(selected_group); - } - else if (action == "leave_group") - { - LLGroupActions::leave(selected_group); - } -} - -bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) -{ - std::string item = userdata.asString(); - uuid_vec_t uuids; - getParticipantUUIDs(uuids); - - if(item == std::string("can_activate_group")) - { - LLUUID selected_group_id = getCurSelectedViewModelItem()->getUUID(); - return gAgent.getGroupID() != selected_group_id; - } - - if(uuids.size() <= 0) - { - return false; - } - - // Note: can_block and can_delete is used only for one person selected menu - // so we don't need to go over all uuids. - - if (item == std::string("can_block")) - { - const LLUUID& id = uuids.front(); - return LLAvatarActions::canBlock(id); - } - else if (item == std::string("can_add")) - { - // We can add friends if: - // - there are selected people - // - and there are no friends among selection yet. - - //EXT-7389 - disable for more than 1 - if(uuids.size() > 1) - { - return false; - } - - bool result = true; - - uuid_vec_t::const_iterator - id = uuids.begin(), - uuids_end = uuids.end(); - - for (;id != uuids_end; ++id) - { - if ( LLAvatarActions::isFriend(*id) ) - { - result = false; - break; - } - } - - return result; - } - else if (item == std::string("can_delete")) - { - // We can remove friends if: - // - there are selected people - // - and there are only friends among selection. - - bool result = (uuids.size() > 0); - - uuid_vec_t::const_iterator - id = uuids.begin(), - uuids_end = uuids.end(); - - for (;id != uuids_end; ++id) - { - if ( !LLAvatarActions::isFriend(*id) ) - { - result = false; - break; - } - } - - return result; - } - else if (item == std::string("can_call")) - { - return LLAvatarActions::canCall(); - } - else if (item == std::string("can_show_on_map")) - { - const LLUUID& id = uuids.front(); - - return (LLAvatarTracker::instance().isBuddyOnline(id) && is_agent_mappable(id)) - || gAgent.isGodlike(); - } - else if(item == std::string("can_offer_teleport")) - { - return LLAvatarActions::canOfferTeleport(uuids); - } - else if("can_moderate_voice" == item || "can_allow_text_chat" == item || "can_mute" == item || "can_unmute" == item) - { - return enableModerateContextMenuItem(item); - } - - return false; -} - -bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata) -{ - std::string item = userdata.asString(); - uuid_vec_t mUUIDs; - getParticipantUUIDs(mUUIDs); - - if(mUUIDs.size() > 0 ) - { - if ("is_blocked" == item) - { - return LLAvatarActions::isBlocked(mUUIDs.front()); - } - else if ("is_allowed_text_chat" == item) - { - const LLSpeaker * speakerp = getSpeakerOfSelectedParticipant(getSpeakerMgrForSelectedParticipant()); - - if (NULL != speakerp) - { - return !speakerp->mModeratorMutedText; - } - } - } - - return false; -} - -void LLIMFloaterContainer::showConversation(const LLUUID& session_id) -{ - setVisibleAndFrontmost(false); - selectConversation(session_id); -} - -// Will select only the conversation item -void LLIMFloaterContainer::selectConversation(const LLUUID& session_id) -{ - LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); - if (widget) - { - (widget->getRoot())->setSelection(widget, FALSE, FALSE); - } -} - -// Synchronous select the conversation item and the conversation floater -BOOL LLIMFloaterContainer::selectConversationPair(const LLUUID& session_id, bool select_widget) -{ - BOOL handled = TRUE; - - /* widget processing */ - if (select_widget) - { - LLFolderViewItem* widget = mConversationsWidgets[session_id]; - if (widget && widget->getParentFolder()) - { - widget->getParentFolder()->setSelection(widget, FALSE, FALSE); - } - } - - /* floater processing */ - - if (session_id != getSelectedSession()) - { - // Store the active session - setSelectedSession(session_id); - - LLIMConversation* session_floater = LLIMConversation::getConversation(session_id); - - if (session_floater->getHost()) - { - // Always expand the message pane if the panel is hosted by the container - collapseMessagesPane(false); - // Switch to the conversation floater that is being selected - selectFloater(session_floater); - } - - // Set the focus on the selected floater - if (!session_floater->hasFocus()) - { - session_floater->setFocus(TRUE); - } - } - - return handled; -} - -void LLIMFloaterContainer::setTimeNow(const LLUUID& session_id, const LLUUID& participant_id) -{ - LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,session_id)); - if (item) - { - item->setTimeNow(participant_id); - mConversationViewModel.requestSortAll(); - mConversationsRoot->arrangeAll(); - } -} - -void LLIMFloaterContainer::setNearbyDistances() -{ - // Get the nearby chat session: that's the one with uuid nul - LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,LLUUID())); - if (item) - { - // Get the positions of the nearby avatars and their ids - std::vector<LLVector3d> positions; - uuid_vec_t avatar_ids; - LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); - // Get the position of the agent - const LLVector3d& me_pos = gAgent.getPositionGlobal(); - // For each nearby avatar, compute and update the distance - int avatar_count = positions.size(); - for (int i = 0; i < avatar_count; i++) - { - F64 dist = dist_vec_squared(positions[i], me_pos); - item->setDistance(avatar_ids[i],dist); - } - // Also does it for the agent itself - item->setDistance(gAgent.getID(),0.0f); - // Request resort - mConversationViewModel.requestSortAll(); - mConversationsRoot->arrangeAll(); - } -} - -LLConversationItem* LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/) -{ - bool is_nearby_chat = uuid.isNull(); - - // Stores the display name for the conversation line item - std::string display_name = is_nearby_chat ? LLTrans::getString("NearbyChatLabel") : LLIMModel::instance().getName(uuid); - - // Check if the item is not already in the list, exit (nothing to do) - // Note: this happens often, when reattaching a torn off conversation for instance - conversations_items_map::iterator item_it = mConversationsItems.find(uuid); - if (item_it != mConversationsItems.end()) - { - return item_it->second; - } - - // Remove the conversation item that might exist already: it'll be recreated anew further down anyway - // and nothing wrong will happen removing it if it doesn't exist - removeConversationListItem(uuid,false); - - // Create a conversation session model - LLConversationItemSession* item = NULL; - LLSpeakerMgr* speaker_manager = (is_nearby_chat ? (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()) : LLIMModel::getInstance()->getSpeakerManager(uuid)); - if (speaker_manager) - { - item = new LLParticipantList(speaker_manager, getRootViewModel()); - } - if (!item) - { - llwarns << "Couldn't create conversation session item : " << display_name << llendl; - return NULL; - } - item->renameItem(display_name); - item->updateParticipantName(NULL); - - mConversationsItems[uuid] = item; - - // Create a widget from it - LLConversationViewSession* widget = createConversationItemWidget(item); - mConversationsWidgets[uuid] = widget; - - // Add a new conversation widget to the root folder of the folder view - widget->addToFolder(mConversationsRoot); - widget->requestArrange(); - - LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(uuid); - - // Create the participants widgets now - // Note: usually, we do not get an updated avatar list at that point - if (uuid.isNull() || im_sessionp && !im_sessionp->isP2PSessionType()) - { - LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); - LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); - while (current_participant_model != end_participant_model) - { - LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); - LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); - participant_view->addToFolder(widget); - current_participant_model++; - } - } - // Do that too for the conversation dialog - LLIMConversation *conversation_floater = (uuid.isNull() ? (LLIMConversation*)(LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")) : (LLIMConversation*)(LLIMFloater::findInstance(uuid))); - if (conversation_floater) - { - conversation_floater->buildConversationViewParticipant(); - } - - // set the widget to minimized mode if conversations pane is collapsed - widget->toggleMinimizedMode(mConversationsPane->isCollapsed()); - - if (isWidgetSelected) - { - selectConversation(uuid); - // scroll to newly added item - mConversationsRoot->scrollToShowSelection(); - } - - return item; -} - -bool LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) -{ - // Delete the widget and the associated conversation item - // Note : since the mConversationsItems is also the listener to the widget, deleting - // the widget will also delete its listener - bool isWidgetSelected = false; - LLFolderViewItem* new_selection = NULL; - LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); - if (widget) - { - isWidgetSelected = widget->isSelected(); - new_selection = mConversationsRoot->getNextFromChild(widget); - if(new_selection == NULL) - { - new_selection = mConversationsRoot->getPreviousFromChild(widget); - } - widget->destroyView(); - } - - // Suppress the conversation items and widgets from their respective maps - mConversationsItems.erase(uuid); - mConversationsWidgets.erase(uuid); - - // Don't let the focus fall IW, select and refocus on the first conversation in the list - if (change_focus) - { - setFocus(TRUE); - if(new_selection != NULL) - { - LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem()); - if(vmi != NULL) - { - selectConversation(vmi->getUUID()); - } - } - } - return isWidgetSelected; -} - -LLConversationViewSession* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) -{ - LLConversationViewSession::Params params; - - params.name = item->getDisplayName(); - params.root = mConversationsRoot; - params.listener = item; - params.tool_tip = params.name; - params.container = this; - - return LLUICtrlFactory::create<LLConversationViewSession>(params); -} - -LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParticipant(LLConversationItem* item) -{ - LLConversationViewParticipant::Params params; - LLRect panel_rect = mConversationsListPanel->getRect(); - - params.name = item->getDisplayName(); - params.root = mConversationsRoot; - params.listener = item; - - //24 is the the current hight of an item (itemHeight) loaded from conversation_view_participant.xml. - params.rect = LLRect (0, 24, panel_rect.getWidth(), 0); - params.tool_tip = params.name; - params.participant_id = item->getUUID(); - params.folder_indentation = 42; - - return LLUICtrlFactory::create<LLConversationViewParticipant>(params); -} - -bool LLIMFloaterContainer::enableModerateContextMenuItem(const std::string& userdata) -{ - // only group moderators can perform actions related to this "enable callback" - if (!isGroupModerator()) - { - return false; - } - - LLSpeaker * speakerp = getSpeakerOfSelectedParticipant(getSpeakerMgrForSelectedParticipant()); - if (NULL == speakerp) - { - return false; - } - - bool voice_channel = speakerp->isInVoiceChannel(); - - if ("can_moderate_voice" == userdata) - { - return voice_channel; - } - else if ("can_mute" == userdata) - { - return voice_channel && !isMuted(getCurSelectedViewModelItem()->getUUID()); - } - else if ("can_unmute" == userdata) - { - return voice_channel && isMuted(getCurSelectedViewModelItem()->getUUID()); - } - - // The last invoke is used to check whether the "can_allow_text_chat" will enabled - return LLVoiceClient::getInstance()->isParticipantAvatar(getCurSelectedViewModelItem()->getUUID()); -} - -bool LLIMFloaterContainer::isGroupModerator() -{ - LLSpeakerMgr * speaker_manager = getSpeakerMgrForSelectedParticipant(); - if (NULL == speaker_manager) - { - llwarns << "Speaker manager is missing" << llendl; - return false; - } - - // Is session a group call/chat? - if(gAgent.isInGroup(speaker_manager->getSessionID())) - { - LLSpeaker * speaker = speaker_manager->findSpeaker(gAgentID).get(); - - // Is agent a moderator? - return speaker && speaker->mIsModerator; - } - - return false; -} - -void LLIMFloaterContainer::moderateVoice(const std::string& command, const LLUUID& userID) -{ - if (!gAgent.getRegion()) return; - - if (command.compare("selected")) - { - moderateVoiceAllParticipants(command.compare("mute_all")); - } - else - { - moderateVoiceParticipant(userID, isMuted(userID)); - } -} - -bool LLIMFloaterContainer::isMuted(const LLUUID& avatar_id) -{ - const LLSpeaker * speakerp = getSpeakerOfSelectedParticipant(getSpeakerMgrForSelectedParticipant()); - return NULL == speakerp ? true : speakerp->mStatus == LLSpeaker::STATUS_MUTED; -} - -void LLIMFloaterContainer::moderateVoiceAllParticipants(bool unmute) -{ - LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr*>(getSpeakerMgrForSelectedParticipant()); - - if (NULL != speaker_managerp) - { - if (!unmute) - { - LLSD payload; - payload["session_id"] = speaker_managerp->getSessionID(); - LLNotificationsUtil::add("ConfirmMuteAll", LLSD(), payload, confirmMuteAllCallback); - return; - } - - speaker_managerp->moderateVoiceAllParticipants(unmute); - } -} - -// static -void LLIMFloaterContainer::confirmMuteAllCallback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - // if Cancel pressed - if (option == 1) - { - return; - } - - const LLSD& payload = notification["payload"]; - const LLUUID& session_id = payload["session_id"]; - - LLIMSpeakerMgr * speaker_manager = dynamic_cast<LLIMSpeakerMgr*> ( - LLIMModel::getInstance()->getSpeakerManager(session_id)); - if (speaker_manager) - { - speaker_manager->moderateVoiceAllParticipants(false); - } - - return; -} - -void LLIMFloaterContainer::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute) -{ - LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr *>(getSpeakerMgrForSelectedParticipant()); - - if (NULL != speaker_managerp) - { - speaker_managerp->moderateVoiceParticipant(avatar_id, unmute); - } -} - -LLSpeakerMgr * LLIMFloaterContainer::getSpeakerMgrForSelectedParticipant() -{ - LLFolderViewItem * selected_folder_itemp = mConversationsRoot->getCurSelectedItem(); - if (NULL == selected_folder_itemp) - { - llwarns << "Current selected item is null" << llendl; - return NULL; - } - - LLFolderViewFolder * conversation_itemp = selected_folder_itemp->getParentFolder(); - - conversations_widgets_map::const_iterator iter = mConversationsWidgets.begin(); - conversations_widgets_map::const_iterator end = mConversationsWidgets.end(); - const LLUUID * conversation_uuidp = NULL; - while(iter != end) - { - if (iter->second == conversation_itemp) - { - conversation_uuidp = &iter->first; - break; - } - ++iter; - } - if (NULL == conversation_uuidp) - { - llwarns << "Cannot find conversation item widget" << llendl; - return NULL; - } - - return conversation_uuidp->isNull() ? (LLSpeakerMgr *)LLLocalSpeakerMgr::getInstance() - : LLIMModel::getInstance()->getSpeakerManager(*conversation_uuidp); -} - -LLSpeaker * LLIMFloaterContainer::getSpeakerOfSelectedParticipant(LLSpeakerMgr * speaker_managerp) -{ - if (NULL == speaker_managerp) - { - llwarns << "Speaker manager is missing" << llendl; - return NULL; - } - - const LLConversationItem * participant_itemp = getCurSelectedViewModelItem(); - if (NULL == participant_itemp) - { - llwarns << "Cannot evaluate current selected view model item" << llendl; - return NULL; - } - - return speaker_managerp->findSpeaker(participant_itemp->getUUID()); -} - -void LLIMFloaterContainer::toggleAllowTextChat(const LLUUID& participant_uuid) -{ - LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr*>(getSpeakerMgrForSelectedParticipant()); - if (NULL != speaker_managerp) - { - speaker_managerp->toggleAllowTextChat(participant_uuid); - } -} - -void LLIMFloaterContainer::openNearbyChat() -{ - // If there's only one conversation in the container and that conversation is the nearby chat - //(which it should be...), open it so to make the list of participants visible. This happens to be the most common case when opening the Chat floater. - if(mConversationsItems.size() == 1) - { - LLConversationViewSession* nearby_chat = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[LLUUID()]); - if (nearby_chat) - { - nearby_chat->setOpen(TRUE); - } - } -} - -void LLIMFloaterContainer::onNearbyChatClosed() -{ - // If nearby chat is the only remaining conversation and it is closed, close whole conversation floater as well - if (mConversationsItems.size() == 1) - closeFloater(); -} - -// EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h deleted file mode 100644 index e42ed053cb..0000000000 --- a/indra/newview/llimfloatercontainer.h +++ /dev/null @@ -1,178 +0,0 @@ -/** - * @file llimfloatercontainer.h - * @brief Multifloater containing active IM sessions in separate tab container tabs - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLIMFLOATERCONTAINER_H -#define LL_LLIMFLOATERCONTAINER_H - -#include <map> -#include <vector> - -#include "llimview.h" -#include "llevents.h" -#include "llfloater.h" -#include "llmultifloater.h" -#include "llavatarpropertiesprocessor.h" -#include "llgroupmgr.h" -#include "lltrans.h" -#include "llconversationmodel.h" -#include "llconversationview.h" - -class LLButton; -class LLLayoutPanel; -class LLLayoutStack; -class LLTabContainer; -class LLIMFloaterContainer; -class LLSpeaker; -class LLSpeakerMgr; - -class LLIMFloaterContainer - : public LLMultiFloater - , public LLIMSessionObserver -{ -public: - LLIMFloaterContainer(const LLSD& seed); - virtual ~LLIMFloaterContainer(); - - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void draw(); - /*virtual*/ void setVisible(BOOL visible); - void onCloseFloater(LLUUID& id); - - /*virtual*/ void addFloater(LLFloater* floaterp, - BOOL select_added_floater, - LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); - - void showConversation(const LLUUID& session_id); - void selectConversation(const LLUUID& session_id); - BOOL selectConversationPair(const LLUUID& session_id, bool select_widget); - - /*virtual*/ void tabClose(); - - static LLFloater* getCurrentVoiceFloater(); - static LLIMFloaterContainer* findInstance(); - static LLIMFloaterContainer* getInstance(); - - static void onCurrentChannelChanged(const LLUUID& session_id); - - void collapseMessagesPane(bool collapse); - - // Callbacks - static void idle(void* user_data); - - // LLIMSessionObserver observe triggers - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); - /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); - /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id); - /*virtual*/ void sessionRemoved(const LLUUID& session_id); - /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); - - LLConversationViewModel& getRootViewModel() { return mConversationViewModel; } - LLUUID getSelectedSession() { return mSelectedSession; } - void setSelectedSession(LLUUID sessionID) { mSelectedSession = sessionID; } - LLConversationItem* getSessionModel(const LLUUID& session_id) { return get_ptr_in_map(mConversationsItems,session_id); } - LLConversationSort& getSortOrder() { return mConversationViewModel.getSorter(); } - - void onNearbyChatClosed(); - -private: - typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; - avatarID_panel_map_t mSessions; - boost::signals2::connection mNewMessageConnection; - - /*virtual*/ void computeResizeLimits(S32& new_min_width, S32& new_min_height); - - void onNewMessageReceived(const LLSD& data); - - void onExpandCollapseButtonClicked(); - void processParticipantsStyleUpdate(); - - void collapseConversationsPane(bool collapse); - - void updateState(bool collapse, S32 delta_width); - - void onAddButtonClicked(); - void onAvatarPicked(const uuid_vec_t& ids); - - BOOL isActionChecked(const LLSD& userdata); - void onCustomAction (const LLSD& userdata); - void setSortOrderSessions(const LLConversationFilter::ESortOrderType order); - void setSortOrderParticipants(const LLConversationFilter::ESortOrderType order); - void setSortOrder(const LLConversationSort& order); - - void getSelectedUUIDs(uuid_vec_t& selected_uuids); - const LLConversationItem * getCurSelectedViewModelItem(); - void getParticipantUUIDs(uuid_vec_t& selected_uuids); - void doToSelected(const LLSD& userdata); - void doToSelectedConversation(const std::string& command, uuid_vec_t& selectedIDS); - void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS); - void doToSelectedGroup(const LLSD& userdata); - bool checkContextMenuItem(const LLSD& userdata); - bool enableContextMenuItem(const LLSD& userdata); - - static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response); - bool enableModerateContextMenuItem(const std::string& userdata); - LLSpeaker * getSpeakerOfSelectedParticipant(LLSpeakerMgr * speaker_managerp); - LLSpeakerMgr * getSpeakerMgrForSelectedParticipant(); - bool isGroupModerator(); - bool isMuted(const LLUUID& avatar_id); - void moderateVoice(const std::string& command, const LLUUID& userID); - void moderateVoiceAllParticipants(bool unmute); - void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); - void toggleAllowTextChat(const LLUUID& participant_uuid); - void openNearbyChat(); - - LLButton* mExpandCollapseBtn; - LLLayoutPanel* mMessagesPane; - LLLayoutPanel* mConversationsPane; - LLLayoutStack* mConversationsStack; - - bool mInitialized; - - LLUUID mSelectedSession; - - // Conversation list implementation -public: - bool removeConversationListItem(const LLUUID& uuid, bool change_focus = true); - LLConversationItem* addConversationListItem(const LLUUID& uuid, bool isWidgetSelected = false); - void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); - void setNearbyDistances(); - -private: - LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); - LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item); - bool onConversationModelEvent(const LLSD& event); - - // Conversation list data - LLPanel* mConversationsListPanel; // This is the main widget we add conversation widget to - conversations_items_map mConversationsItems; - conversations_widgets_map mConversationsWidgets; - LLConversationViewModel mConversationViewModel; - LLFolderView* mConversationsRoot; - LLEventStream mConversationsEventStream; -}; - -#endif // LL_LLIMFLOATERCONTAINER_H diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 0250af6a0e..c64ecdc47a 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -171,7 +171,7 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, // enable line history support for instant message bar mInputEditor->setEnableLineHistory(TRUE); - //*TODO we probably need the same "awaiting message" thing in LLIMFloater + //*TODO we probably need the same "awaiting message" thing in LLFloaterIMSession LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionUUID); if (!im_session) { diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 9f24a5372f..6712127750 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -41,15 +41,15 @@ #include "lltextutil.h" #include "lltrans.h" #include "lluictrlfactory.h" -#include "llimconversation.h" +#include "llfloaterimsessiontab.h" #include "llagent.h" #include "llagentui.h" #include "llappviewer.h" #include "llavatariconctrl.h" #include "llcallingcard.h" #include "llchat.h" -#include "llimfloater.h" -#include "llimfloatercontainer.h" +#include "llfloaterimsession.h" +#include "llfloaterimcontainer.h" #include "llgroupiconctrl.h" #include "llmd5.h" #include "llmutelist.h" @@ -58,7 +58,7 @@ #include "llviewerwindow.h" #include "llnotifications.h" #include "llnotificationsutil.h" -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" #include "llspeakers.h" //for LLIMSpeakerMgr #include "lltextbox.h" #include "lltoolbarview.h" @@ -109,7 +109,7 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id, args["FROM"] = av_name.getCompleteName(); args["FROM_ID"] = msg["from_id"]; args["SESSION_ID"] = msg["session_id"]; - LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLIMFloaterContainer::showConversation, LLIMFloaterContainer::getInstance(), msg["session_id"].asUUID())); + LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); } void toast_callback(const LLSD& msg){ @@ -120,7 +120,7 @@ void toast_callback(const LLSD& msg){ } // Skip toasting if we have open window of IM with this session id - LLIMFloater* open_im_floater = LLIMFloater::findInstance(msg["session_id"]); + LLFloaterIMSession* open_im_floater = LLFloaterIMSession::findInstance(msg["session_id"]); if ( open_im_floater && open_im_floater->isInVisibleChain() @@ -160,7 +160,7 @@ void toast_callback(const LLSD& msg){ LLIMModel::LLIMModel() { - addNewMsgCallback(boost::bind(&LLIMFloater::newIMCallback, _1)); + addNewMsgCallback(boost::bind(&LLFloaterIMSession::newIMCallback, _1)); addNewMsgCallback(boost::bind(&toast_callback, _1)); } @@ -638,7 +638,7 @@ void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, con mId2SessionMap[new_session_id] = session; } - LLIMFloater* im_floater = LLIMFloater::findInstance(old_session_id); + LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(old_session_id); if (im_floater) { im_floater->sessionInitReplyReceived(new_session_id); @@ -1387,7 +1387,7 @@ public: && LLIMModel::getInstance()->findIMSession(mSessionID)) { // TODO remove in 2010, for voice calls we do not open an IM window - //LLIMFloater::show(mSessionID); + //LLFloaterIMSession::show(mSessionID); } gIMMgr->clearPendingAgentListUpdates(mSessionID); @@ -1531,7 +1531,7 @@ LLIMMgr::onConfirmForceCloseError( //only 1 option really LLUUID session_id = notification["payload"]["session_id"]; - LLFloater* floater = LLIMFloater::findInstance(session_id); + LLFloater* floater = LLFloaterIMSession::findInstance(session_id); if ( floater ) { floater->closeFloater(FALSE); @@ -2397,7 +2397,7 @@ LLIMMgr::LLIMMgr() mPendingInvitations = LLSD::emptyMap(); mPendingAgentListUpdates = LLSD::emptyMap(); - LLIMModel::getInstance()->addNewMsgCallback(boost::bind(&LLIMFloater::sRemoveTypingIndicator, _1)); + LLIMModel::getInstance()->addNewMsgCallback(boost::bind(&LLFloaterIMSession::sRemoveTypingIndicator, _1)); } // Add a message to a session. @@ -2492,7 +2492,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess LLChat chat(message); chat.mSourceType = CHAT_SOURCE_SYSTEM; - LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); if (nearby_chat) { nearby_chat->addMessage(chat); @@ -2618,12 +2618,12 @@ LLUUID LLIMMgr::addSession( if (floater_id.notNull()) { - LLIMFloater* im_floater = LLIMFloater::findInstance(floater_id); + LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(floater_id); if (im_floater && im_floater->getStartConferenceInSameFloater()) { // The IM floater should be initialized with a new session_id - // so that it is found by that id when creating a chiclet in LLIMFloater::onIMChicletCreated, + // so that it is found by that id when creating a chiclet in LLFloaterIMSession::onIMChicletCreated, // and a new floater is not created. im_floater->initIMSession(session_id); } @@ -2841,7 +2841,7 @@ void LLIMMgr::clearPendingInvitation(const LLUUID& session_id) void LLIMMgr::processAgentListUpdates(const LLUUID& session_id, const LLSD& body) { - LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); + LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(session_id); if ( im_floater ) { im_floater->processAgentListUpdates(body); @@ -3115,7 +3115,7 @@ void LLIMMgr::processIMTypingStop(const LLIMInfo* im_info) void LLIMMgr::processIMTypingCore(const LLIMInfo* im_info, BOOL typing) { LLUUID session_id = computeSessionID(im_info->mIMType, im_info->mFromID); - LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); + LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(session_id); if ( im_floater ) { im_floater->processIMTyping(im_info, typing); @@ -3160,7 +3160,7 @@ public: speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(session_id)); } - LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); + LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(session_id); if ( im_floater ) { if ( body.has("session_info") ) @@ -3254,7 +3254,7 @@ public: const LLSD& input) const { LLUUID session_id = input["body"]["session_id"].asUUID(); - LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); + LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(session_id); if ( im_floater ) { im_floater->processSessionUpdate(input["body"]["info"]); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 8b04af71c7..ffac67557a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -46,7 +46,7 @@ #include "llfriendcard.h" #include "llgesturemgr.h" #include "llgiveinventory.h" -#include "llimfloatercontainer.h" +#include "llfloaterimcontainer.h" #include "llimview.h" #include "llclipboard.h" #include "llinventorydefines.h" @@ -4683,7 +4683,7 @@ void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string act LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID()); if (session_id != LLUUID::null) { - LLIMFloaterContainer::getInstance()->showConversation(session_id); + LLFloaterIMContainer::getInstance()->showConversation(session_id); } } } diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index dafc71b59c..7c717af840 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -39,7 +39,7 @@ #include "llfloatersidepanelcontainer.h" #include "llfolderview.h" #include "llfolderviewitem.h" -#include "llimfloatercontainer.h" +#include "llfloaterimcontainer.h" #include "llimview.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" @@ -1087,7 +1087,7 @@ bool LLInventoryPanel::beginIMSession() LLUUID session_id = gIMMgr->addSession(name, type, members[0], members); if (session_id != LLUUID::null) { - LLIMFloaterContainer::getInstance()->showConversation(session_id); + LLFloaterIMContainer::getInstance()->showConversation(session_id); } return true; diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp deleted file mode 100644 index dbdf460785..0000000000 --- a/indra/newview/llnearbychat.cpp +++ /dev/null @@ -1,867 +0,0 @@ -/** - * @file LLNearbyChat.cpp - * @brief LLNearbyChat class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "message.h" - -#include "lliconctrl.h" -#include "llappviewer.h" -#include "llchatentry.h" -#include "llfloaterreg.h" -#include "lltrans.h" -#include "llimfloatercontainer.h" -#include "llfloatersidepanelcontainer.h" -#include "llfocusmgr.h" -#include "lllogchat.h" -#include "llresizebar.h" -#include "llresizehandle.h" -#include "lldraghandle.h" -#include "llmenugl.h" -#include "llviewermenu.h" // for gMenuHolder -#include "llnearbychathandler.h" -#include "llchannelmanager.h" -#include "llchathistory.h" -#include "llstylemap.h" -#include "llavatarnamecache.h" -#include "llfloaterreg.h" -#include "lltrans.h" - -#include "llfirstuse.h" -#include "llnearbychat.h" -#include "llagent.h" // gAgent -#include "llgesturemgr.h" -#include "llmultigesture.h" -#include "llkeyboard.h" -#include "llanimationstates.h" -#include "llviewerstats.h" -#include "llcommandhandler.h" -#include "llviewercontrol.h" -#include "llnavigationbar.h" -#include "llwindow.h" -#include "llviewerwindow.h" -#include "llrootview.h" -#include "llviewerchat.h" -#include "lltranslate.h" - -S32 LLNearbyChat::sLastSpecialChatChannel = 0; - -const S32 EXPANDED_HEIGHT = 266; -const S32 COLLAPSED_HEIGHT = 60; -const S32 EXPANDED_MIN_HEIGHT = 150; - -// legacy callback glue -void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); - -struct LLChatTypeTrigger { - std::string name; - EChatType type; -}; - -static LLChatTypeTrigger sChatTypeTriggers[] = { - { "/whisper" , CHAT_TYPE_WHISPER}, - { "/shout" , CHAT_TYPE_SHOUT} -}; - - -LLNearbyChat::LLNearbyChat(const LLSD& llsd) -: LLIMConversation(llsd), - //mOutputMonitor(NULL), - mSpeakerMgr(NULL), - mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) -{ - mIsP2PChat = false; - mIsNearbyChat = true; - setIsChrome(TRUE); - mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); - mSessionID = LLUUID(); -} - -//static -LLNearbyChat* LLNearbyChat::buildFloater(const LLSD& key) -{ - LLFloaterReg::getInstance("im_container"); - return new LLNearbyChat(key); -} - -//virtual -BOOL LLNearbyChat::postBuild() -{ - setIsSingleInstance(TRUE); - BOOL result = LLIMConversation::postBuild(); - mInputEditor->setCommitCallback(boost::bind(&LLNearbyChat::onChatBoxCommit, this)); - mInputEditor->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this)); - mInputEditor->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); - mInputEditor->setFocusReceivedCallback(boost::bind(&LLNearbyChat::onChatBoxFocusReceived, this)); - mInputEditor->setLabel(LLTrans::getString("NearbyChatTitle")); - -// mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); -// mOutputMonitor->setVisible(FALSE); - - // Register for font change notifications - LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChat::onChatFontChange, this, _1)); - - // title must be defined BEFORE call addConversationListItem() because - // it is used for show the item's name in the conversations list - setTitle(LLTrans::getString("NearbyChatTitle")); - - //for menu - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - - enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); - registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); - - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(menu) - { - mPopupMenuHandle = menu->getHandle(); - } - - // obsolete, but may be needed for backward compatibility? - gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); - - if (gSavedPerAccountSettings.getBOOL("LogShowHistory")) - { - loadHistory(); - } - - return result; -} - -// virtual -void LLNearbyChat::refresh() -{ - displaySpeakingIndicator(); - updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); - - // *HACK: Update transparency type depending on whether our children have focus. - // This is needed because this floater is chrome and thus cannot accept focus, so - // the transparency type setting code from LLFloater::setFocus() isn't reached. - if (getTransparencyType() != TT_DEFAULT) - { - setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE); - } -} - -void LLNearbyChat::onNearbySpeakers() -{ - LLSD param; - param["people_panel_tab_name"] = "nearby_panel"; - LLFloaterSidePanelContainer::showPanel("people", "panel_people", param); -} - -void LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata) -{ -} - -bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata) -{ - std::string str = userdata.asString(); - if(str == "nearby_people") - onNearbySpeakers(); - return false; -} - - -BOOL LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask) -{ - //fix for EXT-6625 - //highlight NearbyChat history whenever mouseclick happen in NearbyChat - //setting focus to eidtor will force onFocusLost() call that in its turn will change - //background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. - - if(mChatHistory) - { - mChatHistory->setFocus(TRUE); - } - - BOOL handled = LLPanel::handleMouseDown(x, y, mask); - setFocus(handled); - return handled; -} - -void LLNearbyChat::reloadMessages() -{ - mChatHistory->clear(); - - LLSD do_not_log; - do_not_log["do_not_log"] = true; - for(std::vector<LLChat>::iterator it = mMessageArchive.begin();it!=mMessageArchive.end();++it) - { - // Update the messages without re-writing them to a log file. - addMessage(*it,false, do_not_log); - } -} - -void LLNearbyChat::loadHistory() -{ - LLSD do_not_log; - do_not_log["do_not_log"] = true; - - std::list<LLSD> history; - LLLogChat::loadChatHistory("chat", history); - - std::list<LLSD>::const_iterator it = history.begin(); - while (it != history.end()) - { - const LLSD& msg = *it; - - std::string from = msg[IM_FROM]; - LLUUID from_id; - if (msg[IM_FROM_ID].isDefined()) - { - from_id = msg[IM_FROM_ID].asUUID(); - } - else - { - std::string legacy_name = gCacheName->buildLegacyName(from); - gCacheName->getUUID(legacy_name, from_id); - } - - LLChat chat; - chat.mFromName = from; - chat.mFromID = from_id; - chat.mText = msg[IM_TEXT].asString(); - chat.mTimeStr = msg[IM_TIME].asString(); - chat.mChatStyle = CHAT_STYLE_HISTORY; - - chat.mSourceType = CHAT_SOURCE_AGENT; - if (from_id.isNull() && SYSTEM_FROM == from) - { - chat.mSourceType = CHAT_SOURCE_SYSTEM; - - } - else if (from_id.isNull()) - { - chat.mSourceType = isWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT; - } - - addMessage(chat, true, do_not_log); - - it++; - } -} - -void LLNearbyChat::removeScreenChat() -{ - LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); - if(chat_channel) - { - chat_channel->removeToastsFromChannel(); - } -} - - -void LLNearbyChat::setVisible(BOOL visible) -{ - LLIMConversation::setVisible(visible); - - if(visible) - { - removeScreenChat(); - } - setFocus(visible); -} - -// virtual -void LLNearbyChat::onTearOffClicked() -{ - LLIMConversation::onTearOffClicked(); - - // see CHUI-170: Save torn-off state of the nearby chat between sessions - BOOL in_the_multifloater = !isTornOff(); - gSavedSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater); -} - - -// virtual -void LLNearbyChat::onOpen(const LLSD& key) -{ - LLIMConversation::onOpen(key); - showTranslationCheckbox(LLTranslate::isTranslationConfigured()); -} - -// virtual -void LLNearbyChat::onClose(bool app_quitting) -{ - // Override LLIMConversation::onClose() so that Nearby Chat is not removed from the conversation floater -} - -// virtual -void LLNearbyChat::onClickCloseBtn() -{ - if (!isTornOff()) - return; - onTearOffClicked(); - - LLIMFloaterContainer *im_box = LLIMFloaterContainer::findInstance(); - if (im_box) - { - im_box->onNearbyChatClosed(); - } -} - -void LLNearbyChat::onChatFontChange(LLFontGL* fontp) -{ - // Update things with the new font whohoo - if (mInputEditor) - { - mInputEditor->setFont(fontp); - } -} - - -void LLNearbyChat::show() -{ - if (isChatMultiTab()) - { - openFloater(getKey()); - } -} - -bool LLNearbyChat::isChatVisible() const -{ - bool isVisible = false; - LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); - // Is the IM floater container ever null? - llassert(im_box != NULL); - if (im_box != NULL) - { - isVisible = - isChatMultiTab() && gSavedSettings.getBOOL("NearbyChatIsNotTornOff")? - im_box->getVisible() && !im_box->isMinimized() : - getVisible() && !isMinimized(); - } - - return isVisible; -} - -void LLNearbyChat::showHistory() -{ - openFloater(); - setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); -} - -std::string LLNearbyChat::getCurrentChat() -{ - return mInputEditor ? mInputEditor->getText() : LLStringUtil::null; -} - -// virtual -BOOL LLNearbyChat::handleKeyHere( KEY key, MASK mask ) -{ - BOOL handled = FALSE; - - if( KEY_RETURN == key && mask == MASK_CONTROL) - { - // shout - sendChat(CHAT_TYPE_SHOUT); - handled = TRUE; - } - - return handled; -} - -BOOL LLNearbyChat::matchChatTypeTrigger(const std::string& in_str, std::string* out_str) -{ - U32 in_len = in_str.length(); - S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); - - bool string_was_found = false; - - for (S32 n = 0; n < cnt && !string_was_found; n++) - { - if (in_len <= sChatTypeTriggers[n].name.length()) - { - std::string trigger_trunc = sChatTypeTriggers[n].name; - LLStringUtil::truncate(trigger_trunc, in_len); - - if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) - { - *out_str = sChatTypeTriggers[n].name; - string_was_found = true; - } - } - } - - return string_was_found; -} - -void LLNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userdata) -{ - LLFirstUse::otherAvatarChatFirst(false); - - LLNearbyChat* self = (LLNearbyChat *)userdata; - - LLWString raw_text = self->mInputEditor->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 (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) - { - std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); - self->mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part - - // Select to end of line, starting from the character - // after the last one the user typed. - self->mInputEditor->selectNext(rest_of_match, false); - } - else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) - { - std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); - self->mInputEditor->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part - self->mInputEditor->endOfDoc(); - } - - //llinfos << "GESTUREDEBUG " << trigger - // << " len " << length - // << " outlen " << out_str.getLength() - // << llendl; - } -} - -// static -void LLNearbyChat::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) -{ - // stop typing animation - gAgent.stopTyping(); -} - -void LLNearbyChat::onChatBoxFocusReceived() -{ - mInputEditor->setEnabled(!gDisconnected); -} - -EChatType LLNearbyChat::processChatTypeTriggers(EChatType type, std::string &str) -{ - U32 length = str.length(); - S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); - - for (S32 n = 0; n < cnt; n++) - { - if (length >= sChatTypeTriggers[n].name.length()) - { - std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length()); - - if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name)) - { - U32 trigger_length = sChatTypeTriggers[n].name.length(); - - // It's to remove space after trigger name - if (length > trigger_length && str[trigger_length] == ' ') - trigger_length++; - - str = str.substr(trigger_length, length); - - if (CHAT_TYPE_NORMAL == type) - return sChatTypeTriggers[n].type; - else - break; - } - } - } - - return type; -} - -void LLNearbyChat::sendChat( EChatType type ) -{ - if (mInputEditor) - { - LLWString text = mInputEditor->getWText(); - LLWStringUtil::trim(text); - LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. - if (!text.empty()) - { - // 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 - LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); - } - else - { - utf8_revised_text = utf8text; - } - - utf8_revised_text = utf8str_trim(utf8_revised_text); - - type = processChatTypeTriggers(type, utf8_revised_text); - - if (!utf8_revised_text.empty()) - { - // Chat with animation - sendChatFromViewer(utf8_revised_text, type, TRUE); - } - } - - mInputEditor->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 LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) -{ - appendMessage(chat, args); - - if(archive) - { - mMessageArchive.push_back(chat); - if(mMessageArchive.size()>200) - mMessageArchive.erase(mMessageArchive.begin()); - } - - // logging - if (!args["do_not_log"].asBoolean() - && gSavedPerAccountSettings.getBOOL("LogNearbyChat")) - { - std::string from_name = chat.mFromName; - - if (chat.mSourceType == CHAT_SOURCE_AGENT) - { - // if the chat is coming from an agent, log the complete name - LLAvatarName av_name; - LLAvatarNameCache::get(chat.mFromID, &av_name); - - if (!av_name.mIsDisplayNameDefault) - { - from_name = av_name.getCompleteName(); - } - } - - LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText); - } -} - - -void LLNearbyChat::onChatBoxCommit() -{ - if (mInputEditor->getText().length() > 0) - { - sendChat(CHAT_TYPE_NORMAL); - } - - gAgent.stopTyping(); -} - -void LLNearbyChat::displaySpeakingIndicator() -{ - LLSpeakerMgr::speaker_list_t speaker_list; - LLUUID id; - - id.setNull(); - mSpeakerMgr->update(TRUE); - mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); - - for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) - { - LLPointer<LLSpeaker> s = *i; - if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) - { - id = s->mID; - break; - } - } - - if (!id.isNull()) - { - //mOutputMonitor->setVisible(TRUE); - //mOutputMonitor->setSpeakerId(id); - } - else - { - //mOutputMonitor->setVisible(FALSE); - } -} - -void LLNearbyChat::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) -{ - sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate); -} - -void LLNearbyChat::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 -bool LLNearbyChat::isWordsName(const std::string& name) -{ - // checking to see if it's display name plus username in parentheses - S32 open_paren = name.find(" (", 0); - S32 close_paren = name.find(')', 0); - - if (open_paren != std::string::npos && - close_paren == name.length()-1) - { - return true; - } - else - { - //checking for a single space - S32 pos = name.find(' ', 0); - return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos; - } -} - -// static -void LLNearbyChat::startChat(const char* line) -{ - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); - if (nearby_chat) - { - nearby_chat->show(); - nearby_chat->setVisible(TRUE); - nearby_chat->setFocus(TRUE); - nearby_chat->mInputEditor->setFocus(TRUE); - - if (line) - { - std::string line_string(line); - nearby_chat->mInputEditor->setText(line_string); - } - - nearby_chat->mInputEditor->endOfDoc(); - } -} - -// Exit "chat mode" and do the appropriate focus changes -// static -void LLNearbyChat::stopChat() -{ - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); - if (nearby_chat) - { - nearby_chat->mInputEditor->setFocus(FALSE); - gAgent.stopTyping(); - } -} - -// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20. -// Otherwise returns input and channel 0. -LLWString LLNearbyChat::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 LLChatCommandHandler : public LLCommandHandler -{ -public: - // not allowed from outside the app - LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } - - // Your code here - bool handle(const LLSD& tokens, const LLSD& query_map, - LLMediaCtrl* web) - { - bool retval = false; - // Need at least 2 tokens to have a valid message. - if (tokens.size() < 2) - { - retval = false; - } - else - { - S32 channel = tokens[0].asInteger(); - // VWR-19499 Restrict function to chat channels greater than 0. - if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG)) - { - retval = true; - // Send unescaped message, see EXT-6353. - std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); - send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); - } - else - { - retval = false; - // Tell us this is an unsupported SLurl. - } - } - return retval; - } -}; - -// Creating the object registers with the dispatcher. -LLChatCommandHandler gChatHandler; diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h deleted file mode 100644 index c6a2637e8f..0000000000 --- a/indra/newview/llnearbychat.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @file llnearbychat.h - * @brief LLNearbyChat class definition - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLNEARBYCHAT_H -#define LL_LLNEARBYCHAT_H - -#include "llimconversation.h" -#include "llcombobox.h" -#include "llgesturemgr.h" -#include "llchat.h" -#include "llvoiceclient.h" -#include "lloutputmonitorctrl.h" -#include "llspeakers.h" -#include "llscrollbar.h" -#include "llviewerchat.h" -#include "llpanel.h" - -class LLResizeBar; - -class LLNearbyChat - : public LLIMConversation -{ -public: - // constructor for inline chat-bars (e.g. hosted in chat history window) - LLNearbyChat(const LLSD& key = LLSD(LLUUID())); - ~LLNearbyChat() {} - - static LLNearbyChat* buildFloater(const LLSD& key); - - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void onClose(bool app_quitting); - /*virtual*/ void setVisible(BOOL visible); - - void loadHistory(); - void reloadMessages(); - void removeScreenChat(); - - void addToHost(); - void show(); - bool isChatVisible() const; - - /** @param archive true - to save a message to the chat history log */ - void addMessage (const LLChat& message,bool archive = true, const LLSD &args = LLSD()); - void onNearbyChatContextMenuItemClicked(const LLSD& userdata); - bool onNearbyChatCheckContextMenuItem(const LLSD& userdata); - - LLChatEntry* getChatBox() { return mInputEditor; } - - std::string getCurrentChat(); - - virtual BOOL handleKeyHere( KEY key, MASK mask ); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - - 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); - - static bool isWordsName(const std::string& name); - - void showHistory(); - -protected: - static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); - static void onChatBoxKeystroke(LLTextEditor* caller, void* userdata); - static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); - void onChatBoxFocusReceived(); - - void sendChat( EChatType type ); - void onChatBoxCommit(); - void onChatFontChange(LLFontGL* fontp); - - /*virtual*/ void onTearOffClicked(); - /*virtual*/ void onClickCloseBtn(); - - static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); - EChatType processChatTypeTriggers(EChatType type, std::string &str); - - void displaySpeakingIndicator(); - - // Which non-zero channel did we last chat on? - static S32 sLastSpecialChatChannel; - - LLOutputMonitorCtrl* mOutputMonitor; - LLLocalSpeakerMgr* mSpeakerMgr; - - S32 mExpandedHeight; - -private: - - void onNearbySpeakers (); - - /*virtual*/ void refresh(); - - LLHandle<LLView> mPopupMenuHandle; - std::vector<LLChat> mMessageArchive; - -}; - -#endif diff --git a/indra/newview/llnearbychatbarlistener.cpp b/indra/newview/llnearbychatbarlistener.cpp deleted file mode 100644 index 61815d1864..0000000000 --- a/indra/newview/llnearbychatbarlistener.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file llnearbychatbarlistener.cpp - * @author Dave Simmons - * @date 2011-03-15 - * @brief Implementation for LLNearbyChatBarListener. - * - * $LicenseInfo:firstyear=2011&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2011, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llnearbychatbarlistener.h" -#include "llnearbychat.h" - -#include "llagent.h" -#include "llchat.h" - - - -LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChat & chatbar) - : LLEventAPI("LLChatBar", - "LLChatBar listener to (e.g.) sendChat, etc."), - mChatbar(chatbar) -{ - add("sendChat", - "Send chat to the simulator:\n" - "[\"message\"] chat message text [required]\n" - "[\"channel\"] chat channel number [default = 0]\n" - "[\"type\"] chat type \"whisper\", \"normal\", \"shout\" [default = \"normal\"]", - &LLNearbyChatBarListener::sendChat); -} - - -// "sendChat" command -void LLNearbyChatBarListener::sendChat(LLSD const & chat_data) const -{ - // Extract the data - std::string chat_text = chat_data["message"].asString(); - - S32 channel = 0; - if (chat_data.has("channel")) - { - channel = chat_data["channel"].asInteger(); - if (channel < 0 || channel >= CHAT_CHANNEL_DEBUG) - { // Use 0 up to (but not including) CHAT_CHANNEL_DEBUG - channel = 0; - } - } - - EChatType type_o_chat = CHAT_TYPE_NORMAL; - if (chat_data.has("type")) - { - std::string type_string = chat_data["type"].asString(); - if (type_string == "whisper") - { - type_o_chat = CHAT_TYPE_WHISPER; - } - else if (type_string == "shout") - { - type_o_chat = CHAT_TYPE_SHOUT; - } - } - - // Have to prepend /42 style channel numbers - std::string chat_to_send; - if (channel == 0) - { - chat_to_send = chat_text; - } - else - { - chat_to_send += "/"; - chat_to_send += chat_data["channel"].asString(); - chat_to_send += " "; - chat_to_send += chat_text; - } - - // Send it as if it was typed in - mChatbar.sendChatFromViewer(chat_to_send, type_o_chat, (BOOL)(channel == 0)); -} - diff --git a/indra/newview/llnearbychatbarlistener.h b/indra/newview/llnearbychatbarlistener.h deleted file mode 100644 index 0537275424..0000000000 --- a/indra/newview/llnearbychatbarlistener.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @file llnearbychatbarlistener.h - * @author Dave Simmons - * @date 2011-03-15 - * @brief Class definition for LLNearbyChatBarListener. - * - * $LicenseInfo:firstyear=2011&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2011, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - - -#ifndef LL_LLNEARBYCHATBARLISTENER_H -#define LL_LLNEARBYCHATBARLISTENER_H - -#include "lleventapi.h" - -class LLSD; -class LLNearbyChat; - -class LLNearbyChatBarListener : public LLEventAPI -{ -public: - LLNearbyChatBarListener(LLNearbyChat & chatbar); - -private: - void sendChat(LLSD const & chat_data) const; - - LLNearbyChat & mChatbar; -}; - -#endif // LL_LLNEARBYCHATBARLISTENER_H - diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp deleted file mode 100644 index 1494d9d6ee..0000000000 --- a/indra/newview/llnearbychathandler.cpp +++ /dev/null @@ -1,630 +0,0 @@ -/** - * @file LLNearbyChatHandler.cpp - * @brief Nearby chat chat managment - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llagentdata.h" // for gAgentID -#include "llnearbychathandler.h" - -#include "llchatitemscontainerctrl.h" -#include "llfirstuse.h" -#include "llfloaterscriptdebug.h" -#include "llhints.h" -#include "llnearbychat.h" -#include "llrecentpeople.h" - -#include "llviewercontrol.h" - -#include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance -#include "llviewerwindow.h"//for screen channel position -#include "llnearbychat.h" -#include "llrootview.h" -#include "lllayoutstack.h" - -//add LLNearbyChatHandler to LLNotificationsUI namespace -using namespace LLNotificationsUI; - -static LLNearbyChatToastPanel* createToastPanel() -{ - LLNearbyChatToastPanel* item = LLNearbyChatToastPanel::createInstance(); - return item; -} - - -//----------------------------------------------------------------------------------------------- -//LLNearbyChatScreenChannel -//----------------------------------------------------------------------------------------------- - -class LLNearbyChatScreenChannel: public LLScreenChannelBase -{ - LOG_CLASS(LLNearbyChatScreenChannel); -public: - typedef std::vector<LLHandle<LLToast> > toast_vec_t; - typedef std::list<LLHandle<LLToast> > toast_list_t; - - LLNearbyChatScreenChannel(const Params& p) - : LLScreenChannelBase(p) - { - mStopProcessing = false; - - LLControlVariable* ctrl = gSavedSettings.getControl("NearbyToastLifeTime").get(); - if (ctrl) - { - ctrl->getSignal()->connect(boost::bind(&LLNearbyChatScreenChannel::updateToastsLifetime, this)); - } - - ctrl = gSavedSettings.getControl("NearbyToastFadingTime").get(); - if (ctrl) - { - ctrl->getSignal()->connect(boost::bind(&LLNearbyChatScreenChannel::updateToastFadingTime, this)); - } - } - - void addChat (LLSD& chat); - void arrangeToasts (); - - typedef boost::function<LLNearbyChatToastPanel* (void )> create_toast_panel_callback_t; - void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;} - - void onToastDestroyed (LLToast* toast, bool app_quitting); - void onToastFade (LLToast* toast); - - void redrawToasts() - { - arrangeToasts(); - } - - // hide all toasts from screen, but not remove them from a channel - // removes all toasts from a channel - virtual void removeToastsFromChannel() - { - for(toast_vec_t::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it) - { - addToToastPool(it->get()); - } - m_active_toasts.clear(); - }; - - virtual void deleteAllChildren() - { - LL_DEBUGS("NearbyChat") << "Clearing toast pool" << llendl; - m_toast_pool.clear(); - m_active_toasts.clear(); - LLScreenChannelBase::deleteAllChildren(); - } - -protected: - void deactivateToast(LLToast* toast); - void addToToastPool(LLToast* toast) - { - if (!toast) return; - LL_DEBUGS("NearbyChat") << "Pooling toast" << llendl; - toast->setVisible(FALSE); - toast->stopTimer(); - toast->setIsHidden(true); - - // Nearby chat toasts that are hidden, not destroyed. They are collected to the toast pool, so that - // they can be used next time, this is done for performance. But if the toast lifetime was changed - // (from preferences floater (STORY-36)) while it was shown (at this moment toast isn't in the pool yet) - // changes don't take affect. - // So toast's lifetime should be updated each time it's added to the pool. Otherwise viewer would have - // to be restarted so that changes take effect. - toast->setLifetime(gSavedSettings.getS32("NearbyToastLifeTime")); - toast->setFadingTime(gSavedSettings.getS32("NearbyToastFadingTime")); - m_toast_pool.push_back(toast->getHandle()); - } - - void createOverflowToast(S32 bottom, F32 timer); - - void updateToastsLifetime(); - - void updateToastFadingTime(); - - create_toast_panel_callback_t m_create_toast_panel_callback_t; - - bool createPoolToast(); - - toast_vec_t m_active_toasts; - toast_list_t m_toast_pool; - - bool mStopProcessing; - bool mChannelRect; -}; - - - -//----------------------------------------------------------------------------------------------- -// LLNearbyChatToast -//----------------------------------------------------------------------------------------------- - -// We're deriving from LLToast to be able to override onClose() -// in order to handle closing nearby chat toasts properly. -class LLNearbyChatToast : public LLToast -{ - LOG_CLASS(LLNearbyChatToast); -public: - LLNearbyChatToast(const LLToast::Params& p, LLNearbyChatScreenChannel* nc_channelp) - : LLToast(p), - mNearbyChatScreenChannelp(nc_channelp) - { - } - - /*virtual*/ void onClose(bool app_quitting); - -private: - LLNearbyChatScreenChannel* mNearbyChatScreenChannelp; -}; - -//----------------------------------------------------------------------------------------------- -// LLNearbyChatScreenChannel -//----------------------------------------------------------------------------------------------- - -void LLNearbyChatScreenChannel::deactivateToast(LLToast* toast) -{ - toast_vec_t::iterator pos = std::find(m_active_toasts.begin(), m_active_toasts.end(), toast->getHandle()); - - if (pos == m_active_toasts.end()) - { - llassert(pos == m_active_toasts.end()); - return; - } - - LL_DEBUGS("NearbyChat") << "Deactivating toast" << llendl; - m_active_toasts.erase(pos); -} - -void LLNearbyChatScreenChannel::createOverflowToast(S32 bottom, F32 timer) -{ - //we don't need overflow toast in nearby chat -} - -void LLNearbyChatScreenChannel::onToastDestroyed(LLToast* toast, bool app_quitting) -{ - LL_DEBUGS("NearbyChat") << "Toast destroyed (app_quitting=" << app_quitting << ")" << llendl; - - if (app_quitting) - { - // Viewer is quitting. - // Immediately stop processing chat messages (EXT-1419). - mStopProcessing = true; -} - else - { - // The toast is being closed by user (STORM-192). - // Remove it from the list of active toasts to prevent - // further references to the invalid pointer. - deactivateToast(toast); - } -} - -void LLNearbyChatScreenChannel::onToastFade(LLToast* toast) -{ - LL_DEBUGS("NearbyChat") << "Toast fading" << llendl; - - //fade mean we put toast to toast pool - if(!toast) - return; - - deactivateToast(toast); - - addToToastPool(toast); - - arrangeToasts(); -} - -void LLNearbyChatScreenChannel::updateToastsLifetime() -{ - S32 seconds = gSavedSettings.getS32("NearbyToastLifeTime"); - toast_list_t::iterator it; - - for(it = m_toast_pool.begin(); it != m_toast_pool.end(); ++it) - { - (*it).get()->setLifetime(seconds); - } -} - -void LLNearbyChatScreenChannel::updateToastFadingTime() -{ - S32 seconds = gSavedSettings.getS32("NearbyToastFadingTime"); - toast_list_t::iterator it; - - for(it = m_toast_pool.begin(); it != m_toast_pool.end(); ++it) - { - (*it).get()->setFadingTime(seconds); - } -} - -bool LLNearbyChatScreenChannel::createPoolToast() -{ - LLNearbyChatToastPanel* panel= m_create_toast_panel_callback_t(); - if(!panel) - return false; - - LLToast::Params p; - p.panel = panel; - p.lifetime_secs = gSavedSettings.getS32("NearbyToastLifeTime"); - p.fading_time_secs = gSavedSettings.getS32("NearbyToastFadingTime"); - - LLToast* toast = new LLNearbyChatToast(p, this); - - - toast->setOnFadeCallback(boost::bind(&LLNearbyChatScreenChannel::onToastFade, this, _1)); - - // If the toast gets somehow prematurely destroyed, deactivate it to prevent crash (STORM-1352). - toast->setOnToastDestroyedCallback(boost::bind(&LLNearbyChatScreenChannel::onToastDestroyed, this, _1, false)); - - LL_DEBUGS("NearbyChat") << "Creating and pooling toast" << llendl; - m_toast_pool.push_back(toast->getHandle()); - return true; -} - -void LLNearbyChatScreenChannel::addChat(LLSD& chat) -{ - //look in pool. if there is any message - if(mStopProcessing) - return; - - /* - find last toast and check ID - */ - - if(m_active_toasts.size()) - { - LLUUID fromID = chat["from_id"].asUUID(); // agent id or object id - std::string from = chat["from"].asString(); - LLToast* toast = m_active_toasts[0].get(); - if (toast) - { - LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel()); - - if(panel && panel->messageID() == fromID && panel->getFromName() == from && panel->canAddText()) - { - panel->addMessage(chat); - toast->reshapeToPanel(); - toast->startTimer(); - - arrangeToasts(); - return; - } - } - } - - - - if(m_toast_pool.empty()) - { - //"pool" is empty - create one more panel - LL_DEBUGS("NearbyChat") << "Empty pool" << llendl; - if(!createPoolToast())//created toast will go to pool. so next call will find it - return; - addChat(chat); - return; - } - - int chat_type = chat["chat_type"].asInteger(); - - if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG)) - { - if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) - return; - if(gSavedSettings.getS32("ShowScriptErrorsLocation")== 1) - return; - } - - - //take 1st element from pool, (re)initialize it, put it in active toasts - - LL_DEBUGS("NearbyChat") << "Getting toast from pool" << llendl; - LLToast* toast = m_toast_pool.back().get(); - - m_toast_pool.pop_back(); - - - LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel()); - if(!panel) - return; - panel->init(chat); - - toast->reshapeToPanel(); - toast->startTimer(); - - m_active_toasts.push_back(toast->getHandle()); - - arrangeToasts(); -} - -static bool sort_toasts_predicate(LLHandle<LLToast> first, LLHandle<LLToast> second) -{ - if (!first.get() || !second.get()) return false; // STORM-1352 - - F32 v1 = first.get()->getTimeLeftToLive(); - F32 v2 = second.get()->getTimeLeftToLive(); - return v1 > v2; -} - -void LLNearbyChatScreenChannel::arrangeToasts() -{ - if(mStopProcessing || isHovering()) - return; - - if (mFloaterSnapRegion == NULL) - { - mFloaterSnapRegion = gViewerWindow->getRootView()->getChildView("floater_snap_region"); - } - - if (!getParent()) - { - // connect to floater snap region just to get resize events, we don't care about being a proper widget - mFloaterSnapRegion->addChild(this); - setFollows(FOLLOWS_ALL); - } - - LLRect toast_rect; - updateRect(); - - LLRect channel_rect; - mFloaterSnapRegion->localRectToOtherView(mFloaterSnapRegion->getLocalRect(), &channel_rect, gFloaterView); - channel_rect.mLeft += 10; - channel_rect.mRight = channel_rect.mLeft + 300; - - S32 channel_bottom = channel_rect.mBottom; - - S32 bottom = channel_bottom + 80; - S32 margin = gSavedSettings.getS32("ToastGap"); - - //sort active toasts - std::sort(m_active_toasts.begin(),m_active_toasts.end(),sort_toasts_predicate); - - //calc max visible item and hide other toasts. - - for(toast_vec_t::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it) - { - LLToast* toast = it->get(); - if (!toast) - { - llwarns << "NULL found in the active chat toasts list!" << llendl; - continue; - } - - S32 toast_top = bottom + toast->getRect().getHeight() + margin; - - if(toast_top > channel_rect.getHeight()) - { - while(it!=m_active_toasts.end()) - { - addToToastPool(it->get()); - it=m_active_toasts.erase(it); - } - break; - } - - toast_rect = toast->getRect(); - toast_rect.setLeftTopAndSize(channel_rect.mLeft , bottom + toast_rect.getHeight(), toast_rect.getWidth() ,toast_rect.getHeight()); - - toast->setRect(toast_rect); - bottom += toast_rect.getHeight() - toast->getTopPad() + margin; - } - - // use reverse order to provide correct z-order and avoid toast blinking - - for(toast_vec_t::reverse_iterator it = m_active_toasts.rbegin(); it != m_active_toasts.rend(); ++it) - { - LLToast* toast = it->get(); - if (toast) - { - toast->setIsHidden(false); - toast->setVisible(TRUE); - } - } - -} - - - -//----------------------------------------------------------------------------------------------- -//LLNearbyChatHandler -//----------------------------------------------------------------------------------------------- -boost::scoped_ptr<LLEventPump> LLNearbyChatHandler::sChatWatcher(new LLEventStream("LLChat")); - -LLNearbyChatHandler::LLNearbyChatHandler() -{ - // Getting a Channel for our notifications - LLNearbyChatScreenChannel::Params p; - p.id = LLUUID(gSavedSettings.getString("NearByChatChannelUUID")); - LLNearbyChatScreenChannel* channel = new LLNearbyChatScreenChannel(p); - - LLNearbyChatScreenChannel::create_toast_panel_callback_t callback = createToastPanel; - - channel->setCreatePanelCallback(callback); - - LLChannelManager::getInstance()->addChannel(channel); - - mChannel = channel->getHandle(); -} - -LLNearbyChatHandler::~LLNearbyChatHandler() -{ -} - - -void LLNearbyChatHandler::initChannel() -{ - //LLRect snap_rect = gFloaterView->getSnapRect(); - //mChannel->init(snap_rect.mLeft, snap_rect.mLeft + 200); -} - - - -void LLNearbyChatHandler::processChat(const LLChat& chat_msg, - const LLSD &args) -{ - if(chat_msg.mMuted == TRUE) - return; - - if(chat_msg.mText.empty()) - return;//don't process empty messages - - LLFloaterReg::getInstance("im_container"); - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); - - // Build notification data - LLSD chat; - chat["message"] = chat_msg.mText; - chat["from"] = chat_msg.mFromName; - chat["from_id"] = chat_msg.mFromID; - chat["time"] = chat_msg.mTime; - chat["source"] = (S32)chat_msg.mSourceType; - chat["chat_type"] = (S32)chat_msg.mChatType; - chat["chat_style"] = (S32)chat_msg.mChatStyle; - // Pass sender info so that it can be rendered properly (STORM-1021). - chat["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args); - - if (chat_msg.mChatType == CHAT_TYPE_DIRECT && - chat_msg.mText.length() > 0 && - chat_msg.mText[0] == '@') - { - // Send event on to LLEventStream and exit - sChatWatcher->post(chat); - return; - } - - // don't show toast and add message to chat history on receive debug message - // with disabled setting showing script errors or enabled setting to show script - // errors in separate window. - if (chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG) - { - if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) - return; - - // don't process debug messages from not owned objects, see EXT-7762 - if (gAgentID != chat_msg.mOwnerID) - { - return; - } - - if (gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)// show error in window //("ScriptErrorsAsChat")) - { - - LLColor4 txt_color; - - LLViewerChat::getChatColor(chat_msg,txt_color); - - LLFloaterScriptDebug::addScriptLine(chat_msg.mText, - chat_msg.mFromName, - txt_color, - chat_msg.mFromID); - return; - } - } - - nearby_chat->addMessage(chat_msg, true, args); - - if(chat_msg.mSourceType == CHAT_SOURCE_AGENT - && chat_msg.mFromID.notNull() - && chat_msg.mFromID != gAgentID) - { - LLFirstUse::otherAvatarChatFirst(); - - // Add sender to the recent people list. - LLRecentPeople::instance().add(chat_msg.mFromID); - - } - - // Send event on to LLEventStream - sChatWatcher->post(chat); - - if( nearby_chat->isInVisibleChain() - || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT - && gSavedSettings.getBOOL("UseChatBubbles") ) - || mChannel.isDead() - || !mChannel.get()->getShowToasts() ) // to prevent toasts in Do Not Disturb mode - return;//no need in toast if chat is visible or if bubble chat is enabled - - // arrange a channel on a screen - if(!mChannel.get()->getVisible()) - { - initChannel(); - } - - /* - //comment all this due to EXT-4432 - ..may clean up after some time... - - //only messages from AGENTS - if(CHAT_SOURCE_OBJECT == chat_msg.mSourceType) - { - if(chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG) - return;//ok for now we don't skip messeges from object, so skip only debug messages - } - */ - - LLNearbyChatScreenChannel* channel = dynamic_cast<LLNearbyChatScreenChannel*>(mChannel.get()); - - if(channel) - { - // Handle IRC styled messages. - std::string toast_msg; - if (chat_msg.mChatStyle == CHAT_STYLE_IRC) - { - if (!chat_msg.mFromName.empty()) - { - toast_msg += chat_msg.mFromName; - } - toast_msg += chat_msg.mText.substr(3); - } - else - { - toast_msg = chat_msg.mText; - } - - // Add a nearby chat toast. - LLUUID id; - id.generate(); - chat["id"] = id; - std::string r_color_name = "White"; - F32 r_color_alpha = 1.0f; - LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha); - - chat["text_color"] = r_color_name; - chat["color_alpha"] = r_color_alpha; - chat["font_size"] = (S32)LLViewerChat::getChatFontSize() ; - chat["message"] = toast_msg; - channel->addChat(chat); - } -} - - -//----------------------------------------------------------------------------------------------- -// LLNearbyChatToast -//----------------------------------------------------------------------------------------------- - -// virtual -void LLNearbyChatToast::onClose(bool app_quitting) -{ - mNearbyChatScreenChannelp->onToastDestroyed(this, app_quitting); -} - -// EOF diff --git a/indra/newview/llnearbychathandler.h b/indra/newview/llnearbychathandler.h deleted file mode 100644 index a5034ac1cb..0000000000 --- a/indra/newview/llnearbychathandler.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @file llnearbychathandler.h - * @brief nearby chat notify - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLNEARBYCHATHANDLER_H -#define LL_LLNEARBYCHATHANDLER_H - -#include "llnotificationhandler.h" - -class LLEventPump; - -//add LLNearbyChatHandler to LLNotificationsUI namespace -namespace LLNotificationsUI{ - -class LLNearbyChatHandler : public LLChatHandler -{ -public: - LLNearbyChatHandler(); - virtual ~LLNearbyChatHandler(); - - - virtual void processChat(const LLChat& chat_msg, const LLSD &args); - -protected: - virtual void initChannel(); - - static boost::scoped_ptr<LLEventPump> sChatWatcher; -}; - -} - -#endif /* LL_LLNEARBYCHATHANDLER_H */ diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 0899625242..4bded6ab30 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -36,7 +36,7 @@ #include "llinstantmessage.h" #include "llnotificationptr.h" -class LLIMFloater; +class LLFloaterIMSession; namespace LLNotificationsUI { diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index b4e8927879..7f1216ff40 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -34,9 +34,9 @@ #include "llurlaction.h" #include "llagent.h" -#include "llimfloater.h" +#include "llfloaterimsession.h" #include "llimview.h" -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" #include "llnotificationhandler.h" using namespace LLNotificationsUI; @@ -52,7 +52,7 @@ bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) LLUUID from_id = notification->getPayload()["from_id"]; LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); - LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); + LLFloaterIMSession* im_floater = LLFloaterReg::findTypedInstance<LLFloaterIMSession>("impanel", session_id); if (im_floater != NULL) { @@ -164,7 +164,7 @@ void LLHandlerUtil::logGroupNoticeToIMGroup( // static void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type) { - LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); if (nearby_chat) { LLChat chat_msg(notification->getMessage()); @@ -244,7 +244,7 @@ void LLHandlerUtil::addNotifPanelToIM(const LLNotificationPtr& notification) // static void LLHandlerUtil::updateIMFLoaterMesages(const LLUUID& session_id) { - LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); + LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(session_id); if (im_floater != NULL && im_floater->getVisible()) { im_floater->updateMessages(); diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 2862ad6962..56f13802e3 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -31,7 +31,7 @@ #include "llnotificationmanager.h" -#include "llnearbychathandler.h" +#include "llfloaterimnearbychathandler.h" #include "llnotifications.h" #include <boost/bind.hpp> @@ -64,7 +64,7 @@ void LLNotificationManager::init() mChannels.push_back(new LLOutboxNotification()); mChannels.push_back(new LLIMHandler()); - mChatHandler = boost::shared_ptr<LLNearbyChatHandler>(new LLNearbyChatHandler()); + mChatHandler = boost::shared_ptr<LLFloaterIMNearbyChatHandler>(new LLFloaterIMNearbyChatHandler()); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index c8afdf9e46..f37c6b833c 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -60,7 +60,7 @@ public: void onChat(const LLChat& msg, const LLSD &args); private: - boost::shared_ptr<class LLNearbyChatHandler> mChatHandler; + boost::shared_ptr<class LLFloaterIMNearbyChatHandler> mChatHandler; std::vector<LLNotificationChannelPtr> mChannels; }; diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index a293e6acb6..faa67b5ea4 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -28,8 +28,8 @@ #include "llviewerprecompiledheaders.h" // must be first include #include "llfloaterreg.h" -#include "llnearbychat.h" -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" +#include "llfloaterimnearbychat.h" #include "llnotificationhandler.h" #include "llnotifications.h" #include "lltoastnotifypanel.h" @@ -85,7 +85,7 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); // don't show toast if Nearby Chat is opened - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); if (nearby_chat->isChatVisible()) { return false; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 9a4d1166db..9f89b5f809 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -28,7 +28,7 @@ #include "llavatarnamecache.h" #include "llimview.h" -#include "llimfloatercontainer.h" +#include "llfloaterimcontainer.h" #include "llparticipantlist.h" #include "llspeakers.h" @@ -316,7 +316,7 @@ bool LLParticipantList::onSpeakerUpdateEvent(LLPointer<LLOldEvents::LLEvent> eve if ( evt_data.has("id") ) { LLUUID participant_id = evt_data["id"]; - LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); + LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); if (im_box) { im_box->setTimeNow(mUUID,participant_id); @@ -345,7 +345,7 @@ bool LLParticipantList::onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> e mModeratorList.erase(id); } } - // *TODO : do we have to fire an event so that LLIMConversation::refreshConversation() gets called + // *TODO : do we have to fire an event so that LLFloaterIMSessionTab::refreshConversation() gets called } } return true; diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index a4a0198305..3bcf36ffde 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -39,7 +39,7 @@ #include "lldockablefloater.h" #include "llsyswellwindow.h" -#include "llimfloater.h" +#include "llfloaterimsession.h" #include "llscriptfloater.h" #include "llrootview.h" diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 6f98be1cb8..dc12192697 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -41,7 +41,7 @@ #include "lltoastscripttextbox.h" #include "lltrans.h" #include "llviewerwindow.h" -#include "llimfloater.h" +#include "llfloaterimsession.h" ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index c827b39d0e..8932d12e20 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -54,7 +54,7 @@ #include "llfloaterreg.h" #include "llfocusmgr.h" #include "llhttpsender.h" -#include "llimfloater.h" +#include "llfloaterimsession.h" #include "lllocationhistory.h" #include "llimageworker.h" @@ -63,8 +63,8 @@ #include "llmemorystream.h" #include "llmessageconfig.h" #include "llmoveview.h" -#include "llimfloatercontainer.h" -#include "llnearbychat.h" +#include "llfloaterimcontainer.h" +#include "llfloaterimnearbychat.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llteleporthistory.h" @@ -1384,7 +1384,7 @@ bool idle_startup() // create a container's instance for start a controlling conversation windows // by the voice's events - LLIMFloaterContainer::getInstance(); + LLFloaterIMContainer::getInstance(); // *Note: this is where gWorldMap used to be initialized. diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 4a49922656..65b4a3a44c 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -40,7 +40,7 @@ #include "lltrans.h" #include "llnotificationsutil.h" #include "llviewermessage.h" -#include "llimfloater.h" +#include "llfloaterimsession.h" const S32 BOTTOM_PAD = VPAD * 3; const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index b99d04abae..c6b28b9e5e 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -71,7 +71,7 @@ #include "llfloatermediasettings.h" #include "llfloaterhud.h" #include "llfloaterimagepreview.h" -#include "llimfloater.h" +#include "llfloaterimsession.h" #include "llfloaterinspect.h" #include "llfloaterinventory.h" #include "llfloaterjoystick.h" @@ -120,14 +120,14 @@ #include "llfloaterwhitelistentry.h" #include "llfloaterwindowsize.h" #include "llfloaterworldmap.h" -#include "llimfloatercontainer.h" +#include "llfloaterimcontainer.h" #include "llinspectavatar.h" #include "llinspectgroup.h" #include "llinspectobject.h" #include "llinspectremoteobject.h" #include "llinspecttoast.h" #include "llmoveview.h" -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" #include "llpanelblockedlist.h" #include "llpanelclassified.h" #include "llpreviewanim.h" @@ -193,7 +193,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>); LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatVoiceVolume>); - LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLNearbyChat::buildFloater); + LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterIMNearbyChat::buildFloater); LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>); LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>); @@ -217,8 +217,8 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHelpBrowser>); LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>); - LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloater>); - LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloaterContainer>); + LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterIMSession>); + LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterIMContainer>); LLFloaterReg::add("im_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMWellWindow>); LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>); LLFloaterReg::add("inventory", "floater_my_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); diff --git a/indra/newview/llviewergesture.cpp b/indra/newview/llviewergesture.cpp index 71608b5280..3f35a5001d 100644 --- a/indra/newview/llviewergesture.cpp +++ b/indra/newview/llviewergesture.cpp @@ -41,7 +41,7 @@ #include "llviewermessage.h" // send_guid_sound_trigger #include "llviewernetwork.h" #include "llagent.h" -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" // Globals LLViewerGestureList gGestureList; @@ -131,7 +131,7 @@ void LLViewerGesture::doTrigger( BOOL send_chat ) { // Don't play nodding animation, since that might not blend // with the gesture animation. - (LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))-> + (LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))-> sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); } } diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index f8e988bc0c..4ecdc31e21 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -32,7 +32,7 @@ #include "llmath.h" #include "llagent.h" #include "llagentcamera.h" -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" #include "llviewercontrol.h" #include "llfocusmgr.h" #include "llmorphview.h" @@ -535,7 +535,7 @@ void stop_moving( EKeystate s ) void start_chat( EKeystate s ) { // start chat - LLNearbyChat::startChat(NULL); + LLFloaterIMNearbyChat::startChat(NULL); } void start_gesture( EKeystate s ) @@ -544,15 +544,15 @@ void start_gesture( EKeystate s ) if (KEYSTATE_UP == s && ! (focus_ctrlp && focus_ctrlp->acceptsTextInput())) { - if ((LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"))->getCurrentChat().empty()) + if ((LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->getCurrentChat().empty()) { // No existing chat in chat editor, insert '/' - LLNearbyChat::startChat("/"); + LLFloaterIMNearbyChat::startChat("/"); } else { // Don't overwrite existing text in chat editor - LLNearbyChat::startChat(NULL); + LLFloaterIMNearbyChat::startChat(NULL); } } } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 1ddfc51f27..47249fad70 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -68,7 +68,7 @@ #include "llinventoryfunctions.h" #include "llinventoryobserver.h" #include "llinventorypanel.h" -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llpanelgrouplandmoney.h" @@ -2295,7 +2295,7 @@ void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string m // Treat like a system message and put in chat history. chat.mText = av_name.getCompleteName() + ": " + message; - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); if (nearby_chat) { nearby_chat->addMessage(chat); @@ -2877,7 +2877,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Note: lie to Nearby Chat, pretending that this is NOT an IM, because // IMs from obejcts don't open IM sessions. - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat"); + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); if(!chat_from_system && nearby_chat) { chat.mOwnerID = from_id; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ee838b19b7..afc3e3965c 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -188,7 +188,7 @@ #include "llviewerjoystick.h" #include "llviewernetwork.h" #include "llpostprocess.h" -#include "llnearbychat.h" +#include "llfloaterimnearbychat.h" #include "llagentui.h" #include "llwearablelist.h" @@ -2496,7 +2496,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) return TRUE; } - LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat"); + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); // Traverses up the hierarchy if( keyboard_focus ) @@ -2574,7 +2574,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) LLFloaterReg::toggleInstanceOrBringToFront(name); } - LLChatEntry* chat_editor = LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")->getChatBox(); + LLChatEntry* chat_editor = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")->getChatBox(); if (chat_editor) { // passing NULL here, character will be added later when it is handled by character handler. -- cgit v1.2.3 From 828374749682a5febc6ebac81321e80dee11085e Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Mon, 12 Nov 2012 16:25:35 +0200 Subject: CHUI-386 FIXED Vertical scrollbar not fully showing in conversation message panel --- .../skins/default/xui/en/floater_im_session.xml | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index a889eb7933..1d74f1bc25 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -203,7 +203,7 @@ name="translate_chat_checkbox_lp" top_delta="0" visible="true" - width="230"> + width="210"> <check_box top="10" control_name="TranslateChat" @@ -217,7 +217,7 @@ </layout_panel> <layout_panel height="248" - width="230" + width="210" layout="topleft" follows="all" left_delta="0" @@ -227,17 +227,17 @@ user_resize="true" auto_resize="true" name="chat_holder"> - <chat_history - font="SansSerifSmall" - follows="all" - visible="true" - height="240" - name="chat_history" - parse_highlights="true" - parse_urls="true" - width="230" - left="5"> - </chat_history> + <chat_history + font="SansSerifSmall" + follows="all" + visible="true" + height="240" + name="chat_history" + parse_highlights="true" + parse_urls="true" + right="-5" + left="5"> + </chat_history> </layout_panel> </layout_stack> </panel> -- cgit v1.2.3 From 2813e49d198400a0f6416e01f720bdeb5f506144 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 9 Nov 2012 15:13:52 +0200 Subject: CHUI-362 WIP (Torn off conversation name is highlighted when selected in conversation list with different conversation showing in message panel): implemented method for a switch off tabs (switching to an invisible state) --- indra/llui/lltabcontainer.cpp | 11 +++++++++++ indra/llui/lltabcontainer.h | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index d0920685bf..c24eb2ee90 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1556,6 +1556,17 @@ BOOL LLTabContainer::setTab(S32 which) return is_visible; } + +void LLTabContainer::hideAllTabs() +{ + setCurrentPanelIndex(-1); + for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + { + (* iter)->mTabPanel->setVisible(FALSE); + } +} + + BOOL LLTabContainer::selectTabByName(const std::string& name) { LLPanel* panel = getPanelByName(name); diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index cebace2ceb..a9cdf22b16 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -188,10 +188,11 @@ public: void selectFirstTab(); void selectLastTab(); void selectNextTab(); - void selectPrevTab(); + void selectPrevTab(); BOOL selectTabPanel( LLPanel* child ); BOOL selectTab(S32 which); BOOL selectTabByName(const std::string& title); + void hideAllTabs(); BOOL getTabPanelFlashing(LLPanel* child); void setTabPanelFlashing(LLPanel* child, BOOL state); -- cgit v1.2.3 From 3d42133ecb7671d8284bc0309f8df9e6e7f2df9c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 9 Nov 2012 17:04:21 +0200 Subject: CHUI-362 WIP (Torn off conversation name is highlighted when selected in conversation list with different conversation showing in message panel): implemented the stub panel and a control of it's visibility --- indra/newview/llfloaterimcontainer.cpp | 12 +++++++ indra/newview/llfloaterimcontainer.h | 3 ++ indra/newview/llfloaterimsessiontab.cpp | 1 + .../skins/default/xui/en/floater_im_container.xml | 42 +++++++++++++++++++++- 4 files changed, 57 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 2789b78c2d..994a76189a 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -141,6 +141,8 @@ BOOL LLFloaterIMContainer::postBuild() // mTabContainer will be initialized in LLMultiFloater::addChild() setTabContainer(getChild<LLTabContainer>("im_box_tab_container")); + mStubPanel = getChild<LLPanel>("stub_panel"); + mStubTextBox = getChild<LLTextBox>("stub_textbox"); mConversationsStack = getChild<LLLayoutStack>("conversations_stack"); mConversationsPane = getChild<LLLayoutPanel>("conversations_layout_panel"); @@ -494,6 +496,16 @@ void LLFloaterIMContainer::tabClose() } } +void LLFloaterIMContainer::showStub(bool stub_is_visible) +{ + if (stub_is_visible) + { + mTabContainer->hideAllTabs(); + } + + mStubPanel->setVisible(stub_is_visible); +} + void LLFloaterIMContainer::setVisible(BOOL visible) { LLFloaterIMNearbyChat* nearby_chat; if (visible) diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index f65e946dad..a09cde60f5 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -71,6 +71,7 @@ public: BOOL selectConversationPair(const LLUUID& session_id, bool select_widget); /*virtual*/ void tabClose(); + void showStub(bool visible); static LLFloater* getCurrentVoiceFloater(); static LLFloaterIMContainer* findInstance(); @@ -146,6 +147,8 @@ private: void openNearbyChat(); LLButton* mExpandCollapseBtn; + LLPanel* mStubPanel; + LLTextBox* mStubTextBox; LLLayoutPanel* mMessagesPane; LLLayoutPanel* mConversationsPane; LLLayoutStack* mConversationsStack; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index c39319b373..3a1cc2880a 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -313,6 +313,7 @@ void LLFloaterIMSessionTab::onFocusReceived() if (container) { container->selectConversationPair(mSessionID, true); + container->showStub(! getHost()); } } diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 590ce45c33..e3db3d52ed 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -124,7 +124,47 @@ left="0" name="im_box_tab_container" top="0" - width="412"/> + width="412"> + <panel + follows="all" + layout="topleft" + name="stub_panel" + opaque="true" + top_pad="0" + left="0" + height="430" + width="412"> + <text + type="string" + clip_partial="false" + follows="left|top" + layout="topleft" + left="20" + right="-20" + name="stub_textbox_1" + top="10" + height="20" + valign="center" + wrap="true"> + This conversation is in a separate window. + </text> + <text + type="string" + clip_partial="false" + follows="left|top" + layout="topleft" + left="20" + right="-20" + name="stub_textbox_2" + top="40" + height="20" + valign="center" + parse_urls="false" + wrap="true"> + Bring it back. + </text> + </panel> + </panel_container> </layout_panel> </layout_stack> </multi_floater> -- cgit v1.2.3 From 5790565ec6a2885fbe494c04c687e98cabf514a6 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Fri, 9 Nov 2012 19:44:37 +0200 Subject: Additional fix for CHUI-473 --- indra/newview/llconversationview.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 3495d74191..295dd2ae6d 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -207,11 +207,11 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) { LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem()); LLUUID session_id = item? item->getUUID() : LLUUID(); - + BOOL result = LLFolderViewFolder::handleMouseDown(x, y, mask); (LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"))-> selectConversationPair(session_id, false); - return LLFolderViewFolder::handleMouseDown(x, y, mask); + return result; } // virtual @@ -240,7 +240,7 @@ void LLConversationViewSession::toggleOpen() { getParentFolder()->setSelection(this, true); } - + } } @@ -504,11 +504,11 @@ BOOL LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask ) item = dynamic_cast<LLConversationItem*>(session_widget->getViewModelItem()); } LLUUID session_id = item? item->getUUID() : LLUUID(); + BOOL result = LLFolderViewItem::handleMouseDown(x, y, mask); + (LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"))-> + selectConversationPair(session_id, false); - (LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"))-> - selectConversationPair(session_id, false); - - return LLFolderViewItem::handleMouseDown(x, y, mask); + return result; } S32 LLConversationViewParticipant::getLabelXPos() -- cgit v1.2.3 From 4f58b4088a469d907eb33f1e338569016ba4c1f1 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Fri, 9 Nov 2012 14:41:50 -0800 Subject: CHUI-517: Altering the behavior and copy of the main menu status choices. Busy has been replaced with Do Not Disturb. And both status options have been switched to be indicated with a check rather than alternating text. --- indra/newview/llagent.cpp | 18 +---------- indra/newview/llviewermenu.cpp | 25 +++++++++++---- indra/newview/llviewermenu.h | 2 -- indra/newview/skins/default/xui/en/menu_viewer.xml | 37 ++++++++++++++-------- indra/newview/skins/default/xui/en/strings.xml | 6 ---- 5 files changed, 44 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 9c3a7ac45b..d548ca8fb9 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1356,12 +1356,7 @@ void LLAgent::setAFK() { sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_START); setControlFlags(AGENT_CONTROL_AWAY | AGENT_CONTROL_STOP); - LL_INFOS("AFK") << "Setting Away" << LL_ENDL; gAwayTimer.start(); - if (gAFKMenu) - { - gAFKMenu->setLabel(LLTrans::getString("AvatarSetNotAway")); - } } } @@ -1380,11 +1375,6 @@ void LLAgent::clearAFK() { sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_STOP); clearControlFlags(AGENT_CONTROL_AWAY); - LL_INFOS("AFK") << "Clearing Away" << LL_ENDL; - if (gAFKMenu) - { - gAFKMenu->setLabel(LLTrans::getString("AvatarSetAway")); - } } } @@ -1402,13 +1392,7 @@ BOOL LLAgent::getAFK() const void LLAgent::setDoNotDisturb(bool pIsDotNotDisturb) { mIsDoNotDisturb = pIsDotNotDisturb; - EAnimRequest animRequest = (pIsDotNotDisturb ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); - - sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, animRequest); - if (gDoNotDisturbMenu) - { - gDoNotDisturbMenu->setLabel(LLTrans::getString((pIsDotNotDisturb ? "AvatarSetAvailable" : "AvatarSetDoNotDisturb"))); - } + sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, (pIsDotNotDisturb ? ANIM_REQUEST_START : ANIM_REQUEST_STOP)); LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(pIsDotNotDisturb); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index ac6110f84f..511807ec2f 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -178,9 +178,6 @@ LLContextMenu* gDetachPieMenu = NULL; LLContextMenu* gDetachScreenPieMenu = NULL; LLContextMenu* gDetachBodyPartPieMenus[8]; -LLMenuItemCallGL* gAFKMenu = NULL; -LLMenuItemCallGL* gDoNotDisturbMenu = NULL; - // // Local prototypes @@ -470,8 +467,6 @@ void init_menus() gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", upload_cost); gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", upload_cost); - gAFKMenu = gMenuBarView->getChild<LLMenuItemCallGL>("Set Away", TRUE); - gDoNotDisturbMenu = gMenuBarView->getChild<LLMenuItemCallGL>("set_do_not_disturb", TRUE); gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE); gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE); @@ -7843,6 +7838,22 @@ class LLViewCheckRenderType : public view_listener_t } }; +class LLViewStatusAway : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + return (gAgent.isInitialized() && gAgent.getAFK()); + } +}; + +class LLViewStatusDoNotDisturb : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + return (gAgent.isInitialized() && gAgent.isDoNotDisturb()); + } +}; + class LLViewShowHUDAttachments : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -8276,8 +8287,10 @@ void initialize_menus() view_listener_t::addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips"); view_listener_t::addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent"); view_listener_t::addMenu(new LLViewCheckRenderType(), "View.CheckRenderType"); + view_listener_t::addMenu(new LLViewStatusAway(), "View.Status.CheckAway"); + view_listener_t::addMenu(new LLViewStatusDoNotDisturb(), "View.Status.CheckDoNotDisturb"); view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments"); - + // Me > Movement view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying"); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index e8665a6ef6..139f898b76 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -187,8 +187,6 @@ extern LLContextMenu* gDetachPieMenu; extern LLContextMenu* gAttachBodyPartPieMenus[8]; extern LLContextMenu* gDetachBodyPartPieMenus[8]; -extern LLMenuItemCallGL* gAFKMenu; -extern LLMenuItemCallGL* gDoNotDisturbMenu; extern LLMenuItemCallGL* gMutePieMenu; extern LLMenuItemCallGL* gMuteObjectPieMenu; extern LLMenuItemCallGL* gBuyPassPieMenu; diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index f6a307d9d0..b1e3a2d41f 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -130,19 +130,22 @@ label="Status" name="Status" tear_off="true"> - <menu_item_call - label="Away" - name="Set Away"> - <menu_item_call.on_click + <menu_item_check + label="Away"> + <menu_item_check.on_check + function="View.Status.CheckAway" /> + <menu_item_check.on_click function="World.SetAway" /> - </menu_item_call> - <menu_item_call - label="Busy" - name="set_do_not_disturb"> - <menu_item_call.on_click + </menu_item_check> + <menu_item_check + label="Do Not Disturb"> + <menu_item_check.on_check + function="View.Status.CheckDoNotDisturb" /> + <menu_item_check.on_click function="World.SetDoNotDisturb"/> - </menu_item_call> - </menu> + </menu_item_check> + + </menu> <menu_item_separator/> @@ -254,8 +257,7 @@ parameter="speak" /> </menu_item_check> <menu_item_check - label="Conversations Log..." - name="ConversationsLog"> + label="Conversation Log..."> <menu_item_check.on_check function="Floater.Visible" parameter="conversation" /> @@ -318,6 +320,15 @@ function="SideTray.PanelPeopleTab" parameter="blocked_panel" /> </menu_item_call> + <menu_item_separator/> + <menu_item_check + label="Do Not Disturb"> + <menu_item_check.on_check + function="View.Status.CheckDoNotDisturb" /> + <menu_item_check.on_click + function="World.SetDoNotDisturb"/> + </menu_item_check> + </menu> <menu create_jump_keys="true" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 04b6326769..f873bfe6c7 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2074,12 +2074,6 @@ For AI Character: Get the closest navigable point to the point provided. </string> - <!-- Avatar busy/away mode --> - <string name="AvatarSetNotAway">Not Away</string> - <string name="AvatarSetAway">Away</string> - <string name="AvatarSetAvailable">Not Busy</string> - <string name="AvatarSetDoNotDisturb">Busy</string> - <!-- Wearable Types --> <string name="shape">Shape</string> <string name="skin">Skin</string> -- cgit v1.2.3 From 69f81d5bb6390ed4b3c766fc64605d6f15d5df31 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Fri, 9 Nov 2012 14:58:37 -0800 Subject: CHUI-517: Updating the do not disturb message automatically sent to other users when they attempt to contact a person in do not disturb mode. --- indra/newview/app_settings/settings_per_account.xml | 2 +- indra/newview/llviewermessage.cpp | 4 +--- indra/newview/skins/default/xui/en/strings.xml | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 8126e20b1b..ca22041671 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -20,7 +20,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing.</string> + <string>This resident has turned on 'Do Not Disturb' and will see your message later.</string> </map> <key>ConversationsExpandMessagePaneFirst</key> <map> diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 47249fad70..56c9f81259 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2941,9 +2941,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } else { - // TODO: after LLTrans hits release, get "busy response" into translatable file - buffer = llformat("%s (%s): %s", name.c_str(), "busy response", message.c_str()); - gIMMgr->addMessage(session_id, from_id, name, buffer); + gIMMgr->addMessage(session_id, from_id, name, message); } break; diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index f873bfe6c7..79ee83969b 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2520,7 +2520,7 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale <string name="PanelContentsNewScript">New Script</string> <!-- panel preferences general --> - <string name="DoNotDisturbModeResponseDefault">The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing.</string> + <string name="DoNotDisturbModeResponseDefault">This resident has turned on 'Do Not Disturb' and will see your message later.</string> <!-- Mute --> <string name="MuteByName">(By name)</string> -- cgit v1.2.3 From 873057a21aaa4e21d75998f604119024947ac773 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Fri, 9 Nov 2012 15:45:07 -0800 Subject: CHUI-517: Updating notification copy for Do Not Disturb mode. --- indra/newview/skins/default/xui/en/notifications.xml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 1c1642abac..d63c91a0e6 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3693,8 +3693,11 @@ Cannot offer friendship at this time. Please try again in a moment. icon="alert.tga" name="DoNotDisturbModeSet" type="alert"> -Busy mode is set. -Chat and instant messages will be hidden. Instant messages will get your Busy mode response. All teleportation offers will be declined. All inventory offers will go to your Trash. +Do Not Disturb is on. You will not be notified of incoming communications. + +- Other residents will receive your Do Not Disturb response (set in Preferences > General). +- Teleportation offers will be declined. +- Inventory offers will go to your Trash. <usetemplate ignoretext="I change my status to Do Not Disturb mode" name="okignore" @@ -5170,9 +5173,9 @@ Do you want to replace it with the selected object? label="Do Not Disturb Mode Warning" name="DoNotDisturbModePay" type="alert"> -You are in Busy Mode, which means you will not receive any items offered in exchange for this payment. +You have turned on Do Not Disturb. You will not receive any items offered in exchange for this payment. -Would you like to leave Busy Mode before completing this transaction? +Would you like to turn off Do Not Disturb before completing this transaction? <tag>confirm</tag> <form name="form"> <ignore name="ignore" -- cgit v1.2.3 From 312cb2ab61a20fe1e011e41e82bfae5f50fd7a84 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Fri, 9 Nov 2012 15:53:58 -0800 Subject: Cleaning up white-space in an xml file. --- .../default/xui/en/panel_preferences_chat.xml | 594 ++++++++++----------- 1 file changed, 294 insertions(+), 300 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 28434a670e..5524d0e4f0 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -1,151 +1,150 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel - border="true" - follows="left|top|right|bottom" - height="408" - label="Text Chat" - layout="topleft" - left="102" - name="chat" - top="1" - width="517"> + border="true" + follows="left|top|right|bottom" + height="408" + label="Text Chat" + layout="topleft" + left="102" + name="chat" + top="1" + width="517"> <panel - border="false" - follows="left|top" - height="90" - layout="topleft" - top="10" - left="13" - width="517"> + border="false" + follows="left|top" + height="90" + layout="topleft" + top="10" + left="13" + width="517"> <check_box - control_name="PlayTypingAnim" - height="16" - initial_value="true" - label="Play typing animation when chatting" - layout="topleft" - top="0" - name="play_typing_animation" - width="330" /> + control_name="PlayTypingAnim" + height="16" + initial_value="true" + label="Play typing animation when chatting" + layout="topleft" + top="0" + name="play_typing_animation" + width="330" /> <check_box - enabled="false" - height="16" - label="Email me IMs when I'm offline" - layout="topleft" - name="send_im_to_email" - top_pad="6" - width="330" /> + enabled="false" + height="16" + label="Email me IMs when I'm offline" + layout="topleft" + name="send_im_to_email" + top_pad="6" + width="330" /> <check_box - height="16" - label="Keep a conversation log and transcripts" - layout="topleft" - name="keep_convo_log_and_transcripts" - top_pad="6" - width="330" /> + height="16" + label="Keep a conversation log and transcripts" + layout="topleft" + name="keep_convo_log_and_transcripts" + top_pad="6" + width="330" /> <check_box - control_name="UseChatBubbles" - follows="left|top" - height="16" - label="Bubble Chat" - layout="topleft" - top_pad="6" - name="bubble_text_chat" - width="330" /> + control_name="UseChatBubbles" + follows="left|top" + height="16" + label="Bubble Chat" + layout="topleft" + top_pad="6" + name="bubble_text_chat" + width="330" /> <text - follows="left|top" - layout="topleft" - left="345" - height="12" - name="font_size" - width="120" - top="0"> + follows="left|top" + layout="topleft" + left="345" + height="12" + name="font_size" + width="120" + top="0"> Font size: </text> <radio_group - height="90" - layout="topleft" - left="352" - control_name="ChatFontSize" - name="chat_font_size" - top_pad="0" - width="50"> + height="90" + layout="topleft" + left="352" + control_name="ChatFontSize" + name="chat_font_size" + top_pad="0" + width="50"> <radio_item - height="16" - label="Small" - layout="topleft" - name="radio" - value="0" - top="10" - width="125" /> + height="16" + label="Small" + layout="topleft" + name="radio" + value="0" + top="10" + width="125" /> <radio_item - height="16" - label="Medium" - layout="topleft" - name="radio2" - value="1" - top_pad="6" - width="125" /> + height="16" + label="Medium" + layout="topleft" + name="radio2" + value="1" + top_pad="6" + width="125" /> <radio_item - height="16" - label="Large" - layout="topleft" - name="radio3" - value="2" - top_pad="6" - width="125" /> + height="16" + label="Large" + layout="topleft" + name="radio3" + value="2" + top_pad="6" + width="125" /> </radio_group> </panel> <panel - border="false" - follows="left|top" - height="193" - layout="topleft" - left="13" - width="517"> + border="false" + follows="left|top" + height="193" + layout="topleft" + left="13" + width="517"> <text - follows="left|top" - layout="topleft" - height="12" - name="notifications" - left="0" - width="120"> + follows="left|top" + layout="topleft" + height="12" + name="notifications" + left="0" + width="120"> Notifications: </text> <text - follows="left|top" - layout="topleft" - height="12" - name="friend_ims" - width="145" - left="0" - top_pad="15" - > + follows="left|top" + layout="topleft" + height="12" + name="friend_ims" + width="145" + left="0" + top_pad="15"> Friend IMs: </text> <combo_box - control_name="NotificationFriendIMOptions" - height="23" - layout="topleft" - left_pad="5" - top_delta="-6" - name="FriendIMOptions" - width="223"> + control_name="NotificationFriendIMOptions" + height="23" + layout="topleft" + left_pad="5" + top_delta="-6" + name="FriendIMOptions" + width="223"> <combo_box.item - label="Pop up the message" - name="0" - value="0"/> + label="Pop up the message" + name="0" + value="0"/> <combo_box.item - label="Flash toolbar button" - name="1" - value="1"/> + label="Flash toolbar button" + name="1" + value="1"/> <combo_box.item - label="None" - name="2" - value="2"/> + label="None" + name="2" + value="2"/> </combo_box> <text follows="left|top" @@ -154,244 +153,239 @@ name="non_friend_ims" width="145" left="0" - top_pad="15" - > + top_pad="15"> Non-friend IMs: </text> <combo_box - control_name="NotificationNonFriendIMOptions" - height="23" - layout="topleft" - left_pad="5" - top_delta="-6" - name="NonFriendIMOptions" - width="223"> + control_name="NotificationNonFriendIMOptions" + height="23" + layout="topleft" + left_pad="5" + top_delta="-6" + name="NonFriendIMOptions" + width="223"> <combo_box.item - label="Pop up the message" - name="0" - value="0"/> + label="Pop up the message" + name="0" + value="0"/> <combo_box.item - label="Flash toolbar button" - name="1" - value="1"/> + label="Flash toolbar button" + name="1" + value="1"/> <combo_box.item - label="None" - name="2" - value="2"/> + label="None" + name="2" + value="2"/> </combo_box> <text - follows="left|top" - layout="topleft" - left="0" - height="13" - name="conference_ims" - width="145" - top_pad="14" - > + follows="left|top" + layout="topleft" + left="0" + height="13" + name="conference_ims" + width="145" + top_pad="14"> Conference IMs: </text> <combo_box - control_name="NotificationConferenceIMOptions" - height="23" - layout="topleft" - left_pad="5" - top_delta="-6" - name="ConferenceIMOptions" - width="223"> + control_name="NotificationConferenceIMOptions" + height="23" + layout="topleft" + left_pad="5" + top_delta="-6" + name="ConferenceIMOptions" + width="223"> <combo_box.item - label="Pop up the message" - name="0" - value="0"/> + label="Pop up the message" + name="0" + value="0"/> <combo_box.item - label="Flash toolbar button" - name="1" - value="1"/> + label="Flash toolbar button" + name="1" + value="1"/> <combo_box.item - label="None" - name="2" - value="2"/> + label="None" + name="2" + value="2"/> </combo_box> <text - follows="left|top" - layout="topleft" - left="0" - height="13" - name="group_chat" - width="145" - top_pad="14" - > + follows="left|top" + layout="topleft" + left="0" + height="13" + name="group_chat" + width="145" + top_pad="14"> Group chat: </text> <combo_box - control_name="NotificationGroupChatOptions" - height="23" - layout="topleft" - left_pad="5" - top_delta="-6" - name="GroupChatOptions" - width="223"> + control_name="NotificationGroupChatOptions" + height="23" + layout="topleft" + left_pad="5" + top_delta="-6" + name="GroupChatOptions" + width="223"> <combo_box.item - label="Pop up the message" - name="0" - value="0"/> + label="Pop up the message" + name="0" + value="0"/> <combo_box.item - label="Flash toolbar button" - name="1" - value="1"/> + label="Flash toolbar button" + name="1" + value="1"/> <combo_box.item - label="None" - name="2" - value="2"/> + label="None" + name="2" + value="2"/> </combo_box> <text - follows="left|top" - layout="topleft" - left="0" - height="12" - name="nearby_chat" - width="145" - top_pad="14" - > + follows="left|top" + layout="topleft" + left="0" + height="12" + name="nearby_chat" + width="145" + top_pad="14"> Nearby chat: </text> <combo_box - control_name="NotificationNearbyChatOptions" - height="23" - layout="topleft" - left_pad="5" - top_delta="-6" - name="NearbyChatOptions" - width="223"> + control_name="NotificationNearbyChatOptions" + height="23" + layout="topleft" + left_pad="5" + top_delta="-6" + name="NearbyChatOptions" + width="223"> <combo_box.item - label="Pop up the message" - name="0" - value="0"/> + label="Pop up the message" + name="0" + value="0"/> <combo_box.item - label="Flash toolbar button" - name="1" - value="1"/> + label="Flash toolbar button" + name="1" + value="1"/> <combo_box.item - label="None" - name="2" - value="2"/> + label="None" + name="2" + value="2"/> </combo_box> <text - follows="left|top" - layout="topleft" - left="0" - height="12" - name="notifications_alert" - width="350" - top_pad="11" - visible="true" - text_color="DrYellow" - > + follows="left|top" + layout="topleft" + left="0" + height="12" + name="notifications_alert" + width="350" + top_pad="11" + visible="true" + text_color="DrYellow"> To temporarily stop all notifications, use Me > Status > Busy. </text> </panel> <panel - border="false" - follows="left|top" - height="1" - layout="topleft" - left="13" - width="517"> - - <text + border="false" follows="left|top" + height="1" layout="topleft" - left="0" - name="play_sound" - width="100" - top_pad="13" - visible="true"> + left="13" + width="517"> + + <text + follows="left|top" + layout="topleft" + left="0" + name="play_sound" + width="100" + top_pad="13" + visible="true"> Play sound: </text> <check_box - control_name="NewConversation" - height="16" - initial_value="true" - label="New conversation" - layout="topleft" - left_pad="15" - top_pad="-10" - name="new_conversation" - width="150" /> + control_name="NewConversation" + height="16" + initial_value="true" + label="New conversation" + layout="topleft" + left_pad="15" + top_pad="-10" + name="new_conversation" + width="150" /> <check_box - control_name="IncomingVoiceCall" - height="16" - initial_value="true" - label="Incoming voice call" - layout="topleft" - top_pad="6" - name="incoming_voice_call" - width="150" /> + control_name="IncomingVoiceCall" + height="16" + initial_value="true" + label="Incoming voice call" + layout="topleft" + top_pad="6" + name="incoming_voice_call" + width="150" /> <check_box - control_name="GroupChatMessages" - height="16" - initial_value="false" - label="Group chat messages" - layout="topleft" - top_pad="6" - name="group_chat_messages" - width="150" /> + control_name="GroupChatMessages" + height="16" + initial_value="false" + label="Group chat messages" + layout="topleft" + top_pad="6" + name="group_chat_messages" + width="150" /> <check_box - control_name="TeleportOffer" - height="16" - initial_value="true" - label="Teleport offer" - layout="topleft" - left_pad="35" - top_pad="-59" - name="teleport_offer" - width="150" /> + control_name="TeleportOffer" + height="16" + initial_value="true" + label="Teleport offer" + layout="topleft" + left_pad="35" + top_pad="-59" + name="teleport_offer" + width="150" /> <check_box - control_name="InventoryOffer" - height="16" - initial_value="false" - label="Inventory offer" - layout="topleft" - top_pad="6" - name="inventory_offer" - width="150" /> + control_name="InventoryOffer" + height="16" + initial_value="false" + label="Inventory offer" + layout="topleft" + top_pad="6" + name="inventory_offer" + width="150" /> </panel> - + <button - follows="left|top" - height="23" - label="Translation..." - layout="topleft" - left="9" - name="ok_btn" - top="-29" - width="170"> - <button.commit_callback - function="Pref.TranslationSettings" /> + follows="left|top" + height="23" + label="Translation..." + layout="topleft" + left="9" + name="ok_btn" + top="-29" + width="170"> + <button.commit_callback + function="Pref.TranslationSettings" /> </button> <button - follows="top|left" - height="23" - layout="topleft" - top_pad="-23" - left_pad="5" - name="autoreplace_showgui" - commit_callback.function="Pref.AutoReplace" - label="Auto-Replace..." - width="150"> + follows="top|left" + height="23" + layout="topleft" + top_pad="-23" + left_pad="5" + name="autoreplace_showgui" + commit_callback.function="Pref.AutoReplace" + label="Auto-Replace..." + width="150"> </button> <button - follows="top|left" - height="23" - layout="topleft" - top_pad="-23" - left_pad="5" - name="spellcheck_showgui" - commit_callback.function="Pref.SpellChecker" - label="Spell Checking..." - width="150"> + follows="top|left" + height="23" + layout="topleft" + top_pad="-23" + left_pad="5" + name="spellcheck_showgui" + commit_callback.function="Pref.SpellChecker" + label="Spell Checking..." + width="150"> </button> </panel> -- cgit v1.2.3 From 908f8735d4d60266504c97c13d65fda74045b731 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Fri, 9 Nov 2012 16:09:06 -0800 Subject: CHUI-517: Updating the copy in Preferences for Do Not Disturb mode. --- .../newview/skins/default/xui/en/panel_preferences_chat.xml | 12 ++++++------ .../skins/default/xui/en/panel_preferences_general.xml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 5524d0e4f0..4964df53bb 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -101,7 +101,7 @@ <panel border="false" follows="left|top" - height="193" + height="198" layout="topleft" left="13" width="517"> @@ -274,13 +274,13 @@ follows="left|top" layout="topleft" left="0" - height="12" + height="13" name="notifications_alert" - width="350" + width="500" top_pad="11" visible="true" text_color="DrYellow"> - To temporarily stop all notifications, use Me > Status > Busy. + To temporarily stop all notifications, use Communicate > Do Not Disturb. </text> </panel> @@ -288,7 +288,7 @@ <panel border="false" follows="left|top" - height="1" + height="67" layout="topleft" left="13" width="517"> @@ -299,7 +299,7 @@ left="0" name="play_sound" width="100" - top_pad="13" + top_pad="8" visible="true"> Play sound: </text> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml index 2cb063e8ee..ea0f7d8593 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -409,7 +409,7 @@ name="text_box3" top_pad="3" width="240"> - Busy mode response: + Do Not Disturb response: </text> <text_editor control_name="DoNotDisturbModeResponse" -- cgit v1.2.3 From 1786a7150e754ea10dfd5172ec2491dd67e83a9a Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Fri, 9 Nov 2012 16:16:06 -0800 Subject: CHUI-517: Updating the copy for the avatar in-world name bubble status for Do Not Disturb mode. --- indra/newview/skins/default/xui/en/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 79ee83969b..8310e0c62d 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -295,7 +295,7 @@ Please try logging in again in a minute.</string> <!-- llvoavatar. Displayed in the avatar chat bubble --> <string name="AvatarEditingAppearance">(Editing Appearance)</string> <string name="AvatarAway">Away</string> - <string name="AvatarDoNotDisturb">Busy</string> + <string name="AvatarDoNotDisturb">Do Not Disturb</string> <string name="AvatarMuted">Blocked</string> <!-- animations --> -- cgit v1.2.3 From f429decb0c222b293cee4d3b27c8340262fab572 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 9 Nov 2012 17:00:43 -0800 Subject: CHUI-486: Now the new chat preferences in drop down lists and checkboxes are storable. These values are accessible globally using gSavedSettings. --- indra/llui/llcheckboxctrl.cpp | 14 +-- indra/llui/llcheckboxctrl.h | 2 - indra/newview/app_settings/settings.xml | 121 +++++++++++++++++++++ .../default/xui/en/panel_preferences_chat.xml | 46 ++++---- 4 files changed, 143 insertions(+), 40 deletions(-) (limited to 'indra') diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp index 4fe444c1a4..5525520d78 100644 --- a/indra/llui/llcheckboxctrl.cpp +++ b/indra/llui/llcheckboxctrl.cpp @@ -107,7 +107,7 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p) LLButton::Params params = p.check_button; params.rect(btn_rect); //params.control_name(p.control_name); - params.click_callback.function(boost::bind(&LLCheckBoxCtrl::onButtonPress, this, _2)); + params.click_callback.function(boost::bind(&LLCheckBoxCtrl::onCommit, this)); params.commit_on_return(false); // Checkboxes only allow boolean initial values, but buttons can // take any LLSD. @@ -123,18 +123,6 @@ LLCheckBoxCtrl::~LLCheckBoxCtrl() // Children all cleaned up by default view destructor. } - -// static -void LLCheckBoxCtrl::onButtonPress( const LLSD& data ) -{ - //if (mRadioStyle) - //{ - // setValue(TRUE); - //} - - onCommit(); -} - void LLCheckBoxCtrl::onCommit() { if( getEnabled() ) diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index 67d8091a97..5ce45b2135 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -103,8 +103,6 @@ public: virtual void setControlName(const std::string& control_name, LLView* context); - void onButtonPress(const LLSD& data); - virtual BOOL isDirty() const; // Returns TRUE if the user has modified this control. virtual void resetDirty(); // Clear dirty state diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 5694cb9f30..bba1f4910a 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4667,6 +4667,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>KeepConversationLogTranscripts</key> + <map> + <key>Comment</key> + <string>Keep a conversation log and transcripts</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>LandBrushSize</key> <map> <key>Comment</key> @@ -6285,6 +6296,61 @@ <key>Value</key> <integer>305</integer> </map> + <key>NotificationConferenceIMOptions</key> + <map> + <key>Comment</key> + <string>Specifies how the UI responds to Conference IM Notifications.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>0</string> + </map> + <key>NotificationFriendIMOptions</key> + <map> + <key>Comment</key> + <string>Specifies how the UI responds to Friend IM Notifications.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>0</string> + </map> + <key>NotificationGroupChatOptions</key> + <map> + <key>Comment</key> + <string>Specifies how the UI responds to Group Chat Notifications.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>0</string> + </map> + <key>NotificationNearbyChatOptions</key> + <map> + <key>Comment</key> + <string>Specifies how the UI responds to Nearby Chat Notifications.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>0</string> + </map> + <key>NotificationNonFriendIMOptions</key> + <map> + <key>Comment</key> + <string>Specifies how the UI responds to Non Friend IM Notifications.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>0</string> + </map> <key>NotificationToastLifeTime</key> <map> <key>Comment</key> @@ -6801,6 +6867,61 @@ <key>Value</key> <integer>1</integer> </map> + <key>PlaySoundGroupChatMessages</key> + <map> + <key>Comment</key> + <string>Plays a sound when have a group chat message.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>PlaySoundIncomingVoiceCall</key> + <map> + <key>Comment</key> + <string>Plays a sound when have an incoming voice call.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>PlaySoundInventoryOffer</key> + <map> + <key>Comment</key> + <string>Plays a sound when have an inventory offer.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>PlaySoundNewConversation</key> + <map> + <key>Comment</key> + <string>Plays a sound when have a new conversation.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>PlaySoundTeleportOffer</key> + <map> + <key>Comment</key> + <string>Plays a sound when have a teleport offer.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>PluginAttachDebuggerToPlugins</key> <map> <key>Comment</key> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 4964df53bb..f1b11e2ca8 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -37,6 +37,7 @@ top_pad="6" width="330" /> <check_box + control_name="KeepConversationLogTranscripts" height="16" label="Keep a conversation log and transcripts" layout="topleft" @@ -135,15 +136,15 @@ width="223"> <combo_box.item label="Pop up the message" - name="0" + name="PopUpMessage" value="0"/> <combo_box.item label="Flash toolbar button" - name="1" + name="FlashToolbarButton" value="1"/> <combo_box.item label="None" - name="2" + name="None" value="2"/> </combo_box> <text @@ -166,15 +167,15 @@ width="223"> <combo_box.item label="Pop up the message" - name="0" + name="PopUpMessage" value="0"/> <combo_box.item label="Flash toolbar button" - name="1" + name="FlashToolbarButton" value="1"/> <combo_box.item label="None" - name="2" + name="None" value="2"/> </combo_box> <text @@ -197,15 +198,15 @@ width="223"> <combo_box.item label="Pop up the message" - name="0" + name="PopUpMessage" value="0"/> <combo_box.item label="Flash toolbar button" - name="1" + name="FlashToolbarButton" value="1"/> <combo_box.item label="None" - name="2" + name="None" value="2"/> </combo_box> <text @@ -228,15 +229,15 @@ width="223"> <combo_box.item label="Pop up the message" - name="0" + name="PopUpMessage" value="0"/> <combo_box.item label="Flash toolbar button" - name="1" + name="FlashToolbarButton" value="1"/> <combo_box.item label="None" - name="2" + name="None" value="2"/> </combo_box> <text @@ -259,15 +260,15 @@ width="223"> <combo_box.item label="Pop up the message" - name="0" + name="PopUpMessage" value="0"/> <combo_box.item label="Flash toolbar button" - name="1" + name="FlashToolBarButton" value="1"/> <combo_box.item label="None" - name="2" + name="None" value="2"/> </combo_box> <text @@ -304,9 +305,8 @@ Play sound: </text> <check_box - control_name="NewConversation" + control_name="PlaySoundNewConversation" height="16" - initial_value="true" label="New conversation" layout="topleft" left_pad="15" @@ -314,27 +314,24 @@ name="new_conversation" width="150" /> <check_box - control_name="IncomingVoiceCall" + control_name="PlaySoundIncomingVoiceCall" height="16" - initial_value="true" label="Incoming voice call" layout="topleft" top_pad="6" name="incoming_voice_call" width="150" /> <check_box - control_name="GroupChatMessages" + control_name="PlaySoundGroupChatMessages" height="16" - initial_value="false" label="Group chat messages" layout="topleft" top_pad="6" name="group_chat_messages" width="150" /> <check_box - control_name="TeleportOffer" + control_name="PlaySoundTeleportOffer" height="16" - initial_value="true" label="Teleport offer" layout="topleft" left_pad="35" @@ -342,9 +339,8 @@ name="teleport_offer" width="150" /> <check_box - control_name="InventoryOffer" + control_name="PlaySoundInventoryOffer" height="16" - initial_value="false" label="Inventory offer" layout="topleft" top_pad="6" -- cgit v1.2.3 From ff1dab1792f8d8ba6681e59978383304e25dabe2 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 9 Nov 2012 17:19:03 -0800 Subject: CHUI-450 : Fixed how the list of speakers is updated, always add the agent avatar in it, takes voice activation into account --- indra/newview/llfloaterimcontainer.cpp | 4 ++-- indra/newview/llspeakers.cpp | 26 +++++++++++--------------- 2 files changed, 13 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index b20d19d0fd..2789b78c2d 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1126,7 +1126,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool /* widget processing */ if (select_widget) { - LLFolderViewItem* widget = mConversationsWidgets[session_id]; + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); if (widget && widget->getParentFolder()) { widget->getParentFolder()->setSelection(widget, FALSE, FALSE); @@ -1539,7 +1539,7 @@ void LLFloaterIMContainer::openNearbyChat() //(which it should be...), open it so to make the list of participants visible. This happens to be the most common case when opening the Chat floater. if(mConversationsItems.size() == 1) { - LLConversationViewSession* nearby_chat = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[LLUUID()]); + LLConversationViewSession* nearby_chat = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,LLUUID())); if (nearby_chat) { nearby_chat->setOpen(TRUE); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 726199b7aa..5036334bdd 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -503,27 +503,23 @@ void LLSpeakerMgr::update(BOOL resort_ok) void LLSpeakerMgr::updateSpeakerList() { - // are we bound to the currently active voice channel? - if ((!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel)) - { - std::set<LLUUID> participants; - LLVoiceClient::getInstance()->getParticipantList(participants); - // add new participants to our list of known speakers - for (std::set<LLUUID>::iterator participant_it = participants.begin(); - participant_it != participants.end(); - ++participant_it) + // Are we bound to the currently active voice channel? + if ((!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive())) + { + std::set<LLUUID> participants; + LLVoiceClient::getInstance()->getParticipantList(participants); + // If we are, add all voice client participants to our list of known speakers + for (std::set<LLUUID>::iterator participant_it = participants.begin(); participant_it != participants.end(); ++participant_it) { setSpeaker(*participant_it, LLVoiceClient::getInstance()->getDisplayName(*participant_it), LLSpeaker::STATUS_VOICE_ACTIVE, (LLVoiceClient::getInstance()->isParticipantAvatar(*participant_it)?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL)); - - } } else { - // Check if the list is empty, except if it's Nearby Chat (session_id NULL). + // If not, check if the list is empty, except if it's Nearby Chat (session_id NULL). LLUUID session_id = getSessionID(); if ((mSpeakers.size() == 0) && (!session_id.isNull())) { @@ -533,16 +529,16 @@ void LLSpeakerMgr::updateSpeakerList() LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it) { - // Allow to set buddies if they are on line. Allow any other avatar. + // Add buddies if they are on line, add any other avatar. if (!LLAvatarTracker::instance().isBuddy(*it) || LLAvatarTracker::instance().isBuddyOnline(*it)) { setSpeaker(*it, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } } - // Also add the current agent - setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } } + // Finally, always add the current agent (it has to be there no matter what...) + setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp) -- cgit v1.2.3 From 99181a9777b7e42ed6e863a074789f37aa6b43f8 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 9 Nov 2012 19:06:00 -0800 Subject: CHUI-479 : WIP : Fixed the missing agent appearance in torn off dialogs by adding a consistency check and rebuild. --- indra/newview/llfloaterimsessiontab.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index a47c9177a1..c39319b373 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -263,11 +263,21 @@ void LLFloaterIMSessionTab::draw() { if (mRefreshTimer->hasExpired()) { - if (getParticipantList()) + LLParticipantList* item = getParticipantList(); + if (item) { - getParticipantList()->update(); + // Update all model items + item->update(); + // If the model and view list diverge in count, rebuild + // Note: this happens sometimes right around init (add participant events fire but get dropped) and is the cause + // of missing participants, often, the user agent itself. As there will be no other event fired, there's + // no other choice but get those inconsistencies regularly (and lightly) checked and scrubbed. + if (item->getChildrenCount() != mConversationsWidgets.size()) + { + buildConversationViewParticipant(); + } } - + refreshConversation(); // Restart the refresh timer @@ -376,7 +386,7 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant() LLParticipantList* item = getParticipantList(); if (!item) { - // Nothing to do if the model list is empty + // Nothing to do if the model list is inexistent return; } @@ -470,7 +480,8 @@ void LLFloaterIMSessionTab::refreshConversation() session_name = LLIMModel::instance().getName(mSessionID); } updateSessionName(session_name); - } + } + mConversationViewModel.requestSortAll(); mConversationsRoot->arrangeAll(); mConversationsRoot->update(); -- cgit v1.2.3 From ab5a0a1d4d0a029dd92c9fc108638736a57ce7c6 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 12 Nov 2012 15:06:42 +0200 Subject: CHUI-362 FIXED (Torn off conversation name is highlighted when selected in conversation list with different conversation showing in message panel): connect new method "returnFloaterToHost" to click on quasi-URL "Bring it back" --- indra/newview/llfloaterimcontainer.cpp | 12 ++++++++++-- indra/newview/llfloaterimcontainer.h | 2 +- indra/newview/llfloaterimsessiontab.h | 2 +- indra/newview/skins/default/xui/en/floater_im_container.xml | 4 ++-- 4 files changed, 14 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 994a76189a..2707e3dcbb 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -133,7 +133,6 @@ void LLFloaterIMContainer::onCurrentChannelChanged(const LLUUID& session_id) } } - BOOL LLFloaterIMContainer::postBuild() { mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLFloaterIMContainer::onNewMessageReceived, this, _1)); @@ -142,7 +141,8 @@ BOOL LLFloaterIMContainer::postBuild() setTabContainer(getChild<LLTabContainer>("im_box_tab_container")); mStubPanel = getChild<LLPanel>("stub_panel"); - mStubTextBox = getChild<LLTextBox>("stub_textbox"); + mStubTextBox = getChild<LLTextBox>("stub_textbox_2"); + mStubTextBox->setURLClickedCallback(boost::bind(&LLFloaterIMContainer::returnFloaterToHost, this)); mConversationsStack = getChild<LLLayoutStack>("conversations_stack"); mConversationsPane = getChild<LLLayoutPanel>("conversations_layout_panel"); @@ -506,6 +506,14 @@ void LLFloaterIMContainer::showStub(bool stub_is_visible) mStubPanel->setVisible(stub_is_visible); } +// listener for click on mStubTextBox2 +void LLFloaterIMContainer::returnFloaterToHost() +{ + LLUUID session_id = this->getSelectedSession(); + LLFloaterIMSessionTab* floater = LLFloaterIMSessionTab::getConversation(session_id); + floater->onTearOffClicked(); +} + void LLFloaterIMContainer::setVisible(BOOL visible) { LLFloaterIMNearbyChat* nearby_chat; if (visible) diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index a09cde60f5..e60576a50d 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -65,7 +65,7 @@ public: /*virtual*/ void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); - + void returnFloaterToHost(); void showConversation(const LLUUID& session_id); void selectConversation(const LLUUID& session_id); BOOL selectConversationPair(const LLUUID& session_id, bool select_widget); diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 94854ee9ee..8f5a8c2c1b 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -91,6 +91,7 @@ public: void buildConversationViewParticipant(); void setSortOrder(const LLConversationSort& order); + virtual void onTearOffClicked(); virtual void updateMessages() {} @@ -106,7 +107,6 @@ protected: bool onIMShowModesMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemEnable(const LLSD& userdata); static void onSlide(LLFloaterIMSessionTab *self); - virtual void onTearOffClicked(); // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e3db3d52ed..1388b9e474 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -159,9 +159,9 @@ top="40" height="20" valign="center" - parse_urls="false" + parse_urls="true" wrap="true"> - Bring it back. + [secondlife:/// Bring it back.] </text> </panel> </panel_container> -- cgit v1.2.3 From 91781df3701da9852dbe87a4d5c9d5e3abf09987 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 12 Nov 2012 18:18:34 -0800 Subject: CHUI-486: Now toasts only appear when proper 'Chat Preference' setting is set to 'Pop Up Message'. --- indra/newview/llfloaterimnearbychathandler.cpp | 6 ++++ indra/newview/llimview.cpp | 45 ++++++++++++++++++-------- 2 files changed, 38 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 0dfaa9174b..f382b65b1d 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -283,6 +283,12 @@ bool LLFloaterIMNearbyChatScreenChannel::createPoolToast() void LLFloaterIMNearbyChatScreenChannel::addChat(LLSD& chat) { + //Ignore Nearby Toasts + if(gSavedSettings.getString("NotificationNearbyChatOptions") != "0") + { + return; + } + //look in pool. if there is any message if(mStopProcessing) return; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 6712127750..e4b51b719b 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -139,19 +139,38 @@ void toast_callback(const LLSD& msg){ return; } - // *NOTE Skip toasting if the user disable it in preferences/debug settings ~Alexandrea - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - msg["session_id"]); - if (!gSavedSettings.getBOOL("EnableGroupChatPopups") - && session->isGroupSessionType()) - { - return; - } - if (!gSavedSettings.getBOOL("EnableIMChatPopups") - && !session->isGroupSessionType()) - { - return; - } + // *NOTE Skip toasting if the user disable it in preferences/debug settings ~Alexandrea + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( + msg["session_id"]); + + + //Ignore P2P Friend/Non-Friend toasts + if(session->isP2PSessionType()) + { + //Ignores non-friends + if(LLAvatarTracker::instance().getBuddyInfo(msg["from_id"]) == NULL && + gSavedSettings.getString("NotificationNonFriendIMOptions") != "0") + { + return; + } + //Ignores friends + else if(gSavedSettings.getString("NotificationFriendIMOptions") != "0") + { + return; + } + } + //Ignore Ad Hoc Toasts + else if(session->isAdHocSessionType() && + gSavedSettings.getString("NotificationConferenceIMOptions") != "0") + { + return; + } + //Ignore Group Toasts + else if(session->isGroupSessionType() && + gSavedSettings.getString("NotificationGroupChatOptions") != "0") + { + return; + } LLAvatarNameCache::get(msg["from_id"].asUUID(), boost::bind(&on_avatar_name_cache_toast, -- cgit v1.2.3 From 6ba822c0fffcf86c79d25c44625c2667ac23e64a Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Tue, 13 Nov 2012 13:32:24 +0200 Subject: CHUI-460 FIXED Reselect floater after toggling the participant list open or closed --- indra/newview/llconversationview.cpp | 2 +- indra/newview/llfloaterimcontainer.cpp | 12 +++++++++++- indra/newview/llfloaterimcontainer.h | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 295dd2ae6d..53392ac372 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -240,7 +240,7 @@ void LLConversationViewSession::toggleOpen() { getParentFolder()->setSelection(this, true); } - + mContainer->reSelectConversation(); } } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 2707e3dcbb..962e9f4df6 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -334,7 +334,7 @@ void LLFloaterIMContainer::onExpandCollapseButtonClicked() { collapseConversationsPane(!mConversationsPane->isCollapsed()); } - selectConversation(mSelectedSession); + reSelectConversation(); } LLFloaterIMContainer* LLFloaterIMContainer::findInstance() @@ -1574,4 +1574,14 @@ void LLFloaterIMContainer::onNearbyChatClosed() closeFloater(); } +void LLFloaterIMContainer::reSelectConversation() +{ + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(mSelectedSession); + if (session_floater->getHost()) + { + selectFloater(session_floater); + } + +} + // EOF diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index e60576a50d..ad1f0039e9 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -163,6 +163,7 @@ public: LLConversationItem* addConversationListItem(const LLUUID& uuid, bool isWidgetSelected = false); void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); void setNearbyDistances(); + void reSelectConversation(); private: LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); -- cgit v1.2.3 From aa2640f13ab61fa55819af26b001978fa2dd9a3f Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Tue, 13 Nov 2012 14:04:14 +0200 Subject: CHUI-447 FIXED Set session name as avatar's display name, if session is created by getting new message. --- indra/newview/llimview.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 6712127750..781b0cb2ea 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2424,14 +2424,21 @@ void LLIMMgr::addMessage( //*NOTE session_name is empty in case of incoming P2P sessions std::string fixed_session_name = from; + bool name_is_setted = false; if(!session_name.empty() && session_name.size()>1) { fixed_session_name = session_name; + name_is_setted = true; } bool new_session = !hasSession(new_session_id); if (new_session) { + LLAvatarName av_name; + if (LLAvatarNameCache::get(other_participant_id, &av_name) && !name_is_setted) + { + fixed_session_name = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); + } LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg); // When we get a new IM, and if you are a god, display a bit -- cgit v1.2.3 From 5a31b5dceaeb7dd7089c7426371aac39927c5c02 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 13 Nov 2012 11:19:45 -0800 Subject: CHUI-486: Code cleanup, instead of using values such as 0, 1, 2 now using strings 'toast', 'flash', 'none'. These values are used whether to show a notification or not. --- indra/newview/app_settings/settings.xml | 10 ++++---- indra/newview/llfloaterimnearbychathandler.cpp | 2 +- indra/newview/llimview.cpp | 9 ++++--- .../default/xui/en/panel_preferences_chat.xml | 30 +++++++++++----------- 4 files changed, 26 insertions(+), 25 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 9b8c86ffc8..b703b9cc8e 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6316,7 +6316,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>0</string> + <string>toast</string> </map> <key>NotificationFriendIMOptions</key> <map> @@ -6327,7 +6327,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>0</string> + <string>toast</string> </map> <key>NotificationGroupChatOptions</key> <map> @@ -6338,7 +6338,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>0</string> + <string>toast</string> </map> <key>NotificationNearbyChatOptions</key> <map> @@ -6349,7 +6349,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>0</string> + <string>toast</string> </map> <key>NotificationNonFriendIMOptions</key> <map> @@ -6360,7 +6360,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>0</string> + <string>toast</string> </map> <key>NotificationToastLifeTime</key> <map> diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index f382b65b1d..ab81b85d04 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -284,7 +284,7 @@ bool LLFloaterIMNearbyChatScreenChannel::createPoolToast() void LLFloaterIMNearbyChatScreenChannel::addChat(LLSD& chat) { //Ignore Nearby Toasts - if(gSavedSettings.getString("NotificationNearbyChatOptions") != "0") + if(gSavedSettings.getString("NotificationNearbyChatOptions") != "toast") { return; } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index e4b51b719b..d57ffb9a11 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -149,29 +149,30 @@ void toast_callback(const LLSD& msg){ { //Ignores non-friends if(LLAvatarTracker::instance().getBuddyInfo(msg["from_id"]) == NULL && - gSavedSettings.getString("NotificationNonFriendIMOptions") != "0") + gSavedSettings.getString("NotificationNonFriendIMOptions") != "toast") { return; } //Ignores friends - else if(gSavedSettings.getString("NotificationFriendIMOptions") != "0") + else if(gSavedSettings.getString("NotificationFriendIMOptions") != "toast") { return; } } //Ignore Ad Hoc Toasts else if(session->isAdHocSessionType() && - gSavedSettings.getString("NotificationConferenceIMOptions") != "0") + gSavedSettings.getString("NotificationConferenceIMOptions") != "toast") { return; } //Ignore Group Toasts else if(session->isGroupSessionType() && - gSavedSettings.getString("NotificationGroupChatOptions") != "0") + gSavedSettings.getString("NotificationGroupChatOptions") != "toast") { return; } + //Show toast LLAvatarNameCache::get(msg["from_id"].asUUID(), boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index f1b11e2ca8..8ab5c9a99c 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -137,15 +137,15 @@ <combo_box.item label="Pop up the message" name="PopUpMessage" - value="0"/> + value="toast"/> <combo_box.item label="Flash toolbar button" name="FlashToolbarButton" - value="1"/> + value="flash"/> <combo_box.item label="None" name="None" - value="2"/> + value="none"/> </combo_box> <text follows="left|top" @@ -168,15 +168,15 @@ <combo_box.item label="Pop up the message" name="PopUpMessage" - value="0"/> + value="toast"/> <combo_box.item label="Flash toolbar button" name="FlashToolbarButton" - value="1"/> + value="flash"/> <combo_box.item label="None" name="None" - value="2"/> + value="none"/> </combo_box> <text follows="left|top" @@ -199,15 +199,15 @@ <combo_box.item label="Pop up the message" name="PopUpMessage" - value="0"/> + value="toast"/> <combo_box.item label="Flash toolbar button" name="FlashToolbarButton" - value="1"/> + value="flash"/> <combo_box.item label="None" name="None" - value="2"/> + value="none"/> </combo_box> <text follows="left|top" @@ -230,15 +230,15 @@ <combo_box.item label="Pop up the message" name="PopUpMessage" - value="0"/> + value="toast"/> <combo_box.item label="Flash toolbar button" name="FlashToolbarButton" - value="1"/> + value="flash"/> <combo_box.item label="None" name="None" - value="2"/> + value="none"/> </combo_box> <text follows="left|top" @@ -261,15 +261,15 @@ <combo_box.item label="Pop up the message" name="PopUpMessage" - value="0"/> + value="toast"/> <combo_box.item label="Flash toolbar button" name="FlashToolBarButton" - value="1"/> + value="flash"/> <combo_box.item label="None" name="None" - value="2"/> + value="none"/> </combo_box> <text follows="left|top" -- cgit v1.2.3 From 29e9f792bb9595dbacbc8a4b584b5bf62e7db6c6 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 13 Nov 2012 21:20:05 +0200 Subject: CHUI-512 FIXED (New incoming conversations take focus in message panel only and do not show toasts). Rejected update message when floater hasn't focus --- indra/newview/llfloaterimsession.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 0c622e07c4..e1dc5b91d0 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -142,7 +142,7 @@ void LLFloaterIMSession::newIMCallback(const LLSD& data) LLFloaterIMSession* floater = LLFloaterReg::findTypedInstance<LLFloaterIMSession>("impanel", session_id); // update if visible, otherwise will be updated when opened - if (floater && floater->getVisible()) + if (floater && (floater->getHost()? floater->hasFocus() : floater->getVisible())) { floater->updateMessages(); } -- cgit v1.2.3 From df1fd5d4bbe8e71389872e4cdbac3e9f165cc3f8 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 14 Nov 2012 00:07:46 +0200 Subject: CHUI-508 FIXED Attach to and Attach to HUD menus not showing in inventory floater to select attachment point --- indra/newview/llinventorybridge.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 280a1775e9..52f2897788 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -5453,6 +5453,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) p.on_enable.parameter = cbparams; LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu; LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent); + items.push_back(p.name); } } } -- cgit v1.2.3 From d75824d520ba1965e48196f8b230ded0f15c5841 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 13 Nov 2012 16:45:56 -0800 Subject: CHUI-486: Post code review changes for last submit, just added in some parenthesis for conditional statements, thus making them more clear. --- indra/newview/llimview.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 3b217ef482..0f4bbd054a 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -148,8 +148,8 @@ void toast_callback(const LLSD& msg){ if(session->isP2PSessionType()) { //Ignores non-friends - if(LLAvatarTracker::instance().getBuddyInfo(msg["from_id"]) == NULL && - gSavedSettings.getString("NotificationNonFriendIMOptions") != "toast") + if((LLAvatarTracker::instance().getBuddyInfo(msg["from_id"]) == NULL) + && (gSavedSettings.getString("NotificationNonFriendIMOptions") != "toast")) { return; } @@ -160,14 +160,14 @@ void toast_callback(const LLSD& msg){ } } //Ignore Ad Hoc Toasts - else if(session->isAdHocSessionType() && - gSavedSettings.getString("NotificationConferenceIMOptions") != "toast") + else if(session->isAdHocSessionType() + && (gSavedSettings.getString("NotificationConferenceIMOptions") != "toast")) { return; } //Ignore Group Toasts - else if(session->isGroupSessionType() && - gSavedSettings.getString("NotificationGroupChatOptions") != "toast") + else if(session->isGroupSessionType() + && (gSavedSettings.getString("NotificationGroupChatOptions") != "toast")) { return; } -- cgit v1.2.3 From 40949724345a00a22b1fae5d0645c244cbf47567 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Wed, 14 Nov 2012 15:28:05 +0200 Subject: CHUI-389 FIXED Added parameter for sessionAdded to get access to has_offline_msg value. Set UnreadIMs icon to visible if messages were sent while offline. --- indra/newview/llchiclet.h | 2 +- indra/newview/llchicletbar.cpp | 2 +- indra/newview/llchicletbar.h | 2 +- indra/newview/llconversationlog.cpp | 33 +++++++++++++++++++++++------ indra/newview/llconversationlog.h | 12 ++++++----- indra/newview/llconversationloglist.cpp | 4 ++++ indra/newview/llconversationloglistitem.cpp | 5 +++++ indra/newview/llconversationloglistitem.h | 1 + indra/newview/llfloaterimcontainer.cpp | 2 +- indra/newview/llfloaterimcontainer.h | 2 +- indra/newview/llimview.cpp | 6 +++--- indra/newview/llimview.h | 4 ++-- indra/newview/llsyswellwindow.cpp | 2 +- indra/newview/llsyswellwindow.h | 2 +- 14 files changed, 55 insertions(+), 24 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 3c8389e20d..d6be2df103 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -873,7 +873,7 @@ class LLIMWellChiclet : public LLSysWellChiclet, LLIMSessionObserver { friend class LLUICtrlFactory; public: - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} + /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) {} /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; /*virtual*/ void sessionRemoved(const LLUUID& session_id) { messageCountChanged(LLSD()); } diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index ad7890b47a..c66ae1cdd0 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -84,7 +84,7 @@ LLIMChiclet* LLChicletBar::createIMChiclet(const LLUUID& session_id) } //virtual -void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) { if (!getChicletPanel()) return; diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h index a9a5b61ae7..dc991ca772 100644 --- a/indra/newview/llchicletbar.h +++ b/indra/newview/llchicletbar.h @@ -50,7 +50,7 @@ public: LLChicletPanel* getChicletPanel() { return mChicletPanel; } // LLIMSessionObserver observe triggers - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; /*virtual*/ void sessionRemoved(const LLUUID& session_id); diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 3d2b6a5c00..a0765f5e16 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -223,13 +223,17 @@ void LLConversationLog::enableLogging(bool enable) notifyObservers(); } -void LLConversationLog::logConversation(const LLUUID& session_id) +void LLConversationLog::logConversation(const LLUUID& session_id, BOOL has_offline_msg) { const LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); LLConversation* conversation = findConversation(session); if (session && conversation) { + if(has_offline_msg) + { + updateOfflineIMs(session, has_offline_msg); + } updateConversationTimestamp(conversation); } else if (session && !conversation) @@ -265,7 +269,22 @@ void LLConversationLog::updateConversationName(const LLIMModel::LLIMSession* ses if (conversation) { conversation->setConverstionName(name); - notifyPrticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_NAME); + notifyParticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_NAME); + } +} + +void LLConversationLog::updateOfflineIMs(const LLIMModel::LLIMSession* session, BOOL new_messages) +{ + if (!session) + { + return; + } + + LLConversation* conversation = findConversation(session); + if (conversation) + { + conversation->setOfflineMessages(new_messages); + notifyParticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_OfflineIMs); } } @@ -274,7 +293,7 @@ void LLConversationLog::updateConversationTimestamp(LLConversation* conversation if (conversation) { conversation->updateTimestamp(); - notifyPrticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_TIME); + notifyParticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_TIME); } } @@ -337,9 +356,9 @@ void LLConversationLog::removeObserver(LLConversationLogObserver* observer) mObservers.erase(observer); } -void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) { - logConversation(session_id); + logConversation(session_id, has_offline_msg); } void LLConversationLog::cache() @@ -477,7 +496,7 @@ void LLConversationLog::notifyObservers() } } -void LLConversationLog::notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask) +void LLConversationLog::notifyParticularConversationObservers(const LLUUID& session_id, U32 mask) { std::set<LLConversationLogObserver*>::const_iterator iter = mObservers.begin(); for (; iter != mObservers.end(); ++iter) @@ -489,7 +508,7 @@ void LLConversationLog::notifyPrticularConversationObservers(const LLUUID& sessi void LLConversationLog::onNewMessageReceived(const LLSD& data) { const LLUUID session_id = data["session_id"].asUUID(); - logConversation(session_id); + logConversation(session_id, false); } void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, const LLIMModel::LLIMSession* session) diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 7d0b9113c6..8f6ac3f5d1 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -59,7 +59,7 @@ public: bool hasOfflineMessages() const { return mHasOfflineIMs; } void setConverstionName(std::string conv_name) { mConversationName = conv_name; } - + void setOfflineMessages(bool new_messages) { mHasOfflineIMs = new_messages; } bool isOlderThan(U32 days) const; /* @@ -123,7 +123,7 @@ public: void removeObserver(LLConversationLogObserver* observer); // LLIMSessionObserver triggers - virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; // Stub virtual void sessionRemoved(const LLUUID& session_id){} // Stub virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){}; // Stub @@ -147,9 +147,9 @@ private: /** * adds conversation to the conversation list and notifies observers */ - void logConversation(const LLUUID& session_id); + void logConversation(const LLUUID& session_id, BOOL has_offline_msg); - void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask); + void notifyParticularConversationObservers(const LLUUID& session_id, U32 mask); /** * constructs file name in which conversations log will be saved @@ -165,6 +165,7 @@ private: void createConversation(const LLIMModel::LLIMSession* session); void updateConversationTimestamp(LLConversation* conversation); void updateConversationName(const LLIMModel::LLIMSession* session, const std::string& name); + void updateOfflineIMs(const LLIMModel::LLIMSession* session, BOOL new_messages); LLConversation* findConversation(const LLIMModel::LLIMSession* session); @@ -184,7 +185,8 @@ public: enum EConversationChange { CHANGED_TIME = 1, // last interaction time changed - CHANGED_NAME = 2 // conversation name changed + CHANGED_NAME = 2, // conversation name changed + CHANGED_OfflineIMs = 3 }; virtual ~LLConversationLogObserver(){} diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 429e99f7ad..6dbcb7bef7 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -171,6 +171,10 @@ void LLConversationLogList::changed(const LLUUID& session_id, U32 mask) mIsDirty = true; } } + else if (mask & LLConversationLogObserver::CHANGED_OfflineIMs) + { + item->updateOfflineIMs(); + } } void LLConversationLogList::addNewItem(const LLConversation* conversation) diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp index 9fad0e603e..4e984d603b 100644 --- a/indra/newview/llconversationloglistitem.cpp +++ b/indra/newview/llconversationloglistitem.cpp @@ -119,6 +119,11 @@ void LLConversationLogListItem::updateName() mConversationName->setValue(mConversation->getConversationName()); } +void LLConversationLogListItem::updateOfflineIMs() +{ + getChild<LLIconCtrl>("unread_ims_icon")->setVisible(mConversation->hasOfflineMessages()); +} + void LLConversationLogListItem::onMouseEnter(S32 x, S32 y, MASK mask) { getChildView("hovered_icon")->setVisible(true); diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h index 57f72db382..ee28456bbb 100644 --- a/indra/newview/llconversationloglistitem.h +++ b/indra/newview/llconversationloglistitem.h @@ -69,6 +69,7 @@ public: */ void updateTimestamp(); void updateName(); + void updateOfflineIMs(); private: diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 962e9f4df6..af5db13023 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -96,7 +96,7 @@ LLFloaterIMContainer::~LLFloaterIMContainer() } } -void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) { addConversationListItem(session_id); LLFloaterIMSessionTab::addToHost(session_id); diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index ad1f0039e9..afc8d00174 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -85,7 +85,7 @@ public: static void idle(void* user_data); // LLIMSessionObserver observe triggers - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id); /*virtual*/ void sessionRemoved(const LLUUID& session_id); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 0f4bbd054a..0bb370e6fe 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -724,7 +724,7 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co // When notifying observer, name of session is used instead of "name", because they may not be the // same if it is an adhoc session (in this case name is localized in LLIMSession constructor). std::string session_name = LLIMModel::getInstance()->getName(session_id); - LLIMMgr::getInstance()->notifyObserverSessionAdded(session_id, session_name, other_participant_id); + LLIMMgr::getInstance()->notifyObserverSessionAdded(session_id, session_name, other_participant_id,has_offline_msg); return true; @@ -2974,11 +2974,11 @@ void LLIMMgr::clearPendingAgentListUpdates(const LLUUID& session_id) } } -void LLIMMgr::notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +void LLIMMgr::notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, bool has_offline_msg) { for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++) { - (*it)->sessionAdded(session_id, name, other_participant_id); + (*it)->sessionAdded(session_id, name, other_participant_id, has_offline_msg); } } diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 054388bc6c..19b738069c 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -295,7 +295,7 @@ class LLIMSessionObserver { public: virtual ~LLIMSessionObserver() {} - virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0; + virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) = 0; virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0; virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) = 0; virtual void sessionRemoved(const LLUUID& session_id) = 0; @@ -462,7 +462,7 @@ private: static void onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& name, bool is_group); - void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, bool has_offline_msg); //Triggers when a session has already been added void notifyObserverSessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); void notifyObserverSessionVoiceOrIMStarted(const LLUUID& session_id); diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 18e0d9d0d2..1b8bdf3b46 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -617,7 +617,7 @@ BOOL LLIMWellWindow::postBuild() //virtual void LLIMWellWindow::sessionAdded(const LLUUID& session_id, - const std::string& name, const LLUUID& other_participant_id) + const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) { LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); if (!session) return; diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 378d5e0aa2..d6480f1fc6 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -170,7 +170,7 @@ public: /*virtual*/ BOOL postBuild(); // LLIMSessionObserver observe triggers - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; /*virtual*/ void sessionRemoved(const LLUUID& session_id); -- cgit v1.2.3 From 7a088e9b2c8ffddbf5cd8dad72281a64a32d7c63 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 14 Nov 2012 19:39:50 +0200 Subject: CHUI-501 FIXED Add link to Privacy tab from Comms floater --- indra/newview/llfloaterimcontainer.cpp | 19 +++++++++++-------- indra/newview/llfloaterpreference.cpp | 20 ++++++++++++++++++++ indra/newview/llfloaterpreference.h | 4 ++++ .../skins/default/xui/en/menu_participant_view.xml | 7 +++++++ 4 files changed, 42 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index af5db13023..ec1068d191 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -717,15 +717,18 @@ void LLFloaterIMContainer::onCustomAction(const LLSD& userdata) } if ("chat_preferences" == command) { - LLFloaterPreference* floater_prefs = LLFloaterReg::showTypedInstance<LLFloaterPreference>("preferences"); - if (floater_prefs) + LLFloaterPreference * floater_prefp = LLFloaterReg::showTypedInstance<LLFloaterPreference>("preferences"); + if (floater_prefp) { - LLTabContainer* tab_container = floater_prefs->getChild<LLTabContainer>("pref core"); - LLPanel* chat_panel = tab_container->getPanelByName("chat"); - if (tab_container && chat_panel) - { - tab_container->selectTabPanel(chat_panel); - } + floater_prefp->selectChatPanel(); + } + } + if ("privacy_preferences" == command) + { + LLFloaterPreference * floater_prefp = LLFloaterReg::showTypedInstance<LLFloaterPreference>("preferences"); + if (floater_prefp) + { + floater_prefp->selectPrivacyPanel(); } } } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 7c5e0776a7..ffd59ba8b6 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1570,6 +1570,26 @@ void LLFloaterPreference::setCacheLocation(const LLStringExplicit& location) cache_location_editor->setToolTip(location); } +void LLFloaterPreference::selectPanel(const LLSD& name) +{ + LLTabContainer * tab_containerp = getChild<LLTabContainer>("pref core"); + LLPanel * panel = tab_containerp->getPanelByName(name); + if (NULL != panel) + { + tab_containerp->selectTabPanel(panel); + } +} + +void LLFloaterPreference::selectPrivacyPanel() +{ + selectPanel("im"); +} + +void LLFloaterPreference::selectChatPanel() +{ + selectPanel("chat"); +} + //------------------------------Updater--------------------------------------- static bool handleBandwidthChanged(const LLSD& newvalue) diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 10a416beb5..4c1c122fb1 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -82,6 +82,8 @@ public: void processProfileProperties(const LLAvatarData* pAvatarData ); void storeAvatarProperties( const LLAvatarData* pAvatarData ); void saveAvatarProperties( void ); + void selectPrivacyPanel(); + void selectChatPanel(); protected: void onBtnOK(); @@ -164,6 +166,8 @@ public: void buildPopupLists(); static void refreshSkin(void* data); + void selectPanel(const LLSD& name); + private: static std::string sSkin; bool mClickActionDirty; ///< Set to true when the click/double-click options get changed by user. diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml index 6fa0707eea..523ce7b35b 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_view.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -68,6 +68,13 @@ function="IMFloaterContainer.Action" parameter="chat_preferences" /> </menu_item_call> + <menu_item_call + label="Privacy preferences..." + name="privacy_preferences"> + <on_click + function="IMFloaterContainer.Action" + parameter="privacy_preferences" /> + </menu_item_call> <menu_item_check label="Open conversation log" name="Conversation" -- cgit v1.2.3 From e15921e42b4ac14504b22b0acbb349aa6d19664b Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 14 Nov 2012 10:37:52 -0800 Subject: CHUI-479 : WIP : Small refactoring to allow participant to be added to session whether or not its parent folder is. --- indra/newview/llconversationview.cpp | 21 +++++++++++++-------- indra/newview/llconversationview.h | 1 + indra/newview/llfloaterimsessiontab.cpp | 1 + 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 295dd2ae6d..ad334869fb 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -460,21 +460,26 @@ void LLConversationViewParticipant::refresh() void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder) { - //Add the item to the folder (conversation) + // Add the item to the folder (conversation) LLFolderViewItem::addToFolder(folder); - //Now retrieve the folder (conversation) UUID, which is the speaker session + // Retrieve the folder (conversation) UUID, which is also the speaker session UUID LLConversationItem* vmi = this->getParentFolder() ? dynamic_cast<LLConversationItem*>(this->getParentFolder()->getViewModelItem()) : NULL; - if(vmi) + if (vmi) { - //Allows speaking icon image to be loaded based on mUUID - mAvatarIcon->setValue(mUUID); - - //Allows the speaker indicator to be activated based on the user and conversation - mSpeakingIndicator->setSpeakerId(mUUID, vmi->getUUID()); + addToSession(vmi->getUUID()); } } +void LLConversationViewParticipant::addToSession(const LLUUID& session_id) +{ + //Allows speaking icon image to be loaded based on mUUID + mAvatarIcon->setValue(mUUID); + + //Allows the speaker indicator to be activated based on the user and conversation + mSpeakingIndicator->setSpeakerId(mUUID, session_id); +} + void LLConversationViewParticipant::onInfoBtnClick() { LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", mUUID)); diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index cc6995c207..3610ac67de 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -121,6 +121,7 @@ public: bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } virtual void refresh(); void addToFolder(LLFolderViewFolder* folder); + void addToSession(const LLUUID& session_id); /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index c39319b373..e78422145d 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -417,6 +417,7 @@ void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* p LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); mConversationsWidgets[uuid] = participant_view; participant_view->addToFolder(mConversationsRoot); + participant_view->addToSession(mSessionID); participant_view->setVisible(TRUE); refreshConversation(); } -- cgit v1.2.3 From 33068c6da8f079c557e4fb520b074f6e5ce40ba4 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 14 Nov 2012 10:40:51 -0800 Subject: CHUI-479 : WIP : Add debug tracing into speaking indicator manager and monitors (to be deleted eventually). --- indra/newview/llconversationmodel.cpp | 10 +++++++++ indra/newview/llconversationmodel.h | 1 + indra/newview/llconversationview.cpp | 32 ++++++++++++++++++++++++++++ indra/newview/llconversationview.h | 8 +++++-- indra/newview/lloutputmonitorctrl.cpp | 29 +++++++++++++++++++++++-- indra/newview/llspeakingindicatormanager.cpp | 7 ++++++ indra/newview/llspeakingindicatormanager.h | 2 +- 7 files changed, 84 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 47a82bfe17..8aa740e5d1 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -440,6 +440,16 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam } } +LLConversationItemSession* LLConversationItemParticipant::getParentSession() +{ + LLConversationItemSession* parent_session = NULL; + if (hasParent()) + { + parent_session = dynamic_cast<LLConversationItemSession*>(mParent); + } + return parent_session; +} + void LLConversationItemParticipant::dumpDebugData() { llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", display name = " << mDisplayName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 481d46af58..2ee21d0c16 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -195,6 +195,7 @@ public: virtual const bool getDistanceToAgent(F64& dist) const { dist = mDistToAgent; return (dist >= 0.0); } void fetchAvatarName(); + LLConversationItemSession* getParentSession(); void dumpDebugData(); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 295dd2ae6d..11eef3f7dc 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -327,6 +327,7 @@ void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& sessi mSpeakingIndicator->setSpeakerId(is_active ? gAgentID : LLUUID::null); } + llinfos << "Merov debug : onCurrentVoiceSessionChanged, switchIndicator is_active = " << is_active << llendl; mSpeakingIndicator->switchIndicator(is_active); mCallIconLayoutPanel->setVisible(is_active); } @@ -366,6 +367,11 @@ LLConversationViewParticipant::LLConversationViewParticipant( const LLConversati { } +LLConversationViewParticipant::~LLConversationViewParticipant() +{ + mActiveVoiceChannelConnection.disconnect(); +} + void LLConversationViewParticipant::initFromParams(const LLConversationViewParticipant::Params& params) { LLAvatarIconCtrl::Params avatar_icon_params(params.avatar_icon()); @@ -392,6 +398,7 @@ BOOL LLConversationViewParticipant::postBuild() mInfoBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onInfoBtnClick, this)); mInfoBtn->setVisible(false); + mActiveVoiceChannelConnection = LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLConversationViewParticipant::onCurrentVoiceSessionChanged, this, _1)); mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator"); if (!sStaticInitialized) @@ -445,6 +452,29 @@ S32 LLConversationViewParticipant::arrange(S32* width, S32* height) return arranged; } +void LLConversationViewParticipant::onCurrentVoiceSessionChanged(const LLUUID& session_id) +{ + llinfos << "Merov debug : onCurrentVoiceSessionChanged begin, uuid = " << mUUID << ", session_id = " << session_id << llendl; + LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem()); + //llinfos << "Merov debug : onCurrentVoiceSessionChanged participant_model = " << participant_model << llendl; + + if (participant_model) + { + //llinfos << "Merov debug : onCurrentVoiceSessionChanged enter if 1" << llendl; + LLConversationItemSession* parent_session = participant_model->getParentSession(); + //llinfos << "Merov debug : onCurrentVoiceSessionChanged parent_session = " << parent_session << llendl; + if (parent_session) + { + //llinfos << "Merov debug : onCurrentVoiceSessionChanged enter if 2" << llendl; + bool is_active = (parent_session->getUUID() == session_id); + //llinfos << "Merov debug : onCurrentVoiceSessionChanged, is_active = " << is_active << llendl; + mSpeakingIndicator->switchIndicator(is_active); + //llinfos << "Merov debug : onCurrentVoiceSessionChanged switchIndicator done" << llendl; + } + } + //llinfos << "Merov debug : onCurrentVoiceSessionChanged end" << llendl; +} + void LLConversationViewParticipant::refresh() { // Refresh the participant view from its model data @@ -453,6 +483,7 @@ void LLConversationViewParticipant::refresh() // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat mSpeakingIndicator->setIsMuted(vmi->isMuted()); + //mSpeakingIndicator->switchIndicator(true); // Do the regular upstream refresh LLFolderViewItem::refresh(); @@ -471,6 +502,7 @@ void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder) mAvatarIcon->setValue(mUUID); //Allows the speaker indicator to be activated based on the user and conversation +// llinfos << "Merov debug : setSpeakerId of " << mUUID << ", session id = " << vmi->getUUID() << llendl; mSpeakingIndicator->setSpeakerId(mUUID, vmi->getUUID()); } } diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index cc6995c207..4b2c9b2d76 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -94,7 +94,7 @@ private: bool mMinimizedMode; LLVoiceClientStatusObserver* mVoiceClientObserver; - + boost::signals2::connection mActiveVoiceChannelConnection; }; @@ -116,7 +116,7 @@ public: Params(); }; - virtual ~LLConversationViewParticipant( void ) { } + virtual ~LLConversationViewParticipant( void ); bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } virtual void refresh(); @@ -140,6 +140,8 @@ protected: void onInfoBtnClick(); private: + void onCurrentVoiceSessionChanged(const LLUUID& session_id); + LLAvatarIconCtrl* mAvatarIcon; LLButton * mInfoBtn; LLOutputMonitorCtrl* mSpeakingIndicator; @@ -156,6 +158,8 @@ private: static void initChildrenWidths(LLConversationViewParticipant* self); void updateChildren(); LLView* getItemChildView(EAvatarListItemChildIndex child_view_index); + + boost::signals2::connection mActiveVoiceChannelConnection; }; #endif // LL_LLCONVERSATIONVIEW_H diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 4a9a50d96a..3569516388 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -278,21 +278,45 @@ BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/, bool show_other_participants_speaking /* = false */) { + static LLUUID test_uuid("c684ce33-89fb-4544-8f7b-dae243c8b214"); + bool test_on = (speaker_id == test_uuid); + if (test_on) + { + llinfos << "Merov debug : setSpeakerId, this = " << this << ", session_id = " << session_id << llendl; + } if (speaker_id.isNull() && mSpeakerId.notNull()) { LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); } - if (speaker_id.isNull() || speaker_id == mSpeakerId) return; + if (speaker_id.isNull() || speaker_id == mSpeakerId) + { + if (test_on) + { + llinfos << "Merov debug : setSpeakerId, nothing done because mSpeakerId == speaker_id" << llendl; + } + return; + } if (mSpeakerId.notNull()) { + if (test_on) + { + llinfos << "Merov debug : setSpeakerId, unregisterSpeakingIndicator" << llendl; + } // Unregister previous registration to avoid crash. EXT-4782. - LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); + if (getTargetSessionID() == session_id) + { + LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); + } } mShowParticipantsSpeaking = show_other_participants_speaking; mSpeakerId = speaker_id; + if (test_on) + { + llinfos << "Merov debug : setSpeakerId, registerSpeakingIndicator" << llendl; + } LLSpeakingIndicatorManager::registerSpeakingIndicator(mSpeakerId, this, session_id); //mute management @@ -320,6 +344,7 @@ void LLOutputMonitorCtrl::onChange() // virtual void LLOutputMonitorCtrl::switchIndicator(bool switch_on) { + llinfos << "Merov debug : switchIndicator, mSpeakerId = " << mSpeakerId << ", switch_on = " << switch_on << llendl; // ensure indicator is visible in case it is not in visible chain // to be called when parent became visible next time to notify parent that visibility is changed. setVisible(TRUE); diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 900379ae1e..316a2739b8 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -155,6 +155,7 @@ void SpeakingIndicatorManager::registerSpeakingIndicator(const LLUUID& speaker_i BOOL is_in_same_voice = LLVoiceClient::getInstance()->isParticipant(speaker_id); speakers_uuids.insert(speaker_id); + llinfos << "Merov debug : registerSpeakingIndicator call switchSpeakerIndicators, switch = " << is_in_same_voice << llendl; switchSpeakerIndicators(speakers_uuids, is_in_same_voice); } @@ -195,6 +196,7 @@ SpeakingIndicatorManager::~SpeakingIndicatorManager() void SpeakingIndicatorManager::sOnCurrentChannelChanged(const LLUUID& /*session_id*/) { + llinfos << "Merov debug : sOnCurrentChannelChanged call switchSpeakerIndicators, FALSE" << llendl; switchSpeakerIndicators(mSwitchedIndicatorsOn, FALSE); mSwitchedIndicatorsOn.clear(); } @@ -208,16 +210,21 @@ void SpeakingIndicatorManager::onParticipantsChanged() LL_DEBUGS("SpeakingIndicator") << "Switching all OFF, count: " << mSwitchedIndicatorsOn.size() << LL_ENDL; // switch all indicators off + llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, FALSE" << llendl; switchSpeakerIndicators(mSwitchedIndicatorsOn, FALSE); + llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, end FALSE switch" << llendl; mSwitchedIndicatorsOn.clear(); LL_DEBUGS("SpeakingIndicator") << "Switching all ON, count: " << speakers_uuids.size() << LL_ENDL; // then switch current voice participants indicators on + llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, TRUE" << llendl; switchSpeakerIndicators(speakers_uuids, TRUE); + llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, end TRUE switch" << llendl; } void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& speakers_uuids, BOOL switch_on) { + llinfos << "Merov debug : switchSpeakerIndicators, switch_on = " << switch_on << llendl; LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); LLUUID session_id; if (voice_channel) diff --git a/indra/newview/llspeakingindicatormanager.h b/indra/newview/llspeakingindicatormanager.h index b0a147865b..c2cf2a3702 100644 --- a/indra/newview/llspeakingindicatormanager.h +++ b/indra/newview/llspeakingindicatormanager.h @@ -37,7 +37,7 @@ public: virtual ~LLSpeakingIndicator(){} virtual void switchIndicator(bool switch_on) = 0; -private: +//private: friend class SpeakingIndicatorManager; // Accessors for target voice session UUID. // They are intended to be used only from SpeakingIndicatorManager to ensure target session is -- cgit v1.2.3 From d541d99fce104d28eac378947261297461603462 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 14 Nov 2012 21:44:58 +0200 Subject: CHUI-487, CHUI-488 W.I.P. #1 (Enable flashing FUI button behavior and Implement Flashing Conversations panel line item behavior): build new class LLFlashTimer based on LLSysWellChiclet::FlashToLitTimer; prepared it for general purpose; replaced LLSysWellChiclet::FlashToLitTimer to LLFlashTimer --- indra/newview/CMakeLists.txt | 2 + indra/newview/app_settings/settings.xml | 4 +- indra/newview/llchiclet.cpp | 65 ++------------------------------- indra/newview/llchiclet.h | 5 ++- 4 files changed, 10 insertions(+), 66 deletions(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f652c9e50c..574fdc495a 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -178,6 +178,7 @@ set(viewer_SOURCE_FILES llfilepicker.cpp llfilteredwearablelist.cpp llfirstuse.cpp + llflashtimer.cpp llflexibleobject.cpp llfloaterabout.cpp llfloaterbvhpreview.cpp @@ -762,6 +763,7 @@ set(viewer_HEADER_FILES llfilepicker.h llfilteredwearablelist.h llfirstuse.h + llflashtimer.h llflexibleobject.h llfloaterabout.h llfloaterbvhpreview.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b703b9cc8e..14117ee47b 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -13142,7 +13142,7 @@ <key>Value</key> <real>50.0</real> </map> - <key>WellIconFlashCount</key> + <key>FlashCount</key> <map> <key>Comment</key> <string>Number of flashes of IM Well and Notification Well icons after which flashing buttons stay lit up. Requires restart.</string> @@ -13153,7 +13153,7 @@ <key>Value</key> <integer>3</integer> </map> - <key>WellIconFlashPeriod</key> + <key>FlashPeriod</key> <map> <key>Comment</key> <string>Period at which IM Well and Notification Well icons flash (seconds). Requires restart.</string> diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 64d8a68a99..d6860640b7 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -67,60 +67,6 @@ boost::signals2::signal<LLChiclet* (const LLUUID&), ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -/** - * Updates the Well's 'Lit' state to flash it when "new messages" are come. - * - * It gets callback which will be called 2*N times with passed period. See EXT-3147 - */ -class LLSysWellChiclet::FlashToLitTimer : public LLEventTimer -{ -public: - typedef boost::function<void()> callback_t; - - /** - * Constructor. - * - * @param count - how many times callback should be called (twice to not change original state) - * @param period - how frequently callback should be called - * @param cb - callback to be called each tick - */ - FlashToLitTimer(S32 count, F32 period, callback_t cb) - : LLEventTimer(period) - , mCallback(cb) - , mFlashCount(2 * count) - , mCurrentFlashCount(0) - { - mEventTimer.stop(); - } - - BOOL tick() - { - mCallback(); - - if (++mCurrentFlashCount == mFlashCount) mEventTimer.stop(); - return FALSE; - } - - void flash() - { - mCurrentFlashCount = 0; - mEventTimer.start(); - } - - void stopFlashing() - { - mEventTimer.stop(); - } - -private: - callback_t mCallback; - - /** - * How many times Well will blink. - */ - S32 mFlashCount; - S32 mCurrentFlashCount; -}; LLSysWellChiclet::Params::Params() : button("button") @@ -145,13 +91,8 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p) mButton = LLUICtrlFactory::create<LLButton>(button_params); addChild(mButton); - // use settings from settings.xml to be able change them via Debug settings. See EXT-5973. - // Due to Timer is implemented as derived class from EventTimer it is impossible to change period - // in runtime. So, both settings are made as required restart. - static S32 flash_to_lit_count = gSavedSettings.getS32("WellIconFlashCount"); - static F32 flash_period = gSavedSettings.getF32("WellIconFlashPeriod"); - mFlashToLitTimer = new FlashToLitTimer(flash_to_lit_count, flash_period, boost::bind(&LLSysWellChiclet::changeLitState, this)); + mFlashToLitTimer = new LLFlashTimer(boost::bind(&LLSysWellChiclet::changeLitState, this, _1)); } LLSysWellChiclet::~LLSysWellChiclet() @@ -191,7 +132,7 @@ void LLSysWellChiclet::setToggleState(BOOL toggled) { mButton->setToggleState(toggled); } -void LLSysWellChiclet::changeLitState() +void LLSysWellChiclet::changeLitState(bool blink) { setNewMessagesState(!mIsNewMessagesState); } @@ -320,7 +261,7 @@ void LLIMWellChiclet::messageCountChanged(const LLSD& session_data) // we have to flash to 'Lit' state each time new unread message is coming. if (counter > mCounter && im_not_visible) { - mFlashToLitTimer->flash(); + mFlashToLitTimer->startFlashing(); } else if (counter == 0) { diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index d6be2df103..79ffad92ef 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -29,6 +29,7 @@ #include "llavatariconctrl.h" #include "llbutton.h" +#include "llflashtimer.h" #include "llpanel.h" #include "lltextbox.h" #include "lloutputmonitorctrl.h" @@ -844,7 +845,7 @@ protected: * There is an assumption that it will be called 2*N times to do not change its start state. * @see FlashToLitTimer */ - void changeLitState(); + void changeLitState(bool blink); /** * Displays menu. @@ -860,7 +861,7 @@ protected: S32 mMaxDisplayedCount; bool mIsNewMessagesState; - FlashToLitTimer* mFlashToLitTimer; + LLFlashTimer* mFlashToLitTimer; LLContextMenu* mContextMenu; }; -- cgit v1.2.3 From bd62d1d33717536e71f5fbb5ab4a477a69494c77 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 14 Nov 2012 20:00:01 -0800 Subject: CHUI-479 : WIP : More tracing --- indra/newview/llconversationmodel.cpp | 18 ++++++++++++------ indra/newview/llconversationmodel.h | 2 +- indra/newview/lloutputmonitorctrl.cpp | 8 +++++++- indra/newview/llspeakingindicatormanager.cpp | 8 ++++---- 4 files changed, 24 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 8aa740e5d1..1c56bd672d 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -349,15 +349,21 @@ const bool LLConversationItemSession::getTime(F64& time) const return has_time; } -void LLConversationItemSession::dumpDebugData() +void LLConversationItemSession::dumpDebugData(bool dump_children) { + // Session info llinfos << "Merov debug : session " << this << ", uuid = " << mUUID << ", name = " << mName << ", is loaded = " << mIsLoaded << llendl; - LLConversationItemParticipant* participant = NULL; - child_list_t::iterator iter; - for (iter = mChildren.begin(); iter != mChildren.end(); iter++) + // Children info + if (dump_children) { - participant = dynamic_cast<LLConversationItemParticipant*>(*iter); - participant->dumpDebugData(); + for (child_list_t::iterator iter = mChildren.begin(); iter != mChildren.end(); iter++) + { + LLConversationItemParticipant* participant = dynamic_cast<LLConversationItemParticipant*>(*iter); + if (participant) + { + participant->dumpDebugData(); + } + } } } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 2ee21d0c16..dd849210a8 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -168,7 +168,7 @@ public: void addVoiceOptions(menuentry_vec_t& items); virtual const bool getTime(F64& time) const; - void dumpDebugData(); + void dumpDebugData(bool dump_children = false); private: bool mIsLoaded; // true if at least one participant has been added to the session, false otherwise diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 3569516388..063b90e76b 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -48,6 +48,8 @@ LLColor4 LLOutputMonitorCtrl::sColorBound; //F32 LLOutputMonitorCtrl::sRectWidthRatio = 0.f; //F32 LLOutputMonitorCtrl::sRectHeightRatio = 0.f; +static LLUUID test_uuid("c684ce33-89fb-4544-8f7b-dae243c8b214"); + LLOutputMonitorCtrl::Params::Params() : draw_border("draw_border"), image_mute("image_mute"), @@ -278,7 +280,6 @@ BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/, bool show_other_participants_speaking /* = false */) { - static LLUUID test_uuid("c684ce33-89fb-4544-8f7b-dae243c8b214"); bool test_on = (speaker_id == test_uuid); if (test_on) { @@ -345,6 +346,11 @@ void LLOutputMonitorCtrl::onChange() void LLOutputMonitorCtrl::switchIndicator(bool switch_on) { llinfos << "Merov debug : switchIndicator, mSpeakerId = " << mSpeakerId << ", switch_on = " << switch_on << llendl; + bool test_on = (mSpeakerId == test_uuid); + if (test_on && !switch_on) + { + llinfos << "Merov debug : switching agent off!" << llendl; + } // ensure indicator is visible in case it is not in visible chain // to be called when parent became visible next time to notify parent that visibility is changed. setVisible(TRUE); diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 316a2739b8..752218c776 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -224,13 +224,13 @@ void SpeakingIndicatorManager::onParticipantsChanged() void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& speakers_uuids, BOOL switch_on) { - llinfos << "Merov debug : switchSpeakerIndicators, switch_on = " << switch_on << llendl; LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); LLUUID session_id; if (voice_channel) { session_id = voice_channel->getSessionID(); } + llinfos << "Merov debug : switchSpeakerIndicators, switch_on = " << switch_on << ", voice channel = " << session_id << llendl; speaker_ids_t::const_iterator it_uuid = speakers_uuids.begin(); for (; it_uuid != speakers_uuids.end(); ++it_uuid) @@ -255,17 +255,17 @@ void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& spea } was_switched_on = was_switched_on || switch_current_on; + llinfos << "Merov debug : indicator for " << *it_uuid << ", switch_current_on = " << switch_current_on << ", session = " << indicator->getTargetSessionID() << llendl; indicator->switchIndicator(switch_current_on); - } if (was_found) { - LL_DEBUGS("SpeakingIndicator") << mSpeakingIndicators.count(*it_uuid) << " indicators where found" << LL_ENDL; + LL_DEBUGS("SpeakingIndicator") << mSpeakingIndicators.count(*it_uuid) << " indicators were found" << LL_ENDL; if (switch_on && !was_switched_on) { - LL_DEBUGS("SpeakingIndicator") << "but non of them where switched on" << LL_ENDL; + LL_DEBUGS("SpeakingIndicator") << "but none of them were switched on" << LL_ENDL; } if (was_switched_on) -- cgit v1.2.3 From dbc37f6ca74dba6c6d5194e0397d5cfe6f570c1d Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Thu, 15 Nov 2012 10:38:21 +0200 Subject: CHUI-397 (Delay in removing names from participant list in nearby chat) CHUI-440 (Nearby chat participant list does not clear after teleport when conversation floater is closed/minimized) fixed --- indra/llui/llfolderviewitem.h | 1 + indra/newview/llconversationview.cpp | 14 +++++++++++++- indra/newview/llspeakers.cpp | 8 ++++++++ indra/newview/llspeakers.h | 3 +++ 4 files changed, 25 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index b157aabdcf..152ca242e1 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -118,6 +118,7 @@ protected: // For now assuming all colors are the same in derived classes. static LLUIColor sFgColor; + static LLUIColor sFgDisabledColor; static LLUIColor sHighlightBgColor; static LLUIColor sHighlightFgColor; static LLUIColor sFocusOutlineColor; diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 53392ac372..d1649a93b1 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -409,6 +409,7 @@ BOOL LLConversationViewParticipant::postBuild() void LLConversationViewParticipant::draw() { static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + static LLUIColor sFgDisabledColor = LLUIColorTable::instance().getColor("MenuItemDisabledColor", DEFAULT_WHITE); static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); @@ -421,7 +422,18 @@ void LLConversationViewParticipant::draw() F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad; F32 text_left = (F32)getLabelXPos(); - LLColor4 color = mIsSelected ? sHighlightFgColor : sFgColor; + + LLColor4 color; + LLLocalSpeakerMgr *speakerMgr = LLLocalSpeakerMgr::getInstance(); + + if (speakerMgr && speakerMgr->isSpeakerToBeRemoved(mUUID)) + { + color = sFgDisabledColor; + } + else + { + color = mIsSelected ? sHighlightFgColor : sFgColor; + } drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); drawLabel(font, text_left, y, color, right_x); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 5036334bdd..88f29d7587 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -254,6 +254,10 @@ bool LLSpeakersDelayActionsStorage::onTimerActionCallback(const LLUUID& speaker_ return true; } +bool LLSpeakersDelayActionsStorage::isTimerStarted(const LLUUID& speaker_id) +{ + return (mActionTimersMap.size() > 0) && (mActionTimersMap.find(speaker_id) != mActionTimersMap.end()); +} // // ModerationResponder @@ -603,6 +607,10 @@ const LLUUID LLSpeakerMgr::getSessionID() return mVoiceChannel->getSessionID(); } +bool LLSpeakerMgr::isSpeakerToBeRemoved(const LLUUID& speaker_id) +{ + return mSpeakerDelayRemover && mSpeakerDelayRemover->isTimerStarted(speaker_id); +} void LLSpeakerMgr::setSpeakerTyping(const LLUUID& speaker_id, BOOL typing) { diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 8ab08661d3..7d518fe07b 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -193,6 +193,8 @@ public: void unsetActionTimer(const LLUUID& speaker_id); void removeAllTimers(); + + bool isTimerStarted(const LLUUID& speaker_id); private: /** * Callback of the each instance of LLSpeakerActionTimer. @@ -237,6 +239,7 @@ public: void getSpeakerList(speaker_list_t* speaker_list, BOOL include_text); LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; } const LLUUID getSessionID(); + bool isSpeakerToBeRemoved(const LLUUID& speaker_id); /** * Removes avaline speaker. -- cgit v1.2.3 From 0b910871ab2935bde912314515f8b53ec3ff754e Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 15 Nov 2012 13:12:04 +0200 Subject: CHUI-487, CHUI-488 W.I.P. #2 (Enable flashing FUI button behavior and Implement Flashing Conversations panel line item behavior): build new class LLFlashTimer based on LLSysWellChiclet::FlashToLitTimer; prepared it for general purpose; replaced LLSysWellChiclet::FlashToLitTimer to LLFlashTimer --- indra/newview/llflashtimer.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++ indra/newview/llflashtimer.h | 62 ++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 indra/newview/llflashtimer.cpp create mode 100644 indra/newview/llflashtimer.h (limited to 'indra') diff --git a/indra/newview/llflashtimer.cpp b/indra/newview/llflashtimer.cpp new file mode 100644 index 0000000000..f44ca9f90c --- /dev/null +++ b/indra/newview/llflashtimer.cpp @@ -0,0 +1,72 @@ +/** + * @file llflashtimer.cpp + * @brief LLFlashTimer class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" + +#include "llflashtimer.h" +#include "llviewercontrol.h" + +LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) + : LLEventTimer(period) + , mCallback(cb) + , mCurrentTickCount(0) +{ + mEventTimer.stop(); + + // By default use settings from settings.xml to be able change them via Debug settings. See EXT-5973. + // Due to Timer is implemented as derived class from EventTimer it is impossible to change period + // in runtime. So, both settings are made as required restart. + mFlashCount = 2 * ((count>0)? count : gSavedSettings.getS32("FlashCount")); + if (mPeriod<=0) + { + mPeriod = gSavedSettings.getF32("FlashPeriod"); + } +} + +BOOL LLFlashTimer::tick() +{ + bool blink = !(mCurrentTickCount % 2); + mCallback(blink); + + if (++mCurrentTickCount >= mFlashCount) + { + mEventTimer.stop(); + } + + return FALSE; +} + +void LLFlashTimer::startFlashing() +{ + mCurrentTickCount = 0; + mEventTimer.start(); +} + +void LLFlashTimer::stopFlashing() +{ + mEventTimer.stop(); +} diff --git a/indra/newview/llflashtimer.h b/indra/newview/llflashtimer.h new file mode 100644 index 0000000000..95e458dff6 --- /dev/null +++ b/indra/newview/llflashtimer.h @@ -0,0 +1,62 @@ +/** + * @file llflashtimer.h + * @brief LLFlashTimer class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_FLASHTIMER_H +#define LL_FLASHTIMER_H + +#include "lleventtimer.h" + +class LLFlashTimer : public LLEventTimer +{ +public: + + typedef boost::function<void (bool)> callback_t; + + /** + * Constructor. + * + * @param count - how many times callback should be called (twice to not change original state) + * @param period - how frequently callback should be called + * @param cb - callback to be called each tick + */ + LLFlashTimer(callback_t cb, S32 count = 0, F32 period = 0.0); + ~LLFlashTimer() {}; + + /*virtual*/ BOOL tick(); + + void startFlashing(); + void stopFlashing(); + +private: + callback_t mCallback; + /** + * How many times Well will blink. + */ + S32 mFlashCount; + S32 mCurrentTickCount; +}; + +#endif /* LL_FLASHTIMER_H */ -- cgit v1.2.3 From 70b9dd6ee6af483bf1c96631bb25fd6a3703b351 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Thu, 15 Nov 2012 10:41:53 -0800 Subject: CHUI-524: FIX Removing a function call that results in a circular logic loop and an eventual stack overflow crash. --- indra/newview/llfloaterimsessiontab.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 3a1cc2880a..26a97ea422 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -313,7 +313,13 @@ void LLFloaterIMSessionTab::onFocusReceived() if (container) { container->selectConversationPair(mSessionID, true); + // XXX stinson 11/15/2012 : calling show stub from this focus handler results in a circular + // logic loop of function calls that eventually result in a stack overflow. + // See CHUI-524 for documentation +#define XXX_STINSON_HACK_CHUI_524 1 +#if !XXX_STINSON_HACK_CHUI_524 container->showStub(! getHost()); +#endif } } -- cgit v1.2.3 From 4ea44918dd040520bdd8eb1e52f2b6ba6cfa6f8b Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Fri, 16 Nov 2012 19:36:46 +0200 Subject: CHUI-525 FIXED Tootlips are added for Info buttons --- indra/newview/skins/default/xui/en/panel_avatar_list_item.xml | 1 + indra/newview/skins/default/xui/en/panel_group_list_item.xml | 1 + 2 files changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index b7c58eb6ab..aa1b929412 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -129,6 +129,7 @@ left_pad="3" right="-53" name="info_btn" + tool_tip="More info" tab_stop="false" top_delta="0" width="16" /> diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item.xml b/indra/newview/skins/default/xui/en/panel_group_list_item.xml index 12735026fa..cfe3aeb7c9 100644 --- a/indra/newview/skins/default/xui/en/panel_group_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_group_list_item.xml @@ -56,6 +56,7 @@ left_pad="3" right="-31" name="info_btn" + tool_tip="More info" tab_stop="false" top_delta="-2" width="16" /> -- cgit v1.2.3 From 16f5a67e6550c2041b69b5c8523ad9884d7110f1 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Thu, 15 Nov 2012 23:35:14 +0200 Subject: CHUI-442 FIXED Nearby chat does not open conversations floater when clicking first nearby chat toast in a session --- indra/newview/llfloaterimsessiontab.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 3a1cc2880a..da77ca0079 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -165,6 +165,11 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id) || gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) { floater_container->addFloater(conversp, TRUE, LLTabContainer::END); + + if (!floater_container->getVisible()) + { + LLFloaterReg::toggleInstanceOrBringToFront("im_container"); + } } else { -- cgit v1.2.3 From e89616aac812a7c6080d577f8a284f6df56a51ea Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Thu, 15 Nov 2012 15:11:22 -0800 Subject: Backed out changeset: 80bab29003f8 Removing hack fix for CHUI-524. --- indra/newview/llfloaterimsessiontab.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 26a97ea422..3a1cc2880a 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -313,13 +313,7 @@ void LLFloaterIMSessionTab::onFocusReceived() if (container) { container->selectConversationPair(mSessionID, true); - // XXX stinson 11/15/2012 : calling show stub from this focus handler results in a circular - // logic loop of function calls that eventually result in a stack overflow. - // See CHUI-524 for documentation -#define XXX_STINSON_HACK_CHUI_524 1 -#if !XXX_STINSON_HACK_CHUI_524 container->showStub(! getHost()); -#endif } } -- cgit v1.2.3 From 37d7f469055d3ba4b81815fa2ac8459022e1e3cf Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Thu, 15 Nov 2012 15:32:02 -0800 Subject: CHUI-524: The root reason of crash was in the infinity recursion in the chain of calls LLFloater::setFocus->LLFloater::setFrontmost->LLFloaterView::bringToFront. And problem was not related to CHUI-362. Reviewed by Stinson. --- indra/llui/llfloater.cpp | 10 +++++++++- indra/llui/llfloater.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 0e57ba02bf..1b6e4ed0e5 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2234,7 +2234,8 @@ LLFloaterView::LLFloaterView (const Params& p) mFocusCycleMode(FALSE), mMinimizePositionVOffset(0), mSnapOffsetBottom(0), - mSnapOffsetRight(0) + mSnapOffsetRight(0), + mFrontChild(NULL) { mSnapView = getHandle(); } @@ -2383,6 +2384,13 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) { + if (mFrontChild == child) + { + return; + } + + mFrontChild = child; + // *TODO: make this respect floater's mAutoFocus value, instead of // using parameter if (child->getHost()) diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 07b79d5523..ca0710cdc1 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -576,6 +576,7 @@ private: S32 mMinimizePositionVOffset; typedef std::vector<std::pair<LLHandle<LLFloater>, boost::signals2::connection> > hidden_floaters_t; hidden_floaters_t mHiddenFloaters; + LLFloater * mFrontChild; }; // -- cgit v1.2.3 From d3474c6eaf5f26986e7988f4ca773f67e034c49d Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 15 Nov 2012 15:42:22 -0800 Subject: CHUI-489: Now sounds exist for teleport and inventory offers. The sound is specified in notifications.xml. Also changes for CHUI 486, which allow the user to set preferences for hearing sounds for a New Conversation, Incoming Voice Call, Teleport Offer and Inventory Offer. --- indra/llui/llfloater.cpp | 15 ++++++++++++++- indra/llui/llnotifications.cpp | 5 +++++ indra/llui/llnotifications.h | 1 + indra/newview/llimview.cpp | 6 +++++- indra/newview/lltoastnotifypanel.cpp | 15 +++++++++++++++ indra/newview/skins/default/xui/en/notifications.xml | 6 ++++-- .../skins/default/xui/en/panel_preferences_chat.xml | 1 + 7 files changed, 45 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 0e57ba02bf..3ab66f3321 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -64,6 +64,8 @@ // use this to control "jumping" behavior when Ctrl-Tabbing const S32 TABBED_FLOATER_OFFSET = 0; +extern LLControlGroup gSavedSettings; + namespace LLInitParam { void TypeValues<LLFloaterEnums::EOpenPositioning>::declareValues() @@ -660,7 +662,18 @@ void LLFloater::openFloater(const LLSD& key) && !getFloaterHost() && (!getVisible() || isMinimized())) { - make_ui_sound("UISndWindowOpen"); + bool playSound = true; + + //Don't play a sound for incoming voice call based upon chat preference setting + if(getName() == "incoming call" && gSavedSettings.getBOOL("PlaySoundIncomingVoiceCall") == FALSE) + { + playSound = false; + } + + if(playSound) + { + make_ui_sound("UISndWindowOpen"); + } } //RN: for now, we don't allow rehosting from one multifloater to another diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 929b7da081..fe84dbbdaf 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -899,6 +899,11 @@ bool LLNotification::hasFormElements() const return mTemplatep->mForm->getNumElements() != 0; } +void LLNotification::playSound() +{ + LLUI::sAudioCallback(mTemplatep->mSoundEffect); +} + LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const { return mTemplatep->mCombineBehavior; diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index c677dfe298..088931858a 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -524,6 +524,7 @@ public: bool canLogToIM() const; bool canShowToast() const; bool hasFormElements() const; + void playSound(); typedef enum e_combine_behavior { diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 0f4bbd054a..f7b182e891 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2494,7 +2494,11 @@ void LLIMMgr::addMessage( return; } - make_ui_sound("UISndNewIncomingIMSession"); + //Play sound for new conversations + if(gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE) + { + make_ui_sound("UISndNewIncomingIMSession"); + } } bool skip_message = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index ccad49bc30..8672dc479d 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -493,6 +493,21 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) } // adjust panel's height to the text size snapToMessageHeight(mTextBox, MAX_LENGTH); + + bool playSound = true; + + if((mNotification->getName() == "UserGiveItem" + && gSavedSettings.getBOOL("PlaySoundInventoryOffer") == FALSE) + || mNotification->getName() == "TeleportOffered" + && gSavedSettings.getBOOL("PlaySoundTeleportOffer") == FALSE) + { + playSound = false; + } + + if(playSound) + { + mNotification->playSound(); + } } diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 6c2ad869ac..bf2bfaf386 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6460,7 +6460,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th icon="notify.tga" name="UserGiveItem" log_to_im ="true" - type="offer"> + type="offer" + sound="UISndNewIncomingIMSession"> [NAME_SLURL] has given you this [OBJECTTYPE]: [ITEM_SLURL] <form name="form"> @@ -6517,7 +6518,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th name="TeleportOffered" log_to_im="true" log_to_chat="false" - type="offer"> + type="offer" + sound="UISndNewIncomingIMSession"> [NAME_SLURL] has offered to teleport you to their location: “[MESSAGE]” diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 8ab5c9a99c..712e8bff7f 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -322,6 +322,7 @@ name="incoming_voice_call" width="150" /> <check_box + enabled="false" control_name="PlaySoundGroupChatMessages" height="16" label="Group chat messages" -- cgit v1.2.3 From 89f7335a52ec9955432dbe8bfa5903f605b7362c Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 15 Nov 2012 17:34:34 -0800 Subject: CHUI-489: Found a bug in last commit for this issue. The sound notification (for inventory/teleport offer) would be played for the toast popup as well as once the conversations floater was opened. And also when a button was clicked in the conversation floater to 'accept' or 'deny' the offer. Now only playing the sound notification when the initial offer has been made. --- indra/newview/llnotificationofferhandler.cpp | 17 +++++++++++++++++ indra/newview/lltoastnotifypanel.cpp | 15 +-------------- 2 files changed, 18 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 6e641575fa..8b7cac9f4b 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -117,6 +117,23 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->addToast(p); + + bool playSound = true; + + //Play notification sound for inventory offer and teleport offer based upon chat preference + if((notification->getName() == "UserGiveItem" + && gSavedSettings.getBOOL("PlaySoundInventoryOffer") == FALSE) + || notification->getName() == "TeleportOffered" + && gSavedSettings.getBOOL("PlaySoundTeleportOffer") == FALSE) + { + playSound = false; + } + + if(playSound) + { + notification->playSound(); + } + } if (notification->canLogToIM()) diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 8672dc479d..844d7314d9 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -494,20 +494,7 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) // adjust panel's height to the text size snapToMessageHeight(mTextBox, MAX_LENGTH); - bool playSound = true; - - if((mNotification->getName() == "UserGiveItem" - && gSavedSettings.getBOOL("PlaySoundInventoryOffer") == FALSE) - || mNotification->getName() == "TeleportOffered" - && gSavedSettings.getBOOL("PlaySoundTeleportOffer") == FALSE) - { - playSound = false; - } - - if(playSound) - { - mNotification->playSound(); - } + } -- cgit v1.2.3 From ec5d1e48c4071500400b885e5893373bab0e3d99 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 15 Nov 2012 18:07:57 -0800 Subject: CHUI-479 : WIP : Introduce a publicly available LLSpeakingIndicatorManager::updateSpeakingIndicators() method so to reset all indicators when creating new dialogs. --- indra/newview/llconversationview.cpp | 25 ++++++++++++------------- indra/newview/lloutputmonitorctrl.cpp | 5 ----- indra/newview/llspeakingindicatormanager.cpp | 28 ++++++++++++++++++---------- indra/newview/llspeakingindicatormanager.h | 5 +++++ 4 files changed, 35 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index cc7a76e353..d971c943f0 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -307,7 +307,9 @@ void LLConversationViewSession::refresh() mSessionTitle->setText(vmi->getDisplayName()); } - // Note: for the moment, all that needs to be done is done by LLFolderViewItem::refresh() + // Update all speaking indicators + llinfos << "Merov debug : LLConversationViewSession::refresh, updateSpeakingIndicators" << llendl; + LLSpeakingIndicatorManager::updateSpeakingIndicators(); // Do the regular upstream refresh LLFolderViewFolder::refresh(); @@ -327,7 +329,6 @@ void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& sessi mSpeakingIndicator->setSpeakerId(is_active ? gAgentID : LLUUID::null); } - llinfos << "Merov debug : onCurrentVoiceSessionChanged, switchIndicator is_active = " << is_active << llendl; mSpeakingIndicator->switchIndicator(is_active); mCallIconLayoutPanel->setVisible(is_active); } @@ -456,34 +457,32 @@ void LLConversationViewParticipant::onCurrentVoiceSessionChanged(const LLUUID& s { llinfos << "Merov debug : onCurrentVoiceSessionChanged begin, uuid = " << mUUID << ", session_id = " << session_id << llendl; LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem()); - //llinfos << "Merov debug : onCurrentVoiceSessionChanged participant_model = " << participant_model << llendl; if (participant_model) { - //llinfos << "Merov debug : onCurrentVoiceSessionChanged enter if 1" << llendl; LLConversationItemSession* parent_session = participant_model->getParentSession(); - //llinfos << "Merov debug : onCurrentVoiceSessionChanged parent_session = " << parent_session << llendl; if (parent_session) { - //llinfos << "Merov debug : onCurrentVoiceSessionChanged enter if 2" << llendl; bool is_active = (parent_session->getUUID() == session_id); - //llinfos << "Merov debug : onCurrentVoiceSessionChanged, is_active = " << is_active << llendl; mSpeakingIndicator->switchIndicator(is_active); - //llinfos << "Merov debug : onCurrentVoiceSessionChanged switchIndicator done" << llendl; } } - //llinfos << "Merov debug : onCurrentVoiceSessionChanged end" << llendl; } void LLConversationViewParticipant::refresh() { // Refresh the participant view from its model data - LLConversationItemParticipant* vmi = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem()); - vmi->resetRefresh(); + LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem()); + participant_model->resetRefresh(); // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat - mSpeakingIndicator->setIsMuted(vmi->isMuted()); - //mSpeakingIndicator->switchIndicator(true); + mSpeakingIndicator->setIsMuted(participant_model->isMuted()); + //LLConversationItemSession* parent_session = participant_model->getParentSession(); + //if (parent_session) + //{ + // bool is_active = (parent_session->getUUID() == session_id); + // mSpeakingIndicator->switchIndicator(is_active); + //} // Do the regular upstream refresh LLFolderViewItem::refresh(); diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 063b90e76b..536f1fbd73 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -346,11 +346,6 @@ void LLOutputMonitorCtrl::onChange() void LLOutputMonitorCtrl::switchIndicator(bool switch_on) { llinfos << "Merov debug : switchIndicator, mSpeakerId = " << mSpeakerId << ", switch_on = " << switch_on << llendl; - bool test_on = (mSpeakerId == test_uuid); - if (test_on && !switch_on) - { - llinfos << "Merov debug : switching agent off!" << llendl; - } // ensure indicator is visible in case it is not in visible chain // to be called when parent became visible next time to notify parent that visibility is changed. setVisible(TRUE); diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 752218c776..d9f9ed5966 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -74,6 +74,16 @@ public: */ void unregisterSpeakingIndicator(const LLUUID& speaker_id, const LLSpeakingIndicator* const speaking_indicator); + /** + * Callback of changing voice participant list (from LLVoiceClientParticipantObserver). + * + * Switches off indicators had been switched on and switches on indicators of current participants list. + * There is only a few indicators in lists should be switched off/on. + * So, method does not calculate difference between these list it only switches off already + * switched on indicators and switches on indicators of voice channel participants + */ + void onParticipantsChanged(); + private: typedef std::set<LLUUID> speaker_ids_t; typedef std::multimap<LLUUID, LLSpeakingIndicator*> speaking_indicators_mmap_t; @@ -93,16 +103,6 @@ private: */ void sOnCurrentChannelChanged(const LLUUID& session_id); - /** - * Callback of changing voice participant list (from LLVoiceClientParticipantObserver). - * - * Switches off indicators had been switched on and switches on indicators of current participants list. - * There is only a few indicators in lists should be switched off/on. - * So, method does not calculate difference between these list it only switches off already - * switched on indicators and switches on indicators of voice channel participants - */ - void onParticipantsChanged(); - /** * Changes state of indicators specified by LLUUIDs * @@ -321,5 +321,13 @@ void LLSpeakingIndicatorManager::unregisterSpeakingIndicator(const LLUUID& speak } } +void LLSpeakingIndicatorManager::updateSpeakingIndicators() +{ + if(SpeakingIndicatorManager::instanceExists()) + { + SpeakingIndicatorManager::instance().onParticipantsChanged(); + } +} + // EOF diff --git a/indra/newview/llspeakingindicatormanager.h b/indra/newview/llspeakingindicatormanager.h index c2cf2a3702..8ee368e258 100644 --- a/indra/newview/llspeakingindicatormanager.h +++ b/indra/newview/llspeakingindicatormanager.h @@ -78,6 +78,11 @@ namespace LLSpeakingIndicatorManager * @param speaking_indicator instance of the speaker indicator to be unregistered. */ void unregisterSpeakingIndicator(const LLUUID& speaker_id, const LLSpeakingIndicator* const speaking_indicator); + + /** + * Switch on/off registered speaking indicator according to the most current voice client status + */ + void updateSpeakingIndicators(); } #endif // LL_LLSPEAKINGINDICATORMANAGER_H -- cgit v1.2.3 From 568d818ffe214c358f92717ceb86dd20cb4aed26 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Thu, 15 Nov 2012 19:08:08 -0800 Subject: CHUI-518: WIP First pass as implementing auto-reject voice calls in do not disturb mode. --- indra/newview/llimview.cpp | 16 +++++++++++----- indra/newview/llviewermessage.cpp | 4 +--- indra/newview/llviewermessage.h | 2 ++ indra/newview/skins/default/xui/en/notifications.xml | 1 + indra/newview/skins/default/xui/en/strings.xml | 3 ++- 5 files changed, 17 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 0bb370e6fe..50e2b48f30 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -64,6 +64,7 @@ #include "lltoolbarview.h" #include "llviewercontrol.h" #include "llviewerparcelmgr.h" +#include "message.h" const static std::string ADHOC_NAME_SUFFIX(" Conference"); @@ -2801,12 +2802,17 @@ void LLIMMgr::inviteToSession( if (voice_invite) { - if ( // if we are rejecting group calls - (gSavedSettings.getBOOL("VoiceCallsRejectGroup") && notify_box_type == "VoiceInviteGroup") || - // or we're rejecting non-friend voice calls and this isn't a friend - (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL)) - ) + bool isRejectGroupCall = (gSavedSettings.getBOOL("VoiceCallsRejectGroup") && (notify_box_type == "VoiceInviteGroup")); + bool isRejectNonFriendCall = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL)); + bool isRejectDoNotDisturb = gAgent.isDoNotDisturb(); + if (isRejectGroupCall || isRejectNonFriendCall || isRejectDoNotDisturb) { + if (isRejectDoNotDisturb && !isRejectGroupCall && !isRejectNonFriendCall) + { + LLSD args; + LLIMMgr::getInstance()->addSystemMessage(session_id, "you_auto_rejected_call", args); + send_do_not_disturb_message(gMessageSystem, caller_id, session_id); + } // silently decline the call LLIncomingCallDialog::processCallResponse(1, payload); return; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 56c9f81259..e21db146db 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -179,8 +179,6 @@ const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = FALSE // TeleportYourAgent }; -static void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id = LLUUID::null); - bool friendship_offer_callback(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); @@ -3240,7 +3238,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } } -static void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id) +void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id) { if (gAgent.isDoNotDisturb()) { diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index b298f0060b..447fdeb9c7 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -152,6 +152,8 @@ void send_group_notice(const LLUUID& group_id, const std::string& message, const LLInventoryItem* item); +void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id = LLUUID::null); + void handle_lure(const LLUUID& invitee); void handle_lure(const uuid_vec_t& ids); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 6c2ad869ac..eaa020ff49 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3695,6 +3695,7 @@ Do Not Disturb is on. You will not be notified of incoming communications. - Other residents will receive your Do Not Disturb response (set in Preferences > General). - Teleportation offers will be declined. +- Voice calls will be rejected. - Inventory offers will go to your Trash. <usetemplate ignoretext="I change my status to Do Not Disturb mode" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 8489e8ca0f..18b914c764 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3384,7 +3384,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="answered_call">Your call has been answered</string> <string name="you_started_call">You started a voice call</string> <string name="you_joined_call">You joined the voice call</string> - <string name="name_started_call">[NAME] started a voice call</string> + <string name="you_auto_rejected_call-im">You automatically rejected the voice call while 'Do Not Disturb' was on.</string> + <string name="name_started_call">[NAME] started a voice call</string> <string name="ringing-im"> Joining voice call... -- cgit v1.2.3 From 987350fcb3cf2da03b70ac3fbadb0429f523d07a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 15 Nov 2012 19:24:45 -0800 Subject: CHUI-489: Code review cleanup for both CHUI-489 and CHUI-486. This should be last commit for CHUI-489. --- indra/llui/llfloater.cpp | 7 +------ indra/llui/llnotifications.cpp | 7 ++++--- indra/llui/llnotificationtemplate.h | 6 ++---- indra/newview/llnotificationofferhandler.cpp | 16 +++++----------- 4 files changed, 12 insertions(+), 24 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index a3b5fb993d..ada2bde55e 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -662,13 +662,8 @@ void LLFloater::openFloater(const LLSD& key) && !getFloaterHost() && (!getVisible() || isMinimized())) { - bool playSound = true; - //Don't play a sound for incoming voice call based upon chat preference setting - if(getName() == "incoming call" && gSavedSettings.getBOOL("PlaySoundIncomingVoiceCall") == FALSE) - { - playSound = false; - } + bool playSound = !(getName() == "incoming call" && gSavedSettings.getBOOL("PlaySoundIncomingVoiceCall") == FALSE); if(playSound) { diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index fe84dbbdaf..9618c002f5 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -413,12 +413,13 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()), mLogToChat(p.log_to_chat), mLogToIM(p.log_to_im), - mShowToast(p.show_toast) + mShowToast(p.show_toast), + mSoundName("") { if (p.sound.isProvided() && LLUI::sSettingGroups["config"]->controlExists(p.sound)) { - mSoundEffect = LLUUID(LLUI::sSettingGroups["config"]->getString(p.sound)); + mSoundName = p.sound; } BOOST_FOREACH(const LLNotificationTemplate::UniquenessContext& context, p.unique.contexts) @@ -901,7 +902,7 @@ bool LLNotification::hasFormElements() const void LLNotification::playSound() { - LLUI::sAudioCallback(mTemplatep->mSoundEffect); + make_ui_sound(mTemplatep->mSoundName.c_str()); } LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index 9434efe1b9..906b83a400 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -323,10 +323,8 @@ struct LLNotificationTemplate LLNotificationFormPtr mForm; // default priority for notifications of this type ENotificationPriority mPriority; - // UUID of the audio file to be played when this notification arrives - // this is loaded as a name, but looked up to get the UUID upon template load. - // If null, it wasn't specified. - LLUUID mSoundEffect; + // Stores the sound name which can then be used to play the sound using make_ui_sound + std::string mSoundName; // List of tags that rules can match against. std::list<std::string> mTags; diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 8b7cac9f4b..91003c7d53 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -118,22 +118,16 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) if(channel) channel->addToast(p); - bool playSound = true; - - //Play notification sound for inventory offer and teleport offer based upon chat preference - if((notification->getName() == "UserGiveItem" - && gSavedSettings.getBOOL("PlaySoundInventoryOffer") == FALSE) - || notification->getName() == "TeleportOffered" - && gSavedSettings.getBOOL("PlaySoundTeleportOffer") == FALSE) - { - playSound = false; - } + //Will not play a notification sound for inventory and teleport offer based upon chat preference + bool playSound = !((notification->getName() == "UserGiveItem" + && gSavedSettings.getBOOL("PlaySoundInventoryOffer") == FALSE) + || notification->getName() == "TeleportOffered" + && gSavedSettings.getBOOL("PlaySoundTeleportOffer") == FALSE); if(playSound) { notification->playSound(); } - } if (notification->canLogToIM()) -- cgit v1.2.3 From 50b69c3f97c0b58791f7dd67f8b2fbdc9e8ef503 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 16 Nov 2012 12:38:40 +0200 Subject: CHUI-487, CHUI-488 W.I.P. #3 (Enable flashing FUI button behavior and Implement Flashing Conversations panel line item behavior): implemented conversation's item flashing --- indra/llui/llbutton.cpp | 6 +++++- indra/llui/llfolderviewitem.cpp | 16 ++++++++++++---- indra/llui/llfolderviewitem.h | 2 ++ indra/newview/llflashtimer.cpp | 14 ++++++++++++-- indra/newview/llflashtimer.h | 6 +++++- indra/newview/llfloaterimcontainer.cpp | 11 +++++++++++ indra/newview/llfloaterimcontainer.h | 1 + 7 files changed, 48 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 705fe16559..3b9076ee54 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -176,7 +176,11 @@ LLButton::LLButton(const LLButton::Params& p) { static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0); static Params default_params(LLUICtrlFactory::getDefaultParams<LLButton>()); - +if (this->getName() == "chat") +{ +bool q = false; +q = !q; +} if (!p.label_selected.isProvided()) { mSelectedLabel = mUnselectedLabel; diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 822534ffcf..90568f344a 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -23,9 +23,11 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ + +#include "../newview/llflashtimer.h" + #include "linden_common.h" #include "llfolderviewitem.h" - #include "llfolderview.h" #include "llfolderviewmodel.h" #include "llpanel.h" @@ -142,6 +144,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mArrowSize(p.arrow_size), mMaxFolderItemOverlap(p.max_folder_item_overlap) { + mFlashTimer = new LLFlashTimer(); + sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); @@ -676,12 +680,16 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo const S32 focus_bottom = getRect().getHeight() - mItemHeight; const bool folder_open = (getRect().getHeight() > mItemHeight + 4); const S32 FOCUS_LEFT = 1; + bool flashing = mFlashTimer->isFlashing(); + + if (flashing? mFlashTimer->isHighlight() : mIsSelected) // always render "current" item (only render other selected items if + // mShowSingleSelection is FALSE) or flashing item - if (mIsSelected) // always render "current" item. Only render other selected items if mShowSingleSelection is FALSE { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLColor4 bg_color = bgColor; - if (!mIsCurSelection) + bool selection = flashing? mFlashTimer->isHighlight() : mIsCurSelection; + if (!selection) { // do time-based fade of extra objects F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); @@ -701,7 +709,7 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo getRect().getWidth() - 2, focus_bottom, bg_color, hasKeyboardFocus); - if (mIsCurSelection) + if (selection) { gl_rect_2d(FOCUS_LEFT, focus_top, diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 152ca242e1..c16d65206f 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -29,6 +29,7 @@ #include "llview.h" #include "lluiimage.h" +class LLFlashTimer; class LLFolderView; class LLFolderViewModelItem; class LLFolderViewFolder; @@ -272,6 +273,7 @@ public: private: static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts + LLFlashTimer* mFlashTimer; }; diff --git a/indra/newview/llflashtimer.cpp b/indra/newview/llflashtimer.cpp index f44ca9f90c..2feacfa218 100644 --- a/indra/newview/llflashtimer.cpp +++ b/indra/newview/llflashtimer.cpp @@ -29,11 +29,13 @@ #include "llflashtimer.h" #include "llviewercontrol.h" +#include "lleventtimer.h" LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) : LLEventTimer(period) , mCallback(cb) , mCurrentTickCount(0) + , mIsFlashing(false) { mEventTimer.stop(); @@ -49,8 +51,11 @@ LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) BOOL LLFlashTimer::tick() { - bool blink = !(mCurrentTickCount % 2); - mCallback(blink); + mIsHighlight = !(mCurrentTickCount % 2); + if (mCallback) + { + mCallback(mIsHighlight); + } if (++mCurrentTickCount >= mFlashCount) { @@ -63,10 +68,15 @@ BOOL LLFlashTimer::tick() void LLFlashTimer::startFlashing() { mCurrentTickCount = 0; + mIsFlashing = true; mEventTimer.start(); } void LLFlashTimer::stopFlashing() { + mIsFlashing = false; + mIsHighlight = false; mEventTimer.stop(); } + + diff --git a/indra/newview/llflashtimer.h b/indra/newview/llflashtimer.h index 95e458dff6..c030edfc52 100644 --- a/indra/newview/llflashtimer.h +++ b/indra/newview/llflashtimer.h @@ -42,13 +42,15 @@ public: * @param period - how frequently callback should be called * @param cb - callback to be called each tick */ - LLFlashTimer(callback_t cb, S32 count = 0, F32 period = 0.0); + LLFlashTimer(callback_t cb = NULL, S32 count = 0, F32 period = 0.0); ~LLFlashTimer() {}; /*virtual*/ BOOL tick(); void startFlashing(); void stopFlashing(); + bool isFlashing() {return mIsFlashing;} + bool isHighlight() {return mIsHighlight;} private: callback_t mCallback; @@ -57,6 +59,8 @@ private: */ S32 mFlashCount; S32 mCurrentTickCount; + bool mIsHighlight; + bool mIsFlashing; }; #endif /* LL_FLASHTIMER_H */ diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index aebfdb5bce..da6f3a484d 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1154,6 +1154,7 @@ void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) } } + // Synchronous select the conversation item and the conversation floater BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget) { @@ -1596,4 +1597,14 @@ void LLFloaterIMContainer::reSelectConversation() } +void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id) +{ + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); + if (widget) + { + widget->; + } + +} + // EOF diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index afc8d00174..443688668b 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -164,6 +164,7 @@ public: void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); void setNearbyDistances(); void reSelectConversation(); + void flashConversationItemWidget(const LLUUID& session_id); private: LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); -- cgit v1.2.3 From ed3f43aec48097c56d617a8948d2577624762a88 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 16 Nov 2012 11:14:12 -0800 Subject: CHUI-479 : WIP : Tracing of LLIMModel::processSessionInitializedReply (to be deleted). --- indra/newview/llfloaterimcontainer.cpp | 25 +++++++++++++++++++++++-- indra/newview/llfloaterimsessiontab.cpp | 1 + 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 2707e3dcbb..af090338d7 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -98,6 +98,7 @@ LLFloaterIMContainer::~LLFloaterIMContainer() void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { + llinfos << "Merov debug : sessionAdded, uuid = " << session_id << ", name = " << name << llendl; addConversationListItem(session_id); LLFloaterIMSessionTab::addToHost(session_id); } @@ -109,14 +110,33 @@ void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std: void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { + llinfos << "Merov debug : sessionVoiceOrIMStarted, uuid = " << session_id << llendl; addConversationListItem(session_id); LLFloaterIMSessionTab::addToHost(session_id); } void LLFloaterIMContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) { - // *TODO: We should do this *without* delete and recreate - addConversationListItem(new_session_id, removeConversationListItem(old_session_id)); + llinfos << "Merov debug : sessionIDUpdated, old_session_id = " << old_session_id << ", new_session_id = " << new_session_id << llendl; + // Retrieve the session LLFloaterIMSessionTab + // just close it: that should erase the mSession, close the tab and remove the list item + // *TODO : take the mSessions element (pointing to the tab) out of the list + //bool change_focus = removeConversationListItem(old_session_id); + // *TODO : detach the old tab from the host + // *TODO : delete the tab (that's one thing that's reentrant) + LLFloater* floaterp = get_ptr_in_map(mSessions, old_session_id); + if (floaterp) + { + llinfos << "Merov debug : closeFloater, start" << llendl; + floaterp->closeFloater(); + llinfos << "Merov debug : closeFloater, end" << llendl; + } + bool change_focus = false; + llinfos << "Merov debug : addConversationListItem" << llendl; + addConversationListItem(new_session_id, change_focus); + llinfos << "Merov debug : addToHost" << llendl; + LLFloaterIMSessionTab::addToHost(new_session_id); + llinfos << "Merov debug : end sessionIDUpdated" << llendl; } void LLFloaterIMContainer::sessionRemoved(const LLUUID& session_id) @@ -1300,6 +1320,7 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) { + llinfos << "Merov debug : removeConversationListItem, uuid = " << uuid << llendl; // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 6b13f5f381..6fbc713590 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -721,6 +721,7 @@ void LLFloaterIMSessionTab::onClose(bool app_quitting) LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); if (im_box) { + llinfos << "Merov debug : LLFloaterIMSessionTab::onClose, mKey = " << mKey << llendl; im_box->removeConversationListItem(mKey); } } -- cgit v1.2.3 From e298c2ded8e25a28127c668cf30a74a25c139041 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 16 Nov 2012 22:36:12 +0200 Subject: CHUI-487, CHUI-488 FIXED (Enable flashing FUI button behavior and Implement Flashing Conversations panel line item behavior): implemented FUI button flashing; clean up code --- indra/llui/CMakeLists.txt | 2 + indra/llui/llbutton.cpp | 46 ++++++++---------- indra/llui/llbutton.h | 6 +-- indra/llui/llflashtimer.cpp | 80 ++++++++++++++++++++++++++++++++ indra/llui/llflashtimer.h | 67 +++++++++++++++++++++++++++ indra/llui/llfolderviewitem.cpp | 15 +++--- indra/llui/llfolderviewitem.h | 3 +- indra/llui/lltabcontainer.cpp | 4 +- indra/newview/CMakeLists.txt | 2 - indra/newview/llflashtimer.cpp | 82 --------------------------------- indra/newview/llflashtimer.h | 66 -------------------------- indra/newview/llfloaterimcontainer.cpp | 14 ++++-- indra/newview/llfloaterimcontainer.h | 2 +- indra/newview/llfloaterimsessiontab.cpp | 10 ++++ 14 files changed, 206 insertions(+), 193 deletions(-) create mode 100644 indra/llui/llflashtimer.cpp create mode 100644 indra/llui/llflashtimer.h delete mode 100644 indra/newview/llflashtimer.cpp delete mode 100644 indra/newview/llflashtimer.h (limited to 'indra') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 80cec6c9f3..ccc7aa8cec 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -47,6 +47,7 @@ set(llui_SOURCE_FILES lleditmenuhandler.cpp llf32uictrl.cpp llfiltereditor.cpp + llflashtimer.cpp llflatlistview.cpp llfloater.cpp llfloaterreg.cpp @@ -153,6 +154,7 @@ set(llui_HEADER_FILES lleditmenuhandler.h llf32uictrl.h llfiltereditor.h + llflashtimer.h llflatlistview.h llfloater.h llfloaterreg.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 3b9076ee54..8a34e221b1 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -170,17 +170,18 @@ LLButton::LLButton(const LLButton::Params& p) mMouseUpSignal(NULL), mHeldDownSignal(NULL), mUseDrawContextAlpha(p.use_draw_context_alpha), - mHandleRightMouse(p.handle_right_mouse), - mButtonFlashCount(p.button_flash_count), - mButtonFlashRate(p.button_flash_rate) + mHandleRightMouse(p.handle_right_mouse) { + // If optional parameter "p.button_flash_count" is not provided, LLFlashTimer will be + // used instead it a "default" value from gSavedSettings.getS32("FlashCount")). + // Likewise, missing "p.button_flash_rate" is replaced by gSavedSettings.getF32("FlashPeriod"); + S32 flash_count = p.button_flash_count || 0; + F32 flash_rate = p.button_flash_rate || 0.0; // + mFlashingTimer = new LLFlashTimer ((LLFlashTimer::callback_t)NULL, flash_count, flash_rate); + static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0); static Params default_params(LLUICtrlFactory::getDefaultParams<LLButton>()); -if (this->getName() == "chat") -{ -bool q = false; -q = !q; -} + if (!p.label_selected.isProvided()) { mSelectedLabel = mUnselectedLabel; @@ -271,6 +272,7 @@ LLButton::~LLButton() delete mMouseDownSignal; delete mMouseUpSignal; delete mHeldDownSignal; + delete mFlashingTimer; } // HACK: Committing a button is the same as instantly clicking it. @@ -595,22 +597,11 @@ void LLButton::draw() { static LLCachedControl<bool> sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true); F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); - bool flash = FALSE; - if( mFlashing) - { - if ( sEnableButtonFlashing) - { - F32 elapsed = mFlashingTimer.getElapsedTimeF32(); - S32 flash_count = S32(elapsed * mButtonFlashRate * 2.f); - // flash on or off? - flash = (flash_count % 2 == 0) || flash_count > S32((F32)mButtonFlashCount * 2.f); - } - else - { // otherwise just highlight button in flash color - flash = true; - } - } + mFlashing = mFlashingTimer->isFlashing(); + + bool flash = mFlashing && + (!sEnableButtonFlashing || mFlashingTimer->isHighlight()); bool pressed_by_keyboard = FALSE; if (hasFocus()) @@ -955,10 +946,13 @@ void LLButton::setToggleState(BOOL b) void LLButton::setFlashing( BOOL b ) { - if ((bool)b != mFlashing) + if (b) + { + mFlashingTimer->startFlashing(); + } + else { - mFlashing = b; - mFlashingTimer.reset(); + mFlashingTimer->stopFlashing(); } } diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index deaa0823c6..92548298f5 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -30,6 +30,7 @@ #include "lluuid.h" #include "llbadgeowner.h" #include "llcontrol.h" +#include "llflashtimer.h" #include "lluictrl.h" #include "v4color.h" #include "llframetimer.h" @@ -201,6 +202,7 @@ public: void setHighlight(bool b); void setFlashing( BOOL b ); BOOL getFlashing() const { return mFlashing; } + LLFlashTimer* getFlashTimer() {return mFlashingTimer;} void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } LLFontGL::HAlign getHAlign() const { return mHAlign; } @@ -285,8 +287,6 @@ protected: LLFrameTimer mMouseDownTimer; bool mNeedsHighlight; - S32 mButtonFlashCount; - F32 mButtonFlashRate; void drawBorder(LLUIImage* imagep, const LLColor4& color, S32 size); void resetMouseDownTimer(); @@ -373,7 +373,7 @@ protected: bool mForcePressedState; bool mDisplayPressedState; - LLFrameTimer mFlashingTimer; + LLFlashTimer* mFlashingTimer; bool mHandleRightMouse; }; diff --git a/indra/llui/llflashtimer.cpp b/indra/llui/llflashtimer.cpp new file mode 100644 index 0000000000..c572a83ff5 --- /dev/null +++ b/indra/llui/llflashtimer.cpp @@ -0,0 +1,80 @@ +/** + * @file llflashtimer.cpp + * @brief LLFlashTimer class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#include "../newview/llviewerprecompiledheaders.h" + +#include "llflashtimer.h" +#include "../newview/llviewercontrol.h" +#include "lleventtimer.h" + +LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) + : LLEventTimer(period) + , mCallback(cb) + , mCurrentTickCount(0) + , mIsFlashing(false) +{ + mEventTimer.stop(); + + // By default use settings from settings.xml to be able change them via Debug settings. See EXT-5973. + // Due to Timer is implemented as derived class from EventTimer it is impossible to change period + // in runtime. So, both settings are made as required restart. + mFlashCount = 2 * ((count>0)? count : gSavedSettings.getS32("FlashCount")); + if (mPeriod<=0) + { + mPeriod = gSavedSettings.getF32("FlashPeriod"); + } +} + +BOOL LLFlashTimer::tick() +{ + mIsHighlight = !(mCurrentTickCount % 2); + if (mCallback) + { + mCallback(mIsHighlight); + } + + if (++mCurrentTickCount >= mFlashCount) + { + mEventTimer.stop(); + } + + return FALSE; +} + +void LLFlashTimer::startFlashing() +{ + mCurrentTickCount = 0; + mIsFlashing = true; + mEventTimer.start(); +} + +void LLFlashTimer::stopFlashing() +{ + mIsFlashing = false; + mIsHighlight = false; + mEventTimer.stop(); +} + + diff --git a/indra/llui/llflashtimer.h b/indra/llui/llflashtimer.h new file mode 100644 index 0000000000..2ef6ebcc8a --- /dev/null +++ b/indra/llui/llflashtimer.h @@ -0,0 +1,67 @@ +/** + * @file llflashtimer.h + * @brief LLFlashTimer class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_FLASHTIMER_H +#define LL_FLASHTIMER_H + +#include "lleventtimer.h" + +class LLFlashTimer : public LLEventTimer +{ +public: + + typedef boost::function<void (bool)> callback_t; + + /** + * Constructor. + * + * @param count - how many times callback should be called (twice to not change original state) + * @param period - how frequently callback should be called + * @param cb - callback to be called each tick + */ + LLFlashTimer(callback_t cb = NULL, S32 count = 0, F32 period = 0.0); + ~LLFlashTimer() {}; + + /*virtual*/ BOOL tick(); + + void startFlashing(); + void stopFlashing(); + + bool isFlashing() {return mIsFlashing;} + bool isHighlight() {return mIsHighlight;} + +private: + callback_t mCallback; + /** + * How many times parent will blink. + */ + S32 mFlashCount; + S32 mCurrentTickCount; + bool mIsHighlight; + bool mIsFlashing; +}; + +#endif /* LL_FLASHTIMER_H */ diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 90568f344a..d65f53cd4d 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -23,8 +23,9 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ +#include "../newview/llviewerprecompiledheaders.h" -#include "../newview/llflashtimer.h" +#include "llflashtimer.h" #include "linden_common.h" #include "llfolderviewitem.h" @@ -164,17 +165,19 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) } } +// Destroys the object +LLFolderViewItem::~LLFolderViewItem() +{ + delete mFlashTimer; + mViewModelItem = NULL; +} + BOOL LLFolderViewItem::postBuild() { refresh(); return TRUE; } -// Destroys the object -LLFolderViewItem::~LLFolderViewItem( void ) -{ - mViewModelItem = NULL; -} LLFolderView* LLFolderViewItem::getRoot() { diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index c16d65206f..c8d6c37b04 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -26,10 +26,10 @@ #ifndef LLFOLDERVIEWITEM_H #define LLFOLDERVIEWITEM_H +#include "llflashtimer.h" #include "llview.h" #include "lluiimage.h" -class LLFlashTimer; class LLFolderView; class LLFolderViewModelItem; class LLFolderViewFolder; @@ -163,6 +163,7 @@ public: S32 getIconPad(); S32 getTextPad(); + LLFlashTimer* getFlashTimer() {return mFlashTimer;} // If 'selection' is 'this' then note that otherwise ignore. // Returns TRUE if this item ends up being selected. virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index c24eb2ee90..d1f77830a6 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -506,8 +506,8 @@ void LLTabContainer::draw() } } - mPrevArrowBtn->setFlashing(FALSE); - mNextArrowBtn->setFlashing(FALSE); + mPrevArrowBtn->getFlashTimer()->stopFlashing(); + mNextArrowBtn->getFlashTimer()->stopFlashing(); } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 574fdc495a..f652c9e50c 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -178,7 +178,6 @@ set(viewer_SOURCE_FILES llfilepicker.cpp llfilteredwearablelist.cpp llfirstuse.cpp - llflashtimer.cpp llflexibleobject.cpp llfloaterabout.cpp llfloaterbvhpreview.cpp @@ -763,7 +762,6 @@ set(viewer_HEADER_FILES llfilepicker.h llfilteredwearablelist.h llfirstuse.h - llflashtimer.h llflexibleobject.h llfloaterabout.h llfloaterbvhpreview.h diff --git a/indra/newview/llflashtimer.cpp b/indra/newview/llflashtimer.cpp deleted file mode 100644 index 2feacfa218..0000000000 --- a/indra/newview/llflashtimer.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @file llflashtimer.cpp - * @brief LLFlashTimer class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - - -#include "llviewerprecompiledheaders.h" - -#include "llflashtimer.h" -#include "llviewercontrol.h" -#include "lleventtimer.h" - -LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) - : LLEventTimer(period) - , mCallback(cb) - , mCurrentTickCount(0) - , mIsFlashing(false) -{ - mEventTimer.stop(); - - // By default use settings from settings.xml to be able change them via Debug settings. See EXT-5973. - // Due to Timer is implemented as derived class from EventTimer it is impossible to change period - // in runtime. So, both settings are made as required restart. - mFlashCount = 2 * ((count>0)? count : gSavedSettings.getS32("FlashCount")); - if (mPeriod<=0) - { - mPeriod = gSavedSettings.getF32("FlashPeriod"); - } -} - -BOOL LLFlashTimer::tick() -{ - mIsHighlight = !(mCurrentTickCount % 2); - if (mCallback) - { - mCallback(mIsHighlight); - } - - if (++mCurrentTickCount >= mFlashCount) - { - mEventTimer.stop(); - } - - return FALSE; -} - -void LLFlashTimer::startFlashing() -{ - mCurrentTickCount = 0; - mIsFlashing = true; - mEventTimer.start(); -} - -void LLFlashTimer::stopFlashing() -{ - mIsFlashing = false; - mIsHighlight = false; - mEventTimer.stop(); -} - - diff --git a/indra/newview/llflashtimer.h b/indra/newview/llflashtimer.h deleted file mode 100644 index c030edfc52..0000000000 --- a/indra/newview/llflashtimer.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file llflashtimer.h - * @brief LLFlashTimer class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_FLASHTIMER_H -#define LL_FLASHTIMER_H - -#include "lleventtimer.h" - -class LLFlashTimer : public LLEventTimer -{ -public: - - typedef boost::function<void (bool)> callback_t; - - /** - * Constructor. - * - * @param count - how many times callback should be called (twice to not change original state) - * @param period - how frequently callback should be called - * @param cb - callback to be called each tick - */ - LLFlashTimer(callback_t cb = NULL, S32 count = 0, F32 period = 0.0); - ~LLFlashTimer() {}; - - /*virtual*/ BOOL tick(); - - void startFlashing(); - void stopFlashing(); - bool isFlashing() {return mIsFlashing;} - bool isHighlight() {return mIsHighlight;} - -private: - callback_t mCallback; - /** - * How many times Well will blink. - */ - S32 mFlashCount; - S32 mCurrentTickCount; - bool mIsHighlight; - bool mIsFlashing; -}; - -#endif /* LL_FLASHTIMER_H */ diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index da6f3a484d..90ddeef5bb 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -41,6 +41,7 @@ #include "llcallbacklist.h" #include "llgroupactions.h" #include "llgroupiconctrl.h" +#include "llflashtimer.h" #include "llfloateravatarpicker.h" #include "llfloaterpreference.h" #include "llimview.h" @@ -1594,17 +1595,22 @@ void LLFloaterIMContainer::reSelectConversation() { selectFloater(session_floater); } - } -void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id) +void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes) { LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); if (widget) { - widget->; + if (is_flashes) + { + widget->getFlashTimer()->startFlashing(); + } + else + { + widget->getFlashTimer()->stopFlashing(); + } } - } // EOF diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 443688668b..9112b54018 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -164,7 +164,7 @@ public: void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); void setNearbyDistances(); void reSelectConversation(); - void flashConversationItemWidget(const LLUUID& session_id); + void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes); private: LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 69b42cdd6d..42e7e6cb55 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -40,6 +40,7 @@ #include "llfloaterimsession.h" #include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container #include "lllayoutstack.h" +#include "lltoolbarview.h" #include "llfloaterimnearbychat.h" const F32 REFRESH_INTERVAL = 0.2f; @@ -328,11 +329,20 @@ std::string LLFloaterIMSessionTab::appendTime() void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD &args) { + // Update the participant activity time LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); if (im_box) { im_box->setTimeNow(mSessionID,chat.mFromID); + + // TODO: Warning! The next two lines of code are included below only temporarily + // to demonstrate the correct format call the appropriate functions. + // They should be moved to the right places when working on CHUI-486. ~Alex ProductEngine. + // ---- start demo ---- + im_box->flashConversationItemWidget(mSessionID, true); // flashing of the conversation's item + gToolBarView->flashCommand(LLCommandId("chat"), true); // flashing of the FUI button "Chat" + // ---- end demo ----- } -- cgit v1.2.3 From c6a0f0ae1dec5ef2f7657d8c1ca07d85c1fef55d Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Fri, 16 Nov 2012 16:17:11 -0800 Subject: CHUI-518: FIX Removing the LLIMMgr::getInstance() as the containing method is already a non-static member method of the same class. --- indra/newview/llimview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index a38153c315..e2b678626b 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2814,7 +2814,7 @@ void LLIMMgr::inviteToSession( if (isRejectDoNotDisturb && !isRejectGroupCall && !isRejectNonFriendCall) { LLSD args; - LLIMMgr::getInstance()->addSystemMessage(session_id, "you_auto_rejected_call", args); + addSystemMessage(session_id, "you_auto_rejected_call", args); send_do_not_disturb_message(gMessageSystem, caller_id, session_id); } // silently decline the call -- cgit v1.2.3 From 2d9285cddb4a48fb766b21fac2705c8873e15f93 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 16 Nov 2012 18:53:05 -0800 Subject: CHUI-529: Now the conversations floater will appear when the chat preference is set for friend, non-friend, conference, group and nearby chat. --- indra/newview/llfloaterimnearbychathandler.cpp | 50 ++++++---- indra/newview/llimview.cpp | 104 +++++++++++++-------- .../default/xui/en/panel_preferences_chat.xml | 20 ++++ 3 files changed, 116 insertions(+), 58 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index ab81b85d04..2d8a6d46fe 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -41,6 +41,7 @@ #include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance #include "llviewerwindow.h"//for screen channel position #include "llfloaterimnearbychat.h" +#include "llfloaterimcontainer.h" #include "llrootview.h" #include "lllayoutstack.h" @@ -283,12 +284,6 @@ bool LLFloaterIMNearbyChatScreenChannel::createPoolToast() void LLFloaterIMNearbyChatScreenChannel::addChat(LLSD& chat) { - //Ignore Nearby Toasts - if(gSavedSettings.getString("NotificationNearbyChatOptions") != "toast") - { - return; - } - //look in pool. if there is any message if(mStopProcessing) return; @@ -606,19 +601,36 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, toast_msg = chat_msg.mText; } - // Add a nearby chat toast. - LLUUID id; - id.generate(); - chat["id"] = id; - std::string r_color_name = "White"; - F32 r_color_alpha = 1.0f; - LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha); - - chat["text_color"] = r_color_name; - chat["color_alpha"] = r_color_alpha; - chat["font_size"] = (S32)LLViewerChat::getChatFontSize() ; - chat["message"] = toast_msg; - channel->addChat(chat); + + //Will show toast when chat preference is set + if(gSavedSettings.getString("NotificationNearbyChatOptions") == "toast") + { + // Add a nearby chat toast. + LLUUID id; + id.generate(); + chat["id"] = id; + std::string r_color_name = "White"; + F32 r_color_alpha = 1.0f; + LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha); + + chat["text_color"] = r_color_name; + chat["color_alpha"] = r_color_alpha; + chat["font_size"] = (S32)LLViewerChat::getChatFontSize() ; + chat["message"] = toast_msg; + channel->addChat(chat); + } + //Will show Conversations floater when chat preference is set + else if(gSavedSettings.getString("NotificationNearbyChatOptions") == "openconversations") + { + LLFloaterIMContainer * floaterIMContainer = LLFloaterIMContainer::getInstance(); + + if(floaterIMContainer) + { + floaterIMContainer->setVisible(TRUE); + floaterIMContainer->setFrontmost(TRUE); + } + } + } } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 818de4eaf4..106811b7e0 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -112,6 +112,55 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id, LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); } +//Will return true if the preference is allowed (user configures these preferences via 'Chat Preference' Dialog +bool ignoreNotification(const LLSD& msg, const char * preferenceString) +{ + //Get the session so we can find out the type of session + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( + msg["session_id"]); + + const LLRelationship * relationship; + + // Skip system messages + if (msg["from_id"].asUUID() == LLUUID::null) + { + return true; + } + + //Ignore P2P Friend/Non-Friend Notification + if(session->isP2PSessionType()) + { + relationship = LLAvatarTracker::instance().getBuddyInfo(msg["from_id"]); + + //Ignores non-friends + if(relationship == NULL + && (gSavedSettings.getString("NotificationNonFriendIMOptions") != preferenceString)) + { + return true; + } + //Ignores friends + else if(relationship + && gSavedSettings.getString("NotificationFriendIMOptions") != preferenceString) + { + return true; + } + } + //Ignore Ad Hoc Notification + else if(session->isAdHocSessionType() + && (gSavedSettings.getString("NotificationConferenceIMOptions") != preferenceString)) + { + return true; + } + //Ignore Group Notification + else if(session->isGroupSessionType() + && (gSavedSettings.getString("NotificationGroupChatOptions") != preferenceString)) + { + return true; + } + + return false; +} + void toast_callback(const LLSD& msg){ // do not show toast in do not disturb mode or it goes from agent if (gAgent.isDoNotDisturb() || gAgent.getID() == msg["from_id"]) @@ -133,55 +182,32 @@ void toast_callback(const LLSD& msg){ return; } - // Skip toasting for system messages - if (msg["from_id"].asUUID() == LLUUID::null) - { - return; - } - - // *NOTE Skip toasting if the user disable it in preferences/debug settings ~Alexandrea - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - msg["session_id"]); - - - //Ignore P2P Friend/Non-Friend toasts - if(session->isP2PSessionType()) - { - //Ignores non-friends - if((LLAvatarTracker::instance().getBuddyInfo(msg["from_id"]) == NULL) - && (gSavedSettings.getString("NotificationNonFriendIMOptions") != "toast")) - { - return; - } - //Ignores friends - else if(gSavedSettings.getString("NotificationFriendIMOptions") != "toast") - { - return; - } - } - //Ignore Ad Hoc Toasts - else if(session->isAdHocSessionType() - && (gSavedSettings.getString("NotificationConferenceIMOptions") != "toast")) + //Show toast + if(ignoreNotification(msg, "toast") == false) { - return; + LLAvatarNameCache::get(msg["from_id"].asUUID(), + boost::bind(&on_avatar_name_cache_toast, + _1, _2, msg)); } - //Ignore Group Toasts - else if(session->isGroupSessionType() - && (gSavedSettings.getString("NotificationGroupChatOptions") != "toast")) +} + +void open_conversations_callback(const LLSD& msg) +{ + LLFloaterIMContainer * floaterIMContainer = LLFloaterIMContainer::getInstance(); + + if(floaterIMContainer + && ignoreNotification(msg, "openconversations") == false) { - return; + floaterIMContainer->setVisible(TRUE); + floaterIMContainer->setFrontmost(TRUE); } - - //Show toast - LLAvatarNameCache::get(msg["from_id"].asUUID(), - boost::bind(&on_avatar_name_cache_toast, - _1, _2, msg)); } LLIMModel::LLIMModel() { addNewMsgCallback(boost::bind(&LLFloaterIMSession::newIMCallback, _1)); addNewMsgCallback(boost::bind(&toast_callback, _1)); + addNewMsgCallback(boost::bind(&open_conversations_callback, _1)); } LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg) diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 712e8bff7f..0c94b6b223 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -134,6 +134,10 @@ top_delta="-6" name="FriendIMOptions" width="223"> + <combo_box.item + label="Open Conversations window" + name="OpenConversationsWindow" + value="openconversations"/> <combo_box.item label="Pop up the message" name="PopUpMessage" @@ -165,6 +169,10 @@ top_delta="-6" name="NonFriendIMOptions" width="223"> + <combo_box.item + label="Open Conversations window" + name="OpenConversationsWindow" + value="openconversations"/> <combo_box.item label="Pop up the message" name="PopUpMessage" @@ -196,6 +204,10 @@ top_delta="-6" name="ConferenceIMOptions" width="223"> + <combo_box.item + label="Open Conversations window" + name="OpenConversationsWindow" + value="openconversations"/> <combo_box.item label="Pop up the message" name="PopUpMessage" @@ -227,6 +239,10 @@ top_delta="-6" name="GroupChatOptions" width="223"> + <combo_box.item + label="Open Conversations window" + name="OpenConversationsWindow" + value="openconversations"/> <combo_box.item label="Pop up the message" name="PopUpMessage" @@ -258,6 +274,10 @@ top_delta="-6" name="NearbyChatOptions" width="223"> + <combo_box.item + label="Open Conversations window" + name="OpenConversationsWindow" + value="openconversations"/> <combo_box.item label="Pop up the message" name="PopUpMessage" -- cgit v1.2.3 From 249b44d01ced4ba5bb8b8b9147d7836a7d492d5b Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 16 Nov 2012 21:01:57 -0800 Subject: CHUI-479 : Fixed : Rebuild the root on the LLFloaterIMSession when modifying the session ID --- indra/newview/llfloaterimcontainer.cpp | 42 ++++++++----------- indra/newview/llfloaterimsessiontab.cpp | 72 +++++++++++++++++---------------- indra/newview/llfloaterimsessiontab.h | 1 + 3 files changed, 55 insertions(+), 60 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index af090338d7..bd692aa850 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -117,26 +117,20 @@ void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) void LLFloaterIMContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) { - llinfos << "Merov debug : sessionIDUpdated, old_session_id = " << old_session_id << ", new_session_id = " << new_session_id << llendl; - // Retrieve the session LLFloaterIMSessionTab - // just close it: that should erase the mSession, close the tab and remove the list item - // *TODO : take the mSessions element (pointing to the tab) out of the list - //bool change_focus = removeConversationListItem(old_session_id); - // *TODO : detach the old tab from the host - // *TODO : delete the tab (that's one thing that's reentrant) - LLFloater* floaterp = get_ptr_in_map(mSessions, old_session_id); - if (floaterp) - { - llinfos << "Merov debug : closeFloater, start" << llendl; - floaterp->closeFloater(); - llinfos << "Merov debug : closeFloater, end" << llendl; - } - bool change_focus = false; - llinfos << "Merov debug : addConversationListItem" << llendl; + // The general strategy when a session id is modified is to delete all related objects and create them anew. + + // Note however that the LLFloaterIMSession has its session id updated through a call to sessionInitReplyReceived() + // and do not need to be deleted and recreated (trying this creates loads of problems). We do need however to suppress + // its related mSessions record as it's indexed with the wrong id. + // Grabbing the updated LLFloaterIMSession and readding it in mSessions will eventually be done by addConversationListItem(). + mSessions.erase(old_session_id); + + // Delete the model and participants related to the old session + bool change_focus = removeConversationListItem(old_session_id); + + // Create a new conversation with the new id addConversationListItem(new_session_id, change_focus); - llinfos << "Merov debug : addToHost" << llendl; LLFloaterIMSessionTab::addToHost(new_session_id); - llinfos << "Merov debug : end sessionIDUpdated" << llendl; } void LLFloaterIMContainer::sessionRemoved(const LLUUID& session_id) @@ -483,14 +477,14 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event) else if (type == "update_session") { session_view->refresh(); - if (conversation_floater) - { - conversation_floater->refreshConversation(); - } } mConversationViewModel.requestSortAll(); mConversationsRoot->arrangeAll(); + if (conversation_floater) + { + conversation_floater->refreshConversation(); + } return false; } @@ -1253,10 +1247,6 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& return item_it->second; } - // Remove the conversation item that might exist already: it'll be recreated anew further down anyway - // and nothing wrong will happen removing it if it doesn't exist - removeConversationListItem(uuid,false); - // Create a conversation session model LLConversationItemSession* item = NULL; LLSpeakerMgr* speaker_manager = (is_nearby_chat ? (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()) : LLIMModel::getInstance()->getSpeakerManager(uuid)); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 6fbc713590..22131eac49 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -52,6 +52,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) , mCloseBtn(NULL) , mSessionID(session_id.asUUID()) , mConversationsRoot(NULL) + , mScroller(NULL) , mChatHistory(NULL) , mInputEditor(NULL) , mInputEditorTopPad(0) @@ -68,10 +69,6 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2)); - - // Zero expiry time is set only once to allow initial update. - mRefreshTimer->setTimerExpirySec(0); - mRefreshTimer->start(); } LLFloaterIMSessionTab::~LLFloaterIMSessionTab() @@ -195,33 +192,16 @@ BOOL LLFloaterIMSessionTab::postBuild() mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); - // Create a root view folder for all participants - LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); - LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); - p.rect = LLRect(0, 0, getRect().getWidth(), 0); - p.parent_panel = mParticipantListPanel; - p.listener = base_item; - p.view_model = &mConversationViewModel; - p.root = NULL; - p.use_ellipses = true; - mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); - mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); - // Add a scroller for the folder (participant) view LLRect scroller_view_rect = mParticipantListPanel->getRect(); scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>()); scroller_params.rect(scroller_view_rect); - LLScrollContainer* scroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); - scroller->setFollowsAll(); - - // Insert that scroller into the panel widgets hierarchy and folder view - mParticipantListPanel->addChild(scroller); - scroller->addChild(mConversationsRoot); - mConversationsRoot->setScrollContainer(scroller); - mConversationsRoot->setFollowsAll(); - mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); + mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); + mScroller->setFollowsAll(); + // Insert that scroller into the panel widgets hierarchy + mParticipantListPanel->addChild(mScroller); mChatHistory = getChild<LLChatHistory>("chat_history"); @@ -235,8 +215,6 @@ BOOL LLFloaterIMSessionTab::postBuild() setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); - buildConversationViewParticipant(); - mSaveRect = isTornOff(); initRectControl(); @@ -249,8 +227,14 @@ BOOL LLFloaterIMSessionTab::postBuild() result = LLDockableFloater::postBuild(); } + // Now ready to build the conversation and participants list + buildConversationViewParticipant(); refreshConversation(); - + + // Zero expiry time is set only once to allow initial update. + mRefreshTimer->setTimerExpirySec(0); + mRefreshTimer->start(); + return result; } @@ -276,9 +260,8 @@ void LLFloaterIMSessionTab::draw() { buildConversationViewParticipant(); } + refreshConversation(); } - - refreshConversation(); // Restart the refresh timer mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); @@ -390,7 +373,31 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant() // Nothing to do if the model list is inexistent return; } - + + // Create or recreate the root folder: this is a dummy folder (not shown) but required by the LLFolderView architecture + // We need to redo this when rebuilding as the session id (mSessionID) *may* have changed + if (mConversationsRoot) + { + // Remove the old root if any + mScroller->removeChild(mConversationsRoot); + } + // Create the root using an ad-hoc base item + LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); + LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); + p.rect = LLRect(0, 0, getRect().getWidth(), 0); + p.parent_panel = mParticipantListPanel; + p.listener = base_item; + p.view_model = &mConversationViewModel; + p.root = NULL; + p.use_ellipses = true; + mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); + mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + // Attach that root to the scroller + mScroller->addChild(mConversationsRoot); + mConversationsRoot->setScrollContainer(mScroller); + mConversationsRoot->setFollowsAll(); + mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); + // Create the participants widgets now LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); @@ -420,7 +427,6 @@ void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* p participant_view->addToFolder(mConversationsRoot); participant_view->addToSession(mSessionID); participant_view->setVisible(TRUE); - refreshConversation(); } } @@ -432,7 +438,6 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part mConversationsRoot->extractItem(widget); delete widget; mConversationsWidgets.erase(participant_id); - refreshConversation(); } } @@ -443,7 +448,6 @@ void LLFloaterIMSessionTab::updateConversationViewParticipant(const LLUUID& part { widget->refresh(); } - refreshConversation(); } void LLFloaterIMSessionTab::refreshConversation() diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 8f5a8c2c1b..b765d121de 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -146,6 +146,7 @@ protected: conversations_widgets_map mConversationsWidgets; LLConversationViewModel mConversationViewModel; LLFolderView* mConversationsRoot; + LLScrollContainer* mScroller; LLChatHistory* mChatHistory; LLChatEntry* mInputEditor; -- cgit v1.2.3 From 2d25eb18adc0c2c97c63a8e02f2274362672137c Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Sat, 17 Nov 2012 13:24:41 -0800 Subject: CHUI-479 : Clean up unecessary tracking code --- indra/newview/llconversationview.cpp | 8 -------- indra/newview/llfloaterimcontainer.cpp | 2 -- indra/newview/llfloaterimsessiontab.cpp | 1 - indra/newview/lloutputmonitorctrl.cpp | 27 ++------------------------- indra/newview/llspeakingindicatormanager.cpp | 8 -------- indra/newview/llspeakingindicatormanager.h | 2 +- 6 files changed, 3 insertions(+), 45 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index d971c943f0..64618fabba 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -308,7 +308,6 @@ void LLConversationViewSession::refresh() } // Update all speaking indicators - llinfos << "Merov debug : LLConversationViewSession::refresh, updateSpeakingIndicators" << llendl; LLSpeakingIndicatorManager::updateSpeakingIndicators(); // Do the regular upstream refresh @@ -455,7 +454,6 @@ S32 LLConversationViewParticipant::arrange(S32* width, S32* height) void LLConversationViewParticipant::onCurrentVoiceSessionChanged(const LLUUID& session_id) { - llinfos << "Merov debug : onCurrentVoiceSessionChanged begin, uuid = " << mUUID << ", session_id = " << session_id << llendl; LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem()); if (participant_model) @@ -477,12 +475,6 @@ void LLConversationViewParticipant::refresh() // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat mSpeakingIndicator->setIsMuted(participant_model->isMuted()); - //LLConversationItemSession* parent_session = participant_model->getParentSession(); - //if (parent_session) - //{ - // bool is_active = (parent_session->getUUID() == session_id); - // mSpeakingIndicator->switchIndicator(is_active); - //} // Do the regular upstream refresh LLFolderViewItem::refresh(); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index bd692aa850..78b930984f 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -110,7 +110,6 @@ void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std: void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { - llinfos << "Merov debug : sessionVoiceOrIMStarted, uuid = " << session_id << llendl; addConversationListItem(session_id); LLFloaterIMSessionTab::addToHost(session_id); } @@ -1310,7 +1309,6 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) { - llinfos << "Merov debug : removeConversationListItem, uuid = " << uuid << llendl; // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 22131eac49..c2c6e739e9 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -725,7 +725,6 @@ void LLFloaterIMSessionTab::onClose(bool app_quitting) LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); if (im_box) { - llinfos << "Merov debug : LLFloaterIMSessionTab::onClose, mKey = " << mKey << llendl; im_box->removeConversationListItem(mKey); } } diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 536f1fbd73..e4621a7fc3 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -48,8 +48,6 @@ LLColor4 LLOutputMonitorCtrl::sColorBound; //F32 LLOutputMonitorCtrl::sRectWidthRatio = 0.f; //F32 LLOutputMonitorCtrl::sRectHeightRatio = 0.f; -static LLUUID test_uuid("c684ce33-89fb-4544-8f7b-dae243c8b214"); - LLOutputMonitorCtrl::Params::Params() : draw_border("draw_border"), image_mute("image_mute"), @@ -280,44 +278,24 @@ BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/, bool show_other_participants_speaking /* = false */) { - bool test_on = (speaker_id == test_uuid); - if (test_on) - { - llinfos << "Merov debug : setSpeakerId, this = " << this << ", session_id = " << session_id << llendl; - } if (speaker_id.isNull() && mSpeakerId.notNull()) { LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); } - if (speaker_id.isNull() || speaker_id == mSpeakerId) + if (speaker_id.isNull() || (speaker_id == mSpeakerId)) { - if (test_on) - { - llinfos << "Merov debug : setSpeakerId, nothing done because mSpeakerId == speaker_id" << llendl; - } return; } if (mSpeakerId.notNull()) { - if (test_on) - { - llinfos << "Merov debug : setSpeakerId, unregisterSpeakingIndicator" << llendl; - } // Unregister previous registration to avoid crash. EXT-4782. - if (getTargetSessionID() == session_id) - { - LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); - } + LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); } mShowParticipantsSpeaking = show_other_participants_speaking; mSpeakerId = speaker_id; - if (test_on) - { - llinfos << "Merov debug : setSpeakerId, registerSpeakingIndicator" << llendl; - } LLSpeakingIndicatorManager::registerSpeakingIndicator(mSpeakerId, this, session_id); //mute management @@ -345,7 +323,6 @@ void LLOutputMonitorCtrl::onChange() // virtual void LLOutputMonitorCtrl::switchIndicator(bool switch_on) { - llinfos << "Merov debug : switchIndicator, mSpeakerId = " << mSpeakerId << ", switch_on = " << switch_on << llendl; // ensure indicator is visible in case it is not in visible chain // to be called when parent became visible next time to notify parent that visibility is changed. setVisible(TRUE); diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index d9f9ed5966..76da7d1aee 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -155,7 +155,6 @@ void SpeakingIndicatorManager::registerSpeakingIndicator(const LLUUID& speaker_i BOOL is_in_same_voice = LLVoiceClient::getInstance()->isParticipant(speaker_id); speakers_uuids.insert(speaker_id); - llinfos << "Merov debug : registerSpeakingIndicator call switchSpeakerIndicators, switch = " << is_in_same_voice << llendl; switchSpeakerIndicators(speakers_uuids, is_in_same_voice); } @@ -196,7 +195,6 @@ SpeakingIndicatorManager::~SpeakingIndicatorManager() void SpeakingIndicatorManager::sOnCurrentChannelChanged(const LLUUID& /*session_id*/) { - llinfos << "Merov debug : sOnCurrentChannelChanged call switchSpeakerIndicators, FALSE" << llendl; switchSpeakerIndicators(mSwitchedIndicatorsOn, FALSE); mSwitchedIndicatorsOn.clear(); } @@ -210,16 +208,12 @@ void SpeakingIndicatorManager::onParticipantsChanged() LL_DEBUGS("SpeakingIndicator") << "Switching all OFF, count: " << mSwitchedIndicatorsOn.size() << LL_ENDL; // switch all indicators off - llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, FALSE" << llendl; switchSpeakerIndicators(mSwitchedIndicatorsOn, FALSE); - llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, end FALSE switch" << llendl; mSwitchedIndicatorsOn.clear(); LL_DEBUGS("SpeakingIndicator") << "Switching all ON, count: " << speakers_uuids.size() << LL_ENDL; // then switch current voice participants indicators on - llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, TRUE" << llendl; switchSpeakerIndicators(speakers_uuids, TRUE); - llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, end TRUE switch" << llendl; } void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& speakers_uuids, BOOL switch_on) @@ -230,7 +224,6 @@ void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& spea { session_id = voice_channel->getSessionID(); } - llinfos << "Merov debug : switchSpeakerIndicators, switch_on = " << switch_on << ", voice channel = " << session_id << llendl; speaker_ids_t::const_iterator it_uuid = speakers_uuids.begin(); for (; it_uuid != speakers_uuids.end(); ++it_uuid) @@ -255,7 +248,6 @@ void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& spea } was_switched_on = was_switched_on || switch_current_on; - llinfos << "Merov debug : indicator for " << *it_uuid << ", switch_current_on = " << switch_current_on << ", session = " << indicator->getTargetSessionID() << llendl; indicator->switchIndicator(switch_current_on); } diff --git a/indra/newview/llspeakingindicatormanager.h b/indra/newview/llspeakingindicatormanager.h index 8ee368e258..e5afcd1cb7 100644 --- a/indra/newview/llspeakingindicatormanager.h +++ b/indra/newview/llspeakingindicatormanager.h @@ -37,7 +37,7 @@ public: virtual ~LLSpeakingIndicator(){} virtual void switchIndicator(bool switch_on) = 0; -//private: +private: friend class SpeakingIndicatorManager; // Accessors for target voice session UUID. // They are intended to be used only from SpeakingIndicatorManager to ensure target session is -- cgit v1.2.3 From 0cb67ec3762c1f1671fd01e331fe64a210098fd2 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Mon, 19 Nov 2012 07:42:39 +0200 Subject: CHUI-423 (User typing /me something in chat does not show correctly in italics on outgoing or incoming chat) --- indra/newview/llchathistory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 605e3ece51..a33bd88273 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -809,7 +809,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (irc_me || chat.mChatStyle == CHAT_STYLE_IRC) { delimiter = LLStringUtil::null; - name_params.font.style = "ITALIC"; + body_message_params.font.style = "ITALIC"; } bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY; -- cgit v1.2.3 From f043bc32fd202de88d6823bb938128147ab4a04c Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Mon, 19 Nov 2012 09:08:02 +0200 Subject: CHUI-434 (Don't display phone icon and disable phone button when voice isn't enabled) --- indra/newview/llconversationview.cpp | 20 +++++++------------- indra/newview/llconversationview.h | 2 +- 2 files changed, 8 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 4c52794e4c..b9d62e85c4 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -57,14 +57,11 @@ public: virtual void onChange(EStatusType status, const std::string &channelURI, bool proximal) { - if (conversation - && status != STATUS_JOINING - && status != STATUS_LEFT_CHANNEL - && LLVoiceClient::getInstance()->voiceEnabled() - && LLVoiceClient::getInstance()->isVoiceWorking()) - { - conversation->showVoiceIndicator(); - } + conversation->showVoiceIndicator(conversation + && status != STATUS_JOINING + && status != STATUS_LEFT_CHANNEL + && LLVoiceClient::getInstance()->voiceEnabled() + && LLVoiceClient::getInstance()->isVoiceWorking()); } private: @@ -288,12 +285,9 @@ LLConversationViewParticipant* LLConversationViewSession::findParticipant(const return (iter == getItemsEnd() ? NULL : participant); } -void LLConversationViewSession::showVoiceIndicator() +void LLConversationViewSession::showVoiceIndicator(bool visible) { - if (LLVoiceChannel::getCurrentVoiceChannel()->getSessionID().isNull()) - { - mCallIconLayoutPanel->setVisible(true); - } + mCallIconLayoutPanel->setVisible(visible && LLVoiceChannel::getCurrentVoiceChannel()->getSessionID().isNull()); } void LLConversationViewSession::refresh() diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 1baa8bb5ec..8156b746b2 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -78,7 +78,7 @@ public: void setVisibleIfDetached(BOOL visible); LLConversationViewParticipant* findParticipant(const LLUUID& participant_id); - void showVoiceIndicator(); + void showVoiceIndicator(bool visible); virtual void refresh(); -- cgit v1.2.3 From c48f8c2b28253786ada02d0a57d3a8e005fe9101 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 19 Nov 2012 16:47:40 +0200 Subject: CHUI-487 ADD. FIX (Revised comments) --- indra/newview/app_settings/settings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 14117ee47b..be793a344c 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -13145,7 +13145,7 @@ <key>FlashCount</key> <map> <key>Comment</key> - <string>Number of flashes of IM Well and Notification Well icons after which flashing buttons stay lit up. Requires restart.</string> + <string>Number of flashes of item. Requires restart.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -13156,7 +13156,7 @@ <key>FlashPeriod</key> <map> <key>Comment</key> - <string>Period at which IM Well and Notification Well icons flash (seconds). Requires restart.</string> + <string>Period at which item flash (seconds). Requires restart.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> -- cgit v1.2.3 From 48a683af70fe359f4b4b6fdf6486208fc34dc2a9 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 19 Nov 2012 17:40:46 +0200 Subject: CHUI-488 ADD. fIX Clean up code --- indra/llui/llbutton.cpp | 7 ++++--- indra/newview/skins/default/xui/en/widgets/toolbar.xml | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 8a34e221b1..8ac55b2eb4 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -174,9 +174,10 @@ LLButton::LLButton(const LLButton::Params& p) { // If optional parameter "p.button_flash_count" is not provided, LLFlashTimer will be // used instead it a "default" value from gSavedSettings.getS32("FlashCount")). - // Likewise, missing "p.button_flash_rate" is replaced by gSavedSettings.getF32("FlashPeriod"); - S32 flash_count = p.button_flash_count || 0; - F32 flash_rate = p.button_flash_rate || 0.0; // + // Likewise, missing "p.button_flash_rate" is replaced by gSavedSettings.getF32("FlashPeriod"). + // Note: flashing should be allowed in settings.xml (boolean key "EnableButtonFlashing"). + S32 flash_count = p.button_flash_count.isProvided()? p.button_flash_count : 0; + F32 flash_rate = p.button_flash_rate.isProvided()? p.button_flash_rate : 0.0; mFlashingTimer = new LLFlashTimer ((LLFlashTimer::callback_t)NULL, flash_count, flash_rate); static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0); diff --git a/indra/newview/skins/default/xui/en/widgets/toolbar.xml b/indra/newview/skins/default/xui/en/widgets/toolbar.xml index 0aa478ace9..55ae158c00 100644 --- a/indra/newview/skins/default/xui/en/widgets/toolbar.xml +++ b/indra/newview/skins/default/xui/en/widgets/toolbar.xml @@ -30,8 +30,8 @@ image_overlay_alignment="left" use_ellipses="true" auto_resize="true" - button_flash_count="99999" - button_flash_rate="1.0" + button_flash_count="3" + button_flash_rate="0.25" flash_color="EmphasisColor"/> <button_icon pad_left="10" pad_right="10" -- cgit v1.2.3 From aba409f24f7ec7d74d545b0309340c98854b7217 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Mon, 19 Nov 2012 17:14:18 -0800 Subject: CHUI-495: Ensuring that a user in do-not-disturb mode can receive voice calls from current conversations. --- indra/newview/llimview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index e2b678626b..b5dc4a7967 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2808,7 +2808,7 @@ void LLIMMgr::inviteToSession( { bool isRejectGroupCall = (gSavedSettings.getBOOL("VoiceCallsRejectGroup") && (notify_box_type == "VoiceInviteGroup")); bool isRejectNonFriendCall = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL)); - bool isRejectDoNotDisturb = gAgent.isDoNotDisturb(); + bool isRejectDoNotDisturb = (gAgent.isDoNotDisturb() && !hasSession(session_id)); if (isRejectGroupCall || isRejectNonFriendCall || isRejectDoNotDisturb) { if (isRejectDoNotDisturb && !isRejectGroupCall && !isRejectNonFriendCall) -- cgit v1.2.3 From 2c2e8b83d02efcdec9ccd3216e64073b4e8e1d57 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 19 Nov 2012 19:26:00 +0200 Subject: CHUI-362 ADD. FIX (When the "Bring back" panel is there, it is not possible to collapse the right side of the conversation dialog: the toolbar is completely missing and the "<<" chevrons are not there): This was because the button "<<" belonged session's floater and not the container. Therefore, when all the floaters in the stack becomes invisible, their buttons also become invisible. Solution: Added additional button "<<" in the stub_panel of the container. --- indra/newview/llfloaterimcontainer.cpp | 7 +++++++ indra/newview/llfloaterimcontainer.h | 2 ++ .../skins/default/xui/en/floater_im_container.xml | 17 +++++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 90ddeef5bb..39cd16acfa 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -205,6 +205,8 @@ BOOL LLFloaterIMContainer::postBuild() mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onExpandCollapseButtonClicked, this)); + mStubCollapseBtn = getChild<LLButton>("stub_collapse_btn"); + mStubCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onStubCollapseButtonClicked, this)); childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this)); @@ -335,6 +337,11 @@ void LLFloaterIMContainer::onNewMessageReceived(const LLSD& data) } } +void LLFloaterIMContainer::onStubCollapseButtonClicked() +{ + collapseMessagesPane(true); +} + void LLFloaterIMContainer::onExpandCollapseButtonClicked() { if (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed() diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 9112b54018..9cd6b9bc5d 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -109,6 +109,7 @@ private: void onNewMessageReceived(const LLSD& data); void onExpandCollapseButtonClicked(); + void onStubCollapseButtonClicked(); void processParticipantsStyleUpdate(); void collapseConversationsPane(bool collapse); @@ -147,6 +148,7 @@ private: void openNearbyChat(); LLButton* mExpandCollapseBtn; + LLButton* mStubCollapseBtn; LLPanel* mStubPanel; LLTextBox* mStubTextBox; LLLayoutPanel* mMessagesPane; diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 1388b9e474..4aa7c88312 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -134,6 +134,19 @@ left="0" height="430" width="412"> + <button + follows="right|top" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_collapse" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + right="-10" + name="stub_collapse_btn" + tool_tip="Collapse this pane" + width="31" /> <text type="string" clip_partial="false" @@ -142,7 +155,7 @@ left="20" right="-20" name="stub_textbox_1" - top="10" + top="30" height="20" valign="center" wrap="true"> @@ -156,7 +169,7 @@ left="20" right="-20" name="stub_textbox_2" - top="40" + top="60" height="20" valign="center" parse_urls="true" -- cgit v1.2.3 From 834ded33ae4926b59074f00c13fa3dbf228a3ba0 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 19 Nov 2012 18:41:52 -0800 Subject: CHUI-470 : Fixed : Enable contextual menu in torn off conversations --- indra/llui/llfolderview.h | 1 - indra/newview/llfloaterimcontainer.cpp | 3 +++ indra/newview/llfloaterimcontainer.h | 11 ++++++---- indra/newview/llfloaterimsessiontab.cpp | 39 +++++++++++++++++++++++++++++++++ indra/newview/llfloaterimsessiontab.h | 4 ++++ indra/newview/llinventoryfunctions.cpp | 2 +- 6 files changed, 54 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 487391a477..525efe425a 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -148,7 +148,6 @@ public: virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); virtual std::set<LLFolderViewItem*> getSelectionList() const; - S32 getNumSelectedItems() { return mSelectedItems.size(); } // Make sure if ancestor is selected, descendants are not void sanitizeSelection(); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index aebfdb5bce..65a8aee4ce 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -869,6 +869,7 @@ void LLFloaterIMContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec_t& selectedIDS) { + // *TODO : This is where we need to handle a *list* of participant correctly if(selectedIDS.size() > 0) { const LLUUID& userID = selectedIDS.front(); @@ -981,6 +982,8 @@ void LLFloaterIMContainer::doToSelected(const LLSD& userdata) if(conversationItem != NULL) { getParticipantUUIDs(selected_uuids); + + llinfos << "Merov debug : doToSelected, command = " << command << ", name = " << conversationItem->getName() << ", uuid size = " << selected_uuids.size() << llendl; if(conversationItem->getType() == LLConversationItem::CONV_PARTICIPANT) { diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index afc8d00174..78c312629d 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -99,6 +99,13 @@ public: void onNearbyChatClosed(); + // Handling of lists of participants is public so to be common with llfloatersessiontab + // *TODO : Find a better place for this. + void doToSelected(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); + bool enableContextMenuItem(const LLSD& userdata); + void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS); + private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; avatarID_panel_map_t mSessions; @@ -127,12 +134,8 @@ private: void getSelectedUUIDs(uuid_vec_t& selected_uuids); const LLConversationItem * getCurSelectedViewModelItem(); void getParticipantUUIDs(uuid_vec_t& selected_uuids); - void doToSelected(const LLSD& userdata); void doToSelectedConversation(const std::string& command, uuid_vec_t& selectedIDS); - void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS); void doToSelectedGroup(const LLSD& userdata); - bool checkContextMenuItem(const LLSD& userdata); - bool enableContextMenuItem(const LLSD& userdata); static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response); bool enableModerateContextMenuItem(const std::string& userdata); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 69b42cdd6d..ef36a485a8 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -69,6 +69,12 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2)); + + // Right click menu handling + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMContainer::checkContextMenuItem, floater_container, _2)); + mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMContainer::enableContextMenuItem, floater_container, _2)); + mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2)); } LLFloaterIMSessionTab::~LLFloaterIMSessionTab() @@ -395,6 +401,7 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant() p.view_model = &mConversationViewModel; p.root = NULL; p.use_ellipses = true; + p.options_menu = "menu_conversation.xml"; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); // Attach that root to the scroller @@ -763,3 +770,35 @@ bool LLFloaterIMSessionTab::checkIfTornOff() return isTorn; } + +void LLFloaterIMSessionTab::doToSelected(const LLSD& userdata) +{ + // Get the list of selected items in the tab + // Note: By construction, those can only be participants so we do not check if they are sessions or something else + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; + getSelectedUUIDs(selected_uuids); + + llinfos << "Merov debug : doToSelected, command = " << command << ", uuid size = " << selected_uuids.size() << llendl; + + // Perform the command (IM, profile, etc...) on the list using the general conversation container method + // *TODO : Move this method to LLAvatarActions + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + floater_container->doToParticipants(command, selected_uuids); +} + +void LLFloaterIMSessionTab::getSelectedUUIDs(uuid_vec_t& selected_uuids) +{ + const std::set<LLFolderViewItem*> selected_items = mConversationsRoot->getSelectionList(); + + std::set<LLFolderViewItem*>::const_iterator it = selected_items.begin(); + const std::set<LLFolderViewItem*>::const_iterator it_end = selected_items.end(); + + for (; it != it_end; ++it) + { + LLConversationItem* conversation_item = static_cast<LLConversationItem *>((*it)->getViewModelItem()); + selected_uuids.push_back(conversation_item->getUUID()); + } +} + + diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index b765d121de..5980416dff 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -157,6 +157,10 @@ protected: LLButton* mCloseBtn; private: + // Handling selection and contextual menu + void getSelectedUUIDs(uuid_vec_t& selected_uuids); + void doToSelected(const LLSD& userdata); + /// Refreshes the floater at a constant rate. virtual void refresh() = 0; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 1ae6fd91ce..1426567196 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1068,7 +1068,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root if ("delete" == action) { LLSD args; - args["QUESTION"] = LLTrans::getString(root->getNumSelectedItems() > 1 ? "DeleteItems" : "DeleteItem"); + args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" : "DeleteItem"); LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root)); return; } -- cgit v1.2.3 From 380b82c7ee562877d25b9b67c1ebf5b79b126fad Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 20 Nov 2012 12:55:38 +0200 Subject: CHUI-487, CHUI-488 Commented out demo --- indra/newview/llfloaterimsessiontab.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 42e7e6cb55..9795df78ae 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -340,8 +340,8 @@ void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD &args) // to demonstrate the correct format call the appropriate functions. // They should be moved to the right places when working on CHUI-486. ~Alex ProductEngine. // ---- start demo ---- - im_box->flashConversationItemWidget(mSessionID, true); // flashing of the conversation's item - gToolBarView->flashCommand(LLCommandId("chat"), true); // flashing of the FUI button "Chat" + // im_box->flashConversationItemWidget(mSessionID, true); // flashing of the conversation's item + // gToolBarView->flashCommand(LLCommandId("chat"), true); // flashing of the FUI button "Chat" // ---- end demo ----- } -- cgit v1.2.3 From 668761e1196517913688bab6763bd9d2e11359b0 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Tue, 20 Nov 2012 13:39:09 +0200 Subject: CHUI-539 FIXED Chat FUI button flashes indefinitely if Icons Only setting is selected for the button display --- indra/newview/skins/default/xui/en/widgets/toolbar.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/widgets/toolbar.xml b/indra/newview/skins/default/xui/en/widgets/toolbar.xml index 55ae158c00..053b213ef4 100644 --- a/indra/newview/skins/default/xui/en/widgets/toolbar.xml +++ b/indra/newview/skins/default/xui/en/widgets/toolbar.xml @@ -51,7 +51,7 @@ chrome="true" use_ellipses="true" auto_resize="true" - button_flash_count="99999" - button_flash_rate="1.0" + button_flash_count="3" + button_flash_rate="0.25" flash_color="EmphasisColor"/> </toolbar> -- cgit v1.2.3 From b87974df51c4caf12c47009dec03b7dc8afe543d Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Tue, 20 Nov 2012 15:18:19 +0200 Subject: CHUI-447 Additional fix(Show only display name for user that starts conversation ) --- indra/newview/llavataractions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 4f57498506..f5d8998ce5 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -180,7 +180,7 @@ void LLAvatarActions::offerTeleport(const uuid_vec_t& ids) static void on_avatar_name_cache_start_im(const LLUUID& agent_id, const LLAvatarName& av_name) { - std::string name = av_name.getCompleteName(); + std::string name = av_name.mDisplayName; LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id); if (session_id != LLUUID::null) { -- cgit v1.2.3 From e52c0218c718fe96a7927f0524c4616022be510e Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Tue, 20 Nov 2012 18:40:53 +0200 Subject: CHUI-523 FIXED Set visibility of warning message depending on combobox state. --- indra/newview/llfloaterpreference.cpp | 30 ++++++++++++++++++++++++++++++ indra/newview/llfloaterpreference.h | 4 ++++ 2 files changed, 34 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index ffd59ba8b6..d08a1d0034 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -443,12 +443,25 @@ BOOL LLFloaterPreference::postBuild() getChild<LLComboBox>("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this)); + getChild<LLComboBox>("FriendIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"FriendIMOptions")); + getChild<LLComboBox>("NonFriendIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"NonFriendIMOptions")); + getChild<LLComboBox>("ConferenceIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"ConferenceIMOptions")); + getChild<LLComboBox>("GroupChatOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"GroupChatOptions")); + getChild<LLComboBox>("NearbyChatOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"NearbyChatOptions")); + // if floater is opened before login set default localized do not disturb message if (LLStartUp::getStartupState() < STATE_STARTED) { gSavedPerAccountSettings.setString("DoNotDisturbModeResponse", LLTrans::getString("DoNotDisturbModeResponseDefault")); } + //get the options that were checked + onNotificationsChange("FriendIMOptions"); + onNotificationsChange("NonFriendIMOptions"); + onNotificationsChange("ConferenceIMOptions"); + onNotificationsChange("GroupChatOptions"); + onNotificationsChange("NearbyChatOptions"); + return TRUE; } @@ -863,6 +876,23 @@ void LLFloaterPreference::onLanguageChange() } } +void LLFloaterPreference::onNotificationsChange(const std::string& OptionName) +{ + mNotificationOptions[OptionName] = getChild<LLComboBox>(OptionName)->getSelectedItemLabel(); + + bool show_notifications_alert = true; + for (notifications_map::iterator it_notification = mNotificationOptions.begin(); it_notification != mNotificationOptions.end(); it_notification++) + { + if(it_notification->second != "None") + { + show_notifications_alert = false; + break; + } + } + + getChild<LLTextBox>("notifications_alert")->setVisible(show_notifications_alert); +} + void LLFloaterPreference::onNameTagOpacityChange(const LLSD& newvalue) { LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>("background"); diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 4c1c122fb1..37a531e99e 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -45,6 +45,8 @@ class LLSliderCtrl; class LLSD; class LLTextBox; +typedef std::map<std::string, std::string> notifications_map; + typedef enum { GS_LOW_GRAPHICS, @@ -93,6 +95,7 @@ protected: void onClickClearCache(); // Clear viewer texture cache, vfs, and VO cache on next startup void onClickBrowserClearCache(); // Clear web history and caches as well as viewer caches above void onLanguageChange(); + void onNotificationsChange(const std::string& OptionName); void onNameTagOpacityChange(const LLSD& newvalue); // set value of "DoNotDisturbResponseChanged" in account settings depending on whether do not disturb response @@ -170,6 +173,7 @@ public: private: static std::string sSkin; + notifications_map mNotificationOptions; bool mClickActionDirty; ///< Set to true when the click/double-click options get changed by user. bool mGotPersonalInfo; bool mOriginalIMViaEmail; -- cgit v1.2.3 From 81478d6c4475f4650a23ad0e87496e3d425d5709 Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Tue, 20 Nov 2012 18:57:29 +0200 Subject: CHUI-490 FIXED Small ui changes. Changed sound that is playing when floater is opened. Call startIM() when user clicks on "Open IM instead" button. --- indra/newview/llimview.cpp | 23 +++------ .../skins/default/xui/en/floater_incoming_call.xml | 58 +++++++++++----------- 2 files changed, 36 insertions(+), 45 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index b5dc4a7967..a4e356f6a9 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -29,6 +29,7 @@ #include "llimview.h" #include "llavatarnamecache.h" // IDEVO +#include "llavataractions.h" #include "llfloaterreg.h" #include "llfontgl.h" #include "llgl.h" @@ -1713,7 +1714,7 @@ BOOL LLCallDialog::postBuild() return FALSE; dockToToolbarButton("speak"); - + return TRUE; } @@ -2110,7 +2111,6 @@ BOOL LLIncomingCallDialog::postBuild() getChildView("Start IM")->setVisible( is_avatar && notify_box_type != "VoiceInviteAdHoc" && notify_box_type != "VoiceInviteGroup"); setCanDrag(FALSE); - return TRUE; } @@ -2118,7 +2118,6 @@ void LLIncomingCallDialog::setCallerName(const std::string& ui_title, const std::string& ui_label, const std::string& call_type) { - setTitle(ui_title); // call_type may be a string like " is calling." LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name"); @@ -2136,7 +2135,7 @@ void LLIncomingCallDialog::onAvatarNameCache(const LLUUID& agent_id, void LLIncomingCallDialog::onOpen(const LLSD& key) { LLCallDialog::onOpen(key); - + make_ui_sound("UISndStartIM"); LLStringUtil::format_map_t args; LLGroupData data; // if it's a group call, retrieve group name to use it in question @@ -2144,18 +2143,6 @@ void LLIncomingCallDialog::onOpen(const LLSD& key) { args["[GROUP]"] = data.mName; } - // tell the user which voice channel they would be leaving - LLVoiceChannel *voice = LLVoiceChannel::getCurrentVoiceChannel(); - if (voice && !voice->getSessionName().empty()) - { - args["[CURRENT_CHAT]"] = voice->getSessionName(); - getChild<LLUICtrl>("question")->setValue(getString(key["question_type"].asString(), args)); - } - else - { - args["[CURRENT_CHAT]"] = getString("localchat"); - getChild<LLUICtrl>("question")->setValue(getString(key["question_type"].asString(), args)); - } } //static @@ -2216,6 +2203,10 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload { gIMMgr->startCall(session_id, LLVoiceChannel::INCOMING_CALL); } + else + { + LLAvatarActions::startIM(caller_id); + } gIMMgr->clearPendingAgentListUpdates(session_id); gIMMgr->clearPendingInvitation(session_id); diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml index 81194f61cf..a7864381a9 100644 --- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml +++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml @@ -8,8 +8,8 @@ layout="topleft" name="incoming call" help_topic="incoming_call" - title="Incoming call" - width="410"> + sound_flags="0" + width="550"> <floater.string name="lifetime"> 5 @@ -24,7 +24,7 @@ </floater.string> <floater.string name="VoiceInviteP2P"> - is calling. + is calling you. </floater.string> <floater.string name="VoiceInviteAdHoc"> @@ -49,14 +49,14 @@ image_name="icon_avatar_online.tga" layout="topleft" left_delta="19" - top="35" + top="20" width="36" /> <group_icon enabled="false" follows="left|top" height="36" layout="topleft" - top="35" + top="20" width="36" /> <text clip_partial="true" @@ -67,43 +67,43 @@ name="caller name" top="20" use_ellipses="true" - width="315" + width="475" word_wrap="true" /> - <text - clip_partial="true" - font="SansSerif" - height="30" - layout="topleft" - left="77" - name="question" - top_pad="5" - use_ellipses="true" - width="315" - word_wrap="true"> - Do you want to leave [CURRENT_CHAT] and join this voice chat? - </text> - <button + <button height="24" - label="Accept" - label_selected="Accept" + label="Answer" + label_selected="Answer" layout="topleft" left="70" name="Accept" - top="92" - width="100" /> + top_pad="5" + width="120" /> <button height="24" - label="Reject" - label_selected="Reject" + label="Ignore" + label_selected="Ignore" layout="topleft" name="Reject" left_pad="10" - width="100" /> + width="120" /> <button height="24" - label="Start IM" + label="Open IM instead" layout="topleft" name="Start IM" left_pad="10" - width="100" /> + width="120" /> + <text + clip_partial="true" + font="SansSerif" + height="30" + layout="topleft" + left="77" + name="question" + top_pad="5" + use_ellipses="true" + width="475" + word_wrap="true"> + If you answer, you will be disconnected from your current voice conversation. + </text> </floater> -- cgit v1.2.3 From 3361c9b911447cf30355d1491ce8dd8962676685 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Tue, 20 Nov 2012 19:47:56 +0200 Subject: CHUI-522 FIXED Implement check box item 'Keep a conversation log and transcript' --- indra/newview/llfloaterimcontainer.cpp | 23 +++++++++++++--------- .../skins/default/xui/en/menu_participant_view.xml | 5 ++++- 2 files changed, 18 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 39cd16acfa..c1a5c9ceeb 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1022,16 +1022,21 @@ void LLFloaterIMContainer::doToSelectedGroup(const LLSD& userdata) bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) { - std::string item = userdata.asString(); + const std::string& item = userdata.asString(); uuid_vec_t uuids; getParticipantUUIDs(uuids); - if(item == std::string("can_activate_group")) + if("can_activate_group" == item) { LLUUID selected_group_id = getCurSelectedViewModelItem()->getUUID(); return gAgent.getGroupID() != selected_group_id; } + if("conversation_log" == item) + { + return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); + } + if(uuids.size() <= 0) { return false; @@ -1040,12 +1045,12 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) // Note: can_block and can_delete is used only for one person selected menu // so we don't need to go over all uuids. - if (item == std::string("can_block")) + if ("can_block" == item) { const LLUUID& id = uuids.front(); return LLAvatarActions::canBlock(id); } - else if (item == std::string("can_add")) + else if ("can_add" == item) { // We can add friends if: // - there are selected people @@ -1074,7 +1079,7 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) return result; } - else if (item == std::string("can_delete")) + else if ("can_delete" == item) { // We can remove friends if: // - there are selected people @@ -1097,18 +1102,18 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) return result; } - else if (item == std::string("can_call")) + else if ("can_call" == item) { return LLAvatarActions::canCall(); } - else if (item == std::string("can_show_on_map")) + else if ("can_show_on_map" == item) { const LLUUID& id = uuids.front(); return (LLAvatarTracker::instance().isBuddyOnline(id) && is_agent_mappable(id)) || gAgent.isGodlike(); } - else if(item == std::string("can_offer_teleport")) + else if("can_offer_teleport" == item) { return LLAvatarActions::canOfferTeleport(uuids); } @@ -1117,7 +1122,7 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) return enableModerateContextMenuItem(item); } - return false; + return false; } bool LLFloaterIMContainer::checkContextMenuItem(const LLSD& userdata) diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml index 523ce7b35b..33d7bd7c01 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_view.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -85,5 +85,8 @@ <menu_item_check.on_click function="Floater.Toggle" parameter="conversation" /> - </menu_item_check> + <menu_item_check.on_enable + function="Avatar.EnableItem" + parameter="conversation_log" /> + </menu_item_check> </toggleable_menu> -- cgit v1.2.3 From 1ece38912188650c9bc5a1cf906ca4a88acc21c4 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 20 Nov 2012 19:17:25 +0200 Subject: CHUI-528, CHUI-536, CHUI-538, CHUI-540 Built single processor of different types of notifications --- indra/newview/llfloaterimsessiontab.cpp | 8 --- indra/newview/llimview.cpp | 110 +++++++++++++++++--------------- 2 files changed, 59 insertions(+), 59 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 9795df78ae..a21ee07d47 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -335,14 +335,6 @@ void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD &args) if (im_box) { im_box->setTimeNow(mSessionID,chat.mFromID); - - // TODO: Warning! The next two lines of code are included below only temporarily - // to demonstrate the correct format call the appropriate functions. - // They should be moved to the right places when working on CHUI-486. ~Alex ProductEngine. - // ---- start demo ---- - // im_box->flashConversationItemWidget(mSessionID, true); // flashing of the conversation's item - // gToolBarView->flashCommand(LLCommandId("chat"), true); // flashing of the FUI button "Chat" - // ---- end demo ----- } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index a4e356f6a9..f0e2f45db3 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -114,76 +114,84 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id, LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); } -void toast_callback(const LLSD& msg){ - // do not show toast in do not disturb mode or it goes from agent - if (gAgent.isDoNotDisturb() || gAgent.getID() == msg["from_id"]) - { - return; - } +void on_new_message(const LLSD& msg) +{ + std::string action; + LLUUID participant_id = msg["from_id"].asUUID(); + LLUUID session_id = msg["session_id"]; + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); - // Skip toasting if we have open window of IM with this session id - LLFloaterIMSession* open_im_floater = LLFloaterIMSession::findInstance(msg["session_id"]); - if ( - open_im_floater - && open_im_floater->isInVisibleChain() - && open_im_floater->hasFocus() - && !open_im_floater->isMinimized() - && !(open_im_floater->getHost() - && open_im_floater->getHost()->isMinimized()) - ) + // determine action for this session + if (session_id.isNull()) { - return; + action = gSavedSettings.getString("NotificationNearbyChatOptions"); } - - // Skip toasting for system messages - if (msg["from_id"].asUUID() == LLUUID::null) - { - return; - } - - // *NOTE Skip toasting if the user disable it in preferences/debug settings ~Alexandrea - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - msg["session_id"]); - - - //Ignore P2P Friend/Non-Friend toasts - if(session->isP2PSessionType()) + else if(session->isP2PSessionType()) { - //Ignores non-friends - if((LLAvatarTracker::instance().getBuddyInfo(msg["from_id"]) == NULL) - && (gSavedSettings.getString("NotificationNonFriendIMOptions") != "toast")) + if (LLAvatarTracker::instance().isBuddy(msg["from_id"].asUUID())) { - return; + action = gSavedSettings.getString("NotificationFriendIMOptions"); } - //Ignores friends - else if(gSavedSettings.getString("NotificationFriendIMOptions") != "toast") + else { - return; + action = gSavedSettings.getString("NotificationNonFriendIMOptions"); } } - //Ignore Ad Hoc Toasts - else if(session->isAdHocSessionType() - && (gSavedSettings.getString("NotificationConferenceIMOptions") != "toast")) + else if(session->isAdHocSessionType()) { - return; + action = gSavedSettings.getString("NotificationConferenceIMOptions"); } - //Ignore Group Toasts - else if(session->isGroupSessionType() - && (gSavedSettings.getString("NotificationGroupChatOptions") != "toast")) + else if(session->isGroupSessionType()) { - return; + action = gSavedSettings.getString("NotificationGroupChatOptions"); } - //Show toast - LLAvatarNameCache::get(msg["from_id"].asUUID(), - boost::bind(&on_avatar_name_cache_toast, - _1, _2, msg)); + // do not show notification in "do not disturb" mode or it goes from agent + if (gAgent.isDoNotDisturb() || gAgent.getID() == participant_id) + { + return; + } + + if ("toast" == action) + { + // Skip toasting if we have open window of IM with this session id + LLFloaterIMSession* open_im_floater = LLFloaterIMSession::findInstance(msg["session_id"]); + if ( + open_im_floater + && open_im_floater->isInVisibleChain() + && open_im_floater->hasFocus() + && !open_im_floater->isMinimized() + && !(open_im_floater->getHost() + && open_im_floater->getHost()->isMinimized()) + ) + { + return; + } + + // Skip toasting for system messages + if (participant_id.isNull()) + { + return; + } + + //Show toast + LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); + } + else if ("flash" == action) + { + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + if (im_box) + { + im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item + } + gToolBarView->flashCommand(LLCommandId("chat"), true); // flashing of the FUI button "Chat" + } } LLIMModel::LLIMModel() { addNewMsgCallback(boost::bind(&LLFloaterIMSession::newIMCallback, _1)); - addNewMsgCallback(boost::bind(&toast_callback, _1)); + addNewMsgCallback(boost::bind(&on_new_message, _1)); } LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg) -- cgit v1.2.3 From edeeed95416be2679e1ad3d29bab5396dbcccaa2 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 21 Nov 2012 01:41:49 +0200 Subject: CHUI-531 FIXED Poor fps in CHUI viewer --- indra/llui/llbutton.cpp | 78 +++++++++++++++++++++++++-------- indra/llui/llbutton.h | 8 +++- indra/llui/llcommandmanager.cpp | 2 + indra/llui/llcommandmanager.h | 6 +++ indra/llui/llflashtimer.cpp | 20 +++++---- indra/llui/llflashtimer.h | 8 ++-- indra/llui/llfolderviewitem.cpp | 24 +++++----- indra/llui/llfolderviewitem.h | 5 +-- indra/llui/lltabcontainer.cpp | 4 +- indra/llui/lltoolbar.cpp | 1 + indra/newview/app_settings/commands.xml | 1 + indra/newview/llconversationview.cpp | 13 ++++++ indra/newview/llconversationview.h | 8 +++- indra/newview/llfloaterimcontainer.cpp | 2 +- 14 files changed, 129 insertions(+), 51 deletions(-) (limited to 'indra') diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 8ac55b2eb4..97547208ec 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -105,6 +105,7 @@ LLButton::Params::Params() badge("badge"), handle_right_mouse("handle_right_mouse"), held_down_delay("held_down_delay"), + button_flash_enable("button_flash_enable", false), button_flash_count("button_flash_count"), button_flash_rate("button_flash_rate") { @@ -170,15 +171,24 @@ LLButton::LLButton(const LLButton::Params& p) mMouseUpSignal(NULL), mHeldDownSignal(NULL), mUseDrawContextAlpha(p.use_draw_context_alpha), - mHandleRightMouse(p.handle_right_mouse) + mHandleRightMouse(p.handle_right_mouse), + mFlashingTimer(NULL) { - // If optional parameter "p.button_flash_count" is not provided, LLFlashTimer will be - // used instead it a "default" value from gSavedSettings.getS32("FlashCount")). - // Likewise, missing "p.button_flash_rate" is replaced by gSavedSettings.getF32("FlashPeriod"). - // Note: flashing should be allowed in settings.xml (boolean key "EnableButtonFlashing"). - S32 flash_count = p.button_flash_count.isProvided()? p.button_flash_count : 0; - F32 flash_rate = p.button_flash_rate.isProvided()? p.button_flash_rate : 0.0; - mFlashingTimer = new LLFlashTimer ((LLFlashTimer::callback_t)NULL, flash_count, flash_rate); + if (p.button_flash_enable) + { + // If optional parameter "p.button_flash_count" is not provided, LLFlashTimer will be + // used instead it a "default" value from gSavedSettings.getS32("FlashCount")). + // Likewise, missing "p.button_flash_rate" is replaced by gSavedSettings.getF32("FlashPeriod"). + // Note: flashing should be allowed in settings.xml (boolean key "EnableButtonFlashing"). + S32 flash_count = p.button_flash_count.isProvided()? p.button_flash_count : 0; + F32 flash_rate = p.button_flash_rate.isProvided()? p.button_flash_rate : 0.0; + mFlashingTimer = new LLFlashTimer ((LLFlashTimer::callback_t)NULL, flash_count, flash_rate); + } + else + { + mButtonFlashCount = p.button_flash_count; + mButtonFlashRate = p.button_flash_rate; + } static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0); static Params default_params(LLUICtrlFactory::getDefaultParams<LLButton>()); @@ -273,7 +283,11 @@ LLButton::~LLButton() delete mMouseDownSignal; delete mMouseUpSignal; delete mHeldDownSignal; - delete mFlashingTimer; + + if (mFlashingTimer) + { + delete mFlashingTimer; + } } // HACK: Committing a button is the same as instantly clicking it. @@ -599,10 +613,29 @@ void LLButton::draw() static LLCachedControl<bool> sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true); F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); - mFlashing = mFlashingTimer->isFlashing(); - - bool flash = mFlashing && - (!sEnableButtonFlashing || mFlashingTimer->isHighlight()); + bool flash = false; + if (mFlashingTimer) + { + mFlashing = mFlashingTimer->isFlashingInProgress(); + flash = mFlashing && (!sEnableButtonFlashing || mFlashingTimer->isCurrentlyHighlighted()); + } + else + { + if(mFlashing) + { + if ( sEnableButtonFlashing) + { + F32 elapsed = mFrameTimer.getElapsedTimeF32(); + S32 flash_count = S32(elapsed * mButtonFlashRate * 2.f); + // flash on or off? + flash = (flash_count % 2 == 0) || flash_count > S32((F32)mButtonFlashCount * 2.f); + } + else + { // otherwise just highlight button in flash color + flash = true; + } + } + } bool pressed_by_keyboard = FALSE; if (hasFocus()) @@ -945,19 +978,26 @@ void LLButton::setToggleState(BOOL b) } } -void LLButton::setFlashing( BOOL b ) +void LLButton::setFlashing( bool b ) { - if (b) + if (mFlashingTimer) { - mFlashingTimer->startFlashing(); + if (b) + { + mFlashingTimer->startFlashing(); + } + else + { + mFlashingTimer->stopFlashing(); + } } - else + else if (b != mFlashing) { - mFlashingTimer->stopFlashing(); + mFlashing = b; + mFrameTimer.reset(); } } - BOOL LLButton::toggleState() { bool flipped = ! getToggleState(); diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 92548298f5..060db59a8a 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -134,6 +134,7 @@ public: Optional<bool> handle_right_mouse; + Optional<bool> button_flash_enable; Optional<S32> button_flash_count; Optional<F32> button_flash_rate; @@ -200,7 +201,7 @@ public: void setToggleState(BOOL b); void setHighlight(bool b); - void setFlashing( BOOL b ); + void setFlashing( bool b ); BOOL getFlashing() const { return mFlashing; } LLFlashTimer* getFlashTimer() {return mFlashingTimer;} @@ -287,6 +288,8 @@ protected: LLFrameTimer mMouseDownTimer; bool mNeedsHighlight; + S32 mButtonFlashCount; + F32 mButtonFlashRate; void drawBorder(LLUIImage* imagep, const LLColor4& color, S32 size); void resetMouseDownTimer(); @@ -373,7 +376,8 @@ protected: bool mForcePressedState; bool mDisplayPressedState; - LLFlashTimer* mFlashingTimer; + LLFrameTimer mFrameTimer; + LLFlashTimer * mFlashingTimer; bool mHandleRightMouse; }; diff --git a/indra/llui/llcommandmanager.cpp b/indra/llui/llcommandmanager.cpp index 0e2f3f1961..625fb8e870 100644 --- a/indra/llui/llcommandmanager.cpp +++ b/indra/llui/llcommandmanager.cpp @@ -63,6 +63,7 @@ LLCommand::Params::Params() , is_running_parameters("is_running_parameters") , is_starting_function("is_starting_function") , is_starting_parameters("is_starting_parameters") + , is_flashing_allowed("is_flashing_allowed", false) { } @@ -83,6 +84,7 @@ LLCommand::LLCommand(const LLCommand::Params& p) , mIsRunningParameters(p.is_running_parameters) , mIsStartingFunction(p.is_starting_function) , mIsStartingParameters(p.is_starting_parameters) + , mIsFlashingAllowed(p.is_flashing_allowed) { } diff --git a/indra/llui/llcommandmanager.h b/indra/llui/llcommandmanager.h index a7276a48aa..ff5a8a3257 100644 --- a/indra/llui/llcommandmanager.h +++ b/indra/llui/llcommandmanager.h @@ -111,6 +111,8 @@ public: Optional<std::string> is_starting_function; Optional<LLSD> is_starting_parameters; + Optional<bool> is_flashing_allowed; + Params(); }; @@ -138,6 +140,8 @@ public: const std::string& isStartingFunctionName() const { return mIsStartingFunction; } const LLSD& isStartingParameters() const { return mIsStartingParameters; } + bool isFlashingAllowed() const { return mIsFlashingAllowed; } + private: LLCommandId mIdentifier; @@ -161,6 +165,8 @@ private: std::string mIsStartingFunction; LLSD mIsStartingParameters; + + bool mIsFlashingAllowed; }; diff --git a/indra/llui/llflashtimer.cpp b/indra/llui/llflashtimer.cpp index c572a83ff5..2ad86b5751 100644 --- a/indra/llui/llflashtimer.cpp +++ b/indra/llui/llflashtimer.cpp @@ -33,15 +33,15 @@ LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) : LLEventTimer(period) , mCallback(cb) , mCurrentTickCount(0) - , mIsFlashing(false) + , mIsFlashingInProgress(false) { mEventTimer.stop(); // By default use settings from settings.xml to be able change them via Debug settings. See EXT-5973. // Due to Timer is implemented as derived class from EventTimer it is impossible to change period // in runtime. So, both settings are made as required restart. - mFlashCount = 2 * ((count>0)? count : gSavedSettings.getS32("FlashCount")); - if (mPeriod<=0) + mFlashCount = 2 * ((count > 0) ? count : gSavedSettings.getS32("FlashCount")); + if (mPeriod <= 0) { mPeriod = gSavedSettings.getF32("FlashPeriod"); } @@ -49,15 +49,18 @@ LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) BOOL LLFlashTimer::tick() { - mIsHighlight = !(mCurrentTickCount % 2); + mIsCurrentlyHighlighted = !mIsCurrentlyHighlighted; + if (mCallback) { - mCallback(mIsHighlight); + mCallback(mIsCurrentlyHighlighted); } if (++mCurrentTickCount >= mFlashCount) { mEventTimer.stop(); + mCurrentTickCount = 0; + mIsFlashingInProgress = false; } return FALSE; @@ -65,15 +68,14 @@ BOOL LLFlashTimer::tick() void LLFlashTimer::startFlashing() { - mCurrentTickCount = 0; - mIsFlashing = true; + mIsFlashingInProgress = true; mEventTimer.start(); } void LLFlashTimer::stopFlashing() { - mIsFlashing = false; - mIsHighlight = false; + mIsFlashingInProgress = false; + mIsCurrentlyHighlighted = false; mEventTimer.stop(); } diff --git a/indra/llui/llflashtimer.h b/indra/llui/llflashtimer.h index 2ef6ebcc8a..538ee0fcca 100644 --- a/indra/llui/llflashtimer.h +++ b/indra/llui/llflashtimer.h @@ -50,8 +50,8 @@ public: void startFlashing(); void stopFlashing(); - bool isFlashing() {return mIsFlashing;} - bool isHighlight() {return mIsHighlight;} + bool isFlashingInProgress() {return mIsFlashingInProgress;} + bool isCurrentlyHighlighted() {return mIsCurrentlyHighlighted;} private: callback_t mCallback; @@ -60,8 +60,8 @@ private: */ S32 mFlashCount; S32 mCurrentTickCount; - bool mIsHighlight; - bool mIsFlashing; + bool mIsCurrentlyHighlighted; + bool mIsFlashingInProgress; }; #endif /* LL_FLASHTIMER_H */ diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index d65f53cd4d..95407d2364 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -145,8 +145,6 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mArrowSize(p.arrow_size), mMaxFolderItemOverlap(p.max_folder_item_overlap) { - mFlashTimer = new LLFlashTimer(); - sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); @@ -168,7 +166,6 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) // Destroys the object LLFolderViewItem::~LLFolderViewItem() { - delete mFlashTimer; mViewModelItem = NULL; } @@ -671,6 +668,16 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L } } +/*virtual*/ bool LLFolderViewItem::isHighlightAllowed() +{ + return mIsSelected; +} + +/*virtual*/ bool LLFolderViewItem::isHighlightActive() +{ + return mIsCurSelection; +} + void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor, const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor) { @@ -683,16 +690,13 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo const S32 focus_bottom = getRect().getHeight() - mItemHeight; const bool folder_open = (getRect().getHeight() > mItemHeight + 4); const S32 FOCUS_LEFT = 1; - bool flashing = mFlashTimer->isFlashing(); - - if (flashing? mFlashTimer->isHighlight() : mIsSelected) // always render "current" item (only render other selected items if - // mShowSingleSelection is FALSE) or flashing item + if (isHighlightAllowed()) // always render "current" item (only render other selected items if + // mShowSingleSelection is FALSE) or flashing item { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLColor4 bg_color = bgColor; - bool selection = flashing? mFlashTimer->isHighlight() : mIsCurSelection; - if (!selection) + if (!isHighlightActive()) { // do time-based fade of extra objects F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); @@ -712,7 +716,7 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo getRect().getWidth() - 2, focus_bottom, bg_color, hasKeyboardFocus); - if (selection) + if (isHighlightActive()) { gl_rect_2d(FOCUS_LEFT, focus_top, diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index c8d6c37b04..c5d6d26e84 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -135,6 +135,8 @@ protected: // no-op at this level, but reimplemented in derived classes. virtual void addItem(LLFolderViewItem*) { } virtual void addFolder(LLFolderViewFolder*) { } + virtual bool isHighlightAllowed(); + virtual bool isHighlightActive(); static LLFontGL* getLabelFontForStyle(U8 style); @@ -163,7 +165,6 @@ public: S32 getIconPad(); S32 getTextPad(); - LLFlashTimer* getFlashTimer() {return mFlashTimer;} // If 'selection' is 'this' then note that otherwise ignore. // Returns TRUE if this item ends up being selected. virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); @@ -274,8 +275,6 @@ public: private: static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts - LLFlashTimer* mFlashTimer; - }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index d1f77830a6..3c1dfc1184 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -506,8 +506,8 @@ void LLTabContainer::draw() } } - mPrevArrowBtn->getFlashTimer()->stopFlashing(); - mNextArrowBtn->getFlashTimer()->stopFlashing(); + mPrevArrowBtn->setFlashing(false); + mNextArrowBtn->setFlashing(false); } diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 81ea0ebf0c..1aa46806c3 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -914,6 +914,7 @@ LLToolBarButton* LLToolBar::createButton(const LLCommandId& id) button_p.label = LLTrans::getString(commandp->labelRef()); button_p.tool_tip = LLTrans::getString(commandp->tooltipRef()); button_p.image_overlay = LLUI::getUIImage(commandp->icon()); + button_p.button_flash_enable = commandp->isFlashingAllowed(); button_p.overwriteFrom(mButtonParams[mButtonType]); LLToolBarButton* button = LLUICtrlFactory::create<LLToolBarButton>(button_p); diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index d4bbd84d0f..4659673333 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -44,6 +44,7 @@ /> <command name="chat" available_in_toybox="true" + is_flashing_allowed="true" icon="Command_Chat_Icon" label_ref="Command_Chat_Label" tooltip_ref="Command_Conversations_Tooltip" diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index b9d62e85c4..e40d57c318 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -82,6 +82,7 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes mVoiceClientObserver(NULL), mMinimizedMode(false) { + mFlashTimer = new LLFlashTimer(); } LLConversationViewSession::~LLConversationViewSession() @@ -92,6 +93,18 @@ LLConversationViewSession::~LLConversationViewSession() { LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); } + + delete mFlashTimer; +} + +bool LLConversationViewSession::isHighlightAllowed() +{ + return mFlashTimer->isFlashingInProgress() || mIsSelected; +} + +bool LLConversationViewSession::isHighlightActive() +{ + return mFlashTimer->isFlashingInProgress() ? mFlashTimer->isCurrentlyHighlighted() : mIsCurSelection; } BOOL LLConversationViewSession::postBuild() diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 8156b746b2..acd7128b7d 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -55,7 +55,10 @@ public: protected: friend class LLUICtrlFactory; LLConversationViewSession( const Params& p ); - + + /*virtual*/ bool isHighlightAllowed(); + /*virtual*/ bool isHighlightActive(); + LLFloaterIMContainer* mContainer; public: @@ -82,6 +85,8 @@ public: virtual void refresh(); + LLFlashTimer * getFlashTimer() { return mFlashTimer; } + private: void onCurrentVoiceSessionChanged(const LLUUID& session_id); @@ -90,6 +95,7 @@ private: LLPanel* mCallIconLayoutPanel; LLTextBox* mSessionTitle; LLOutputMonitorCtrl* mSpeakingIndicator; + LLFlashTimer* mFlashTimer; bool mMinimizedMode; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index bcc7e77116..304fb78260 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1611,7 +1611,7 @@ void LLFloaterIMContainer::reSelectConversation() void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes) { - LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); + LLConversationViewSession * widget = dynamic_cast<LLConversationViewSession *>(get_ptr_in_map(mConversationsWidgets,session_id)); if (widget) { if (is_flashes) -- cgit v1.2.3 From 2dea7a52f616665040d4faff2339e78596a31b90 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Wed, 21 Nov 2012 12:30:12 +0200 Subject: CHUI-535 (Starting a conversation with a user that you have an existing conversation with can cause the conversation list and message panel to be out of synch) fixed --- indra/newview/llfloaterimcontainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 39cd16acfa..f93f741b3f 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -106,7 +106,7 @@ void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::str void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - selectConversation(session_id); + selectConversationPair(session_id, true); } void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) -- cgit v1.2.3 From da5792fcecd1e0a3d84634c0a81bd16d4c04488f Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Wed, 21 Nov 2012 15:14:47 +0200 Subject: CHUI-533 FIXED Check that mConversationsRoot is not null --- indra/newview/llfloaterimsessiontab.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index a21ee07d47..0057ed3231 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -496,8 +496,11 @@ void LLFloaterIMSessionTab::refreshConversation() } mConversationViewModel.requestSortAll(); - mConversationsRoot->arrangeAll(); - mConversationsRoot->update(); + if(mConversationsRoot != NULL) + { + mConversationsRoot->arrangeAll(); + mConversationsRoot->update(); + } updateHeaderAndToolbar(); refresh(); } -- cgit v1.2.3 From a4a6e5a17d2ae715d8f225d90598a079f8adb17d Mon Sep 17 00:00:00 2001 From: maxim_productengine <mnikolenko@productengine.com> Date: Wed, 21 Nov 2012 15:26:56 +0200 Subject: CHUI-523 Additional fix --- indra/newview/llfloaterpreference.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index d08a1d0034..2c3f460701 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -455,13 +455,6 @@ BOOL LLFloaterPreference::postBuild() gSavedPerAccountSettings.setString("DoNotDisturbModeResponse", LLTrans::getString("DoNotDisturbModeResponseDefault")); } - //get the options that were checked - onNotificationsChange("FriendIMOptions"); - onNotificationsChange("NonFriendIMOptions"); - onNotificationsChange("ConferenceIMOptions"); - onNotificationsChange("GroupChatOptions"); - onNotificationsChange("NearbyChatOptions"); - return TRUE; } @@ -703,6 +696,14 @@ void LLFloaterPreference::onOpen(const LLSD& key) // while preferences floater was closed. buildPopupLists(); + + //get the options that were checked + onNotificationsChange("FriendIMOptions"); + onNotificationsChange("NonFriendIMOptions"); + onNotificationsChange("ConferenceIMOptions"); + onNotificationsChange("GroupChatOptions"); + onNotificationsChange("NearbyChatOptions"); + LLPanelLogin::setAlwaysRefresh(true); refresh(); -- cgit v1.2.3 From a12464b9cbc40d4584d6968db2092a56fa3f4bc6 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 21 Nov 2012 11:46:38 -0800 Subject: CHUI-429, CHUI-511, CHUI-388 : Multiselection and menus in torn off dialogs --- indra/newview/llconversationmodel.cpp | 7 +- indra/newview/llfloaterimcontainer.cpp | 225 ++++++++++----------- indra/newview/llfloaterimcontainer.h | 1 + indra/newview/llfloaterimsessiontab.cpp | 18 +- indra/newview/llfloaterimsessiontab.h | 1 + .../skins/default/xui/en/menu_conversation.xml | 12 +- 6 files changed, 142 insertions(+), 122 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 1c56bd672d..0837a49095 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -27,7 +27,6 @@ #include "llviewerprecompiledheaders.h" -#include "llagent.h" #include "llavatarnamecache.h" #include "llavataractions.h" #include "llevents.h" @@ -422,10 +421,8 @@ void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t items; menuentry_vec_t disabled_items; - if(gAgent.getID() != mUUID) - { - buildParticipantMenuOptions(items); - } + buildParticipantMenuOptions(items); + hide_context_entries(menu, items, disabled_items); } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 65a8aee4ce..079cd71039 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -869,68 +869,83 @@ void LLFloaterIMContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec_t& selectedIDS) { - // *TODO : This is where we need to handle a *list* of participant correctly - if(selectedIDS.size() > 0) + if (selectedIDS.size() == 1) { const LLUUID& userID = selectedIDS.front(); - if(gAgent.getID() != userID) + if ("view_profile" == command) { - if ("view_profile" == command) - { - LLAvatarActions::showProfile(userID); - } - else if("im" == command) - { - LLAvatarActions::startIM(userID); - } - else if("offer_teleport" == command) - { - LLAvatarActions::offerTeleport(selectedIDS); - } - else if("voice_call" == command) - { - LLAvatarActions::startCall(userID); - } - else if("chat_history" == command) - { - LLAvatarActions::viewChatHistory(userID); - } - else if("add_friend" == command) - { - LLAvatarActions::requestFriendshipDialog(userID); - } - else if("remove_friend" == command) - { - LLAvatarActions::removeFriendDialog(userID); - } - else if("invite_to_group" == command) - { - LLAvatarActions::inviteToGroup(userID); - } - else if("map" == command) - { - LLAvatarActions::showOnMap(userID); - } - else if("share" == command) - { - LLAvatarActions::share(userID); - } - else if("pay" == command) - { - LLAvatarActions::pay(userID); - } - else if("block_unblock" == command) - { - LLAvatarActions::toggleBlock(userID); - } - else if("selected" == command || "mute_all" == command || "unmute_all" == command) - { - moderateVoice(command, userID); - } - else if ("toggle_allow_text_chat" == command) - { - toggleAllowTextChat(userID); - } + LLAvatarActions::showProfile(userID); + } + else if ("im" == command) + { + LLAvatarActions::startIM(userID); + } + else if ("offer_teleport" == command) + { + LLAvatarActions::offerTeleport(selectedIDS); + } + else if ("voice_call" == command) + { + LLAvatarActions::startCall(userID); + } + else if ("chat_history" == command) + { + LLAvatarActions::viewChatHistory(userID); + } + else if ("add_friend" == command) + { + LLAvatarActions::requestFriendshipDialog(userID); + } + else if ("remove_friend" == command) + { + LLAvatarActions::removeFriendDialog(userID); + } + else if ("invite_to_group" == command) + { + LLAvatarActions::inviteToGroup(userID); + } + else if ("map" == command) + { + LLAvatarActions::showOnMap(userID); + } + else if ("share" == command) + { + LLAvatarActions::share(userID); + } + else if ("pay" == command) + { + LLAvatarActions::pay(userID); + } + else if ("block_unblock" == command) + { + LLAvatarActions::toggleBlock(userID); + } + else if ("selected" == command || "mute_all" == command || "unmute_all" == command) + { + moderateVoice(command, userID); + } + else if ("toggle_allow_text_chat" == command) + { + toggleAllowTextChat(userID); + } + } + else if (selectedIDS.size() > 1) + { + if ("im" == command) + { + LLAvatarActions::startConference(selectedIDS); + } + else if ("offer_teleport" == command) + { + LLAvatarActions::offerTeleport(selectedIDS); + } + else if ("voice_call" == command) + { + LLAvatarActions::startAdhocCall(selectedIDS); + } + else if ("remove_friend" == command) + { + LLAvatarActions::removeFriendsDialog(selectedIDS); } } } @@ -1021,75 +1036,61 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) uuid_vec_t uuids; getParticipantUUIDs(uuids); - if(item == std::string("can_activate_group")) + if (item == std::string("can_activate_group")) { LLUUID selected_group_id = getCurSelectedViewModelItem()->getUUID(); return gAgent.getGroupID() != selected_group_id; } + + return enableContextMenuItem(item, uuids); +} - if(uuids.size() <= 0) +bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_vec_t& uuids) +{ + // If nothing is selected, everything needs to be disabled + if (uuids.size() <= 0) { return false; } + + // Extract the single select info + bool is_single_select = (uuids.size() == 1); + const LLUUID& single_id = uuids.front(); + + // Handle options that are applicable to all including the user agent + if ("can_view_profile" == item) + { + return is_single_select; + } + + // Beyond that point, if only the user agent is selected, everything is disabled + if (is_single_select && (single_id == gAgentID)) + { + return false; + } - // Note: can_block and can_delete is used only for one person selected menu - // so we don't need to go over all uuids. - + // Handle all other options if (item == std::string("can_block")) { - const LLUUID& id = uuids.front(); - return LLAvatarActions::canBlock(id); + return (is_single_select ? LLAvatarActions::canBlock(single_id) : false); } else if (item == std::string("can_add")) { // We can add friends if: - // - there are selected people - // - and there are no friends among selection yet. - - //EXT-7389 - disable for more than 1 - if(uuids.size() > 1) - { - return false; - } - - bool result = true; - - uuid_vec_t::const_iterator - id = uuids.begin(), - uuids_end = uuids.end(); - - for (;id != uuids_end; ++id) - { - if ( LLAvatarActions::isFriend(*id) ) - { - result = false; - break; - } - } - - return result; + // - there is only 1 selected avatar (EXT-7389) + // - this avatar is not a friend yet + return (is_single_select ? !LLAvatarActions::isFriend(single_id) : false); } else if (item == std::string("can_delete")) { // We can remove friends if: // - there are selected people - // - and there are only friends among selection. - - bool result = (uuids.size() > 0); - - uuid_vec_t::const_iterator - id = uuids.begin(), - uuids_end = uuids.end(); - - for (;id != uuids_end; ++id) + // - and there are only friends among the selection + bool result = true; + for (uuid_vec_t::const_iterator id = uuids.begin(); id != uuids.end(); ++id) { - if ( !LLAvatarActions::isFriend(*id) ) - { - result = false; - break; - } + result &= LLAvatarActions::isFriend(*id); } - return result; } else if (item == std::string("can_call")) @@ -1098,21 +1099,19 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) } else if (item == std::string("can_show_on_map")) { - const LLUUID& id = uuids.front(); - - return (LLAvatarTracker::instance().isBuddyOnline(id) && is_agent_mappable(id)) - || gAgent.isGodlike(); + return (is_single_select ? (LLAvatarTracker::instance().isBuddyOnline(single_id) && is_agent_mappable(single_id)) || gAgent.isGodlike() : false); } - else if(item == std::string("can_offer_teleport")) + else if (item == std::string("can_offer_teleport")) { return LLAvatarActions::canOfferTeleport(uuids); } - else if("can_moderate_voice" == item || "can_allow_text_chat" == item || "can_mute" == item || "can_unmute" == item) + else if ("can_moderate_voice" == item || "can_allow_text_chat" == item || "can_mute" == item || "can_unmute" == item) { return enableModerateContextMenuItem(item); } - return false; + // By default, options that not explicitely disabled are enabled + return true; } bool LLFloaterIMContainer::checkContextMenuItem(const LLSD& userdata) diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 78c312629d..3d82ccfc21 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -104,6 +104,7 @@ public: void doToSelected(const LLSD& userdata); bool checkContextMenuItem(const LLSD& userdata); bool enableContextMenuItem(const LLSD& userdata); + bool enableContextMenuItem(const std::string& item, uuid_vec_t& selectedIDS); void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS); private: diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index ef36a485a8..751b3c9db8 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -73,7 +73,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) // Right click menu handling LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMContainer::checkContextMenuItem, floater_container, _2)); - mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMContainer::enableContextMenuItem, floater_container, _2)); + mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2)); mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2)); } @@ -787,6 +787,22 @@ void LLFloaterIMSessionTab::doToSelected(const LLSD& userdata) floater_container->doToParticipants(command, selected_uuids); } +bool LLFloaterIMSessionTab::enableContextMenuItem(const LLSD& userdata) +{ + // Get the list of selected items in the tab + // Note: By construction, those can only be participants so we do not check if they are sessions or something else + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; + getSelectedUUIDs(selected_uuids); + + llinfos << "Merov debug : enableContextMenuItem, command = " << command << ", uuid size = " << selected_uuids.size() << llendl; + + // Perform the command (IM, profile, etc...) on the list using the general conversation container method + // *TODO : Move this method to LLAvatarActions + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + return floater_container->enableContextMenuItem(command, selected_uuids); +} + void LLFloaterIMSessionTab::getSelectedUUIDs(uuid_vec_t& selected_uuids) { const std::set<LLFolderViewItem*> selected_items = mConversationsRoot->getSelectionList(); diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 5980416dff..0154839287 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -160,6 +160,7 @@ private: // Handling selection and contextual menu void getSelectedUUIDs(uuid_vec_t& selected_uuids); void doToSelected(const LLSD& userdata); + bool enableContextMenuItem(const LLSD& userdata); /// Refreshes the floater at a constant rate. virtual void refresh() = 0; diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index 2e9bda5804..908b2c174f 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -30,12 +30,14 @@ layout="topleft" name="view_profile"> <on_click function="Avatar.DoToSelected" parameter="view_profile"/> + <on_enable function="Avatar.EnableItem" parameter="can_view_profile"/> </menu_item_call> <menu_item_call label="IM" layout="topleft" name="im"> <on_click function="Avatar.DoToSelected" parameter="im"/> + <on_enable function="Avatar.EnableItem" parameter="can_im"/> </menu_item_call> <menu_item_call label="Offer teleport" @@ -56,6 +58,7 @@ layout="topleft" name="chat_history"> <on_click function="Avatar.DoToSelected" parameter="chat_history"/> + <on_enable function="Avatar.EnableItem" parameter="can_chat_history"/> </menu_item_call> <menu_item_separator layout="topleft" name="separator_chat_history"/> <menu_item_call @@ -77,6 +80,7 @@ layout="topleft" name="invite_to_group"> <on_click function="Avatar.DoToSelected" parameter="invite_to_group" /> + <on_enable function="Avatar.EnableItem" parameter="can_invite" /> </menu_item_call> <menu_item_separator layout="topleft" name="separator_invite_to_group"/> <menu_item_call @@ -91,12 +95,14 @@ layout="topleft" name="share"> <on_click function="Avatar.DoToSelected" parameter="share" /> + <on_enable function="Avatar.EnableItem" parameter="can_share" /> </menu_item_call> <menu_item_call label="Pay" layout="topleft" name="pay"> <on_click function="Avatar.DoToSelected" parameter="pay" /> + <on_enable function="Avatar.EnableItem" parameter="can_pay" /> </menu_item_call> <menu_item_check label="Block / unblock" @@ -111,6 +117,7 @@ layout="topleft" name="group_profile"> <on_click function="Group.DoToSelected" parameter="group_profile"/> + <on_enable function="Avatar.EnableItem" parameter="can_group_profile" /> </menu_item_call> <menu_item_call label="Activate Group" @@ -124,10 +131,9 @@ layout="topleft" name="leave_group"> <on_click function="Group.DoToSelected" parameter="leave_group"/> + <on_enable function="Avatar.EnableItem" parameter="can_leave_group" /> </menu_item_call> - <menu_item_separator - layout="topleft" - name="Moderator Options Separator"/> + <menu_item_separator layout="topleft" name="Moderator Options Separator"/> <context_menu label="Moderator Options" layout="topleft" -- cgit v1.2.3 From 7ca2508cc2adcdc5201bd53e814246e156bc6013 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 21 Nov 2012 18:15:24 -0800 Subject: CHUI-429 : Completed this though it still doesn't work on Nearby Chat. --- indra/newview/llfloaterimcontainer.cpp | 42 +++++++++++++++++++-------------- indra/newview/llfloaterimcontainer.h | 7 +++--- indra/newview/llfloaterimnearbychat.cpp | 21 +++++++++-------- indra/newview/llfloaterimnearbychat.h | 2 +- indra/newview/llfloaterimsessiontab.cpp | 26 +++++++++++--------- indra/newview/llfloaterimsessiontab.h | 4 +++- 6 files changed, 58 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 079cd71039..a56705d969 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -98,7 +98,6 @@ LLFloaterIMContainer::~LLFloaterIMContainer() void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) { - llinfos << "Merov debug : sessionAdded, uuid = " << session_id << ", name = " << name << llendl; addConversationListItem(session_id); LLFloaterIMSessionTab::addToHost(session_id); } @@ -998,8 +997,6 @@ void LLFloaterIMContainer::doToSelected(const LLSD& userdata) { getParticipantUUIDs(selected_uuids); - llinfos << "Merov debug : doToSelected, command = " << command << ", name = " << conversationItem->getName() << ", uuid size = " << selected_uuids.size() << llendl; - if(conversationItem->getType() == LLConversationItem::CONV_PARTICIPANT) { doToParticipants(command, selected_uuids); @@ -1070,22 +1067,25 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v } // Handle all other options - if (item == std::string("can_block")) + if (("can_invite" == item) || ("can_chat_history" == item) || ("can_share" == item) || ("can_pay" == item)) + { + // Those menu items are enable only if a single avatar is selected + return is_single_select; + } + else if ("can_block" == item) { return (is_single_select ? LLAvatarActions::canBlock(single_id) : false); } - else if (item == std::string("can_add")) + else if ("can_add" == item) { // We can add friends if: // - there is only 1 selected avatar (EXT-7389) - // - this avatar is not a friend yet + // - this avatar is not already a friend return (is_single_select ? !LLAvatarActions::isFriend(single_id) : false); } - else if (item == std::string("can_delete")) + else if ("can_delete" == item) { - // We can remove friends if: - // - there are selected people - // - and there are only friends among the selection + // We can remove friends if there are only friends among the selection bool result = true; for (uuid_vec_t::const_iterator id = uuids.begin(); id != uuids.end(); ++id) { @@ -1093,20 +1093,21 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v } return result; } - else if (item == std::string("can_call")) + else if ("can_call" == item) { return LLAvatarActions::canCall(); } - else if (item == std::string("can_show_on_map")) + else if ("can_show_on_map" == item) { return (is_single_select ? (LLAvatarTracker::instance().isBuddyOnline(single_id) && is_agent_mappable(single_id)) || gAgent.isGodlike() : false); } - else if (item == std::string("can_offer_teleport")) + else if ("can_offer_teleport" == item) { return LLAvatarActions::canOfferTeleport(uuids); } - else if ("can_moderate_voice" == item || "can_allow_text_chat" == item || "can_mute" == item || "can_unmute" == item) + else if (("can_moderate_voice" == item) || ("can_allow_text_chat" == item) || ("can_mute" == item) || ("can_unmute" == item)) { + // *TODO : get that out of here... return enableModerateContextMenuItem(item); } @@ -1117,14 +1118,19 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v bool LLFloaterIMContainer::checkContextMenuItem(const LLSD& userdata) { std::string item = userdata.asString(); - uuid_vec_t mUUIDs; - getParticipantUUIDs(mUUIDs); + uuid_vec_t uuids; + getParticipantUUIDs(uuids); + + return checkContextMenuItem(item, uuids); +} - if(mUUIDs.size() > 0 ) +bool LLFloaterIMContainer::checkContextMenuItem(const std::string& item, uuid_vec_t& uuids) +{ + if (uuids.size() == 1) { if ("is_blocked" == item) { - return LLAvatarActions::isBlocked(mUUIDs.front()); + return LLAvatarActions::isBlocked(uuids.front()); } else if ("is_allowed_text_chat" == item) { diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 3d82ccfc21..bec0c3ef14 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -101,9 +101,7 @@ public: // Handling of lists of participants is public so to be common with llfloatersessiontab // *TODO : Find a better place for this. - void doToSelected(const LLSD& userdata); - bool checkContextMenuItem(const LLSD& userdata); - bool enableContextMenuItem(const LLSD& userdata); + bool checkContextMenuItem(const std::string& item, uuid_vec_t& selectedIDS); bool enableContextMenuItem(const std::string& item, uuid_vec_t& selectedIDS); void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS); @@ -135,6 +133,9 @@ private: void getSelectedUUIDs(uuid_vec_t& selected_uuids); const LLConversationItem * getCurSelectedViewModelItem(); void getParticipantUUIDs(uuid_vec_t& selected_uuids); + void doToSelected(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); + bool enableContextMenuItem(const LLSD& userdata); void doToSelectedConversation(const std::string& command, uuid_vec_t& selectedIDS); void doToSelectedGroup(const LLSD& userdata); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 5867eb3e84..7002342c0b 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -112,6 +112,7 @@ BOOL LLFloaterIMNearbyChat::postBuild() { setIsSingleInstance(TRUE); BOOL result = LLFloaterIMSessionTab::postBuild(); + mInputEditor->setCommitCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxCommit, this)); mInputEditor->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this)); mInputEditor->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); @@ -122,24 +123,24 @@ BOOL LLFloaterIMNearbyChat::postBuild() // mOutputMonitor->setVisible(FALSE); // Register for font change notifications - LLViewerChat::setFontChangedCallback(boost::bind(&LLFloaterIMNearbyChat::onChatFontChange, this, _1)); +// LLViewerChat::setFontChangedCallback(boost::bind(&LLFloaterIMNearbyChat::onChatFontChange, this, _1)); // title must be defined BEFORE call addConversationListItem() because // it is used for show the item's name in the conversations list setTitle(LLTrans::getString("NearbyChatTitle")); //for menu - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; +// LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +// LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - enable_registrar.add("NearbyChat.Check", boost::bind(&LLFloaterIMNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); - registrar.add("NearbyChat.Action", boost::bind(&LLFloaterIMNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); +// enable_registrar.add("NearbyChat.Check", boost::bind(&LLFloaterIMNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); +// registrar.add("NearbyChat.Action", boost::bind(&LLFloaterIMNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(menu) - { - mPopupMenuHandle = menu->getHandle(); - } +// LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +// if(menu) +// { +// mPopupMenuHandle = menu->getHandle(); +// } // obsolete, but may be needed for backward compatibility? gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index 1479746fbd..5ed639136b 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -117,7 +117,7 @@ private: /*virtual*/ void refresh(); - LLHandle<LLView> mPopupMenuHandle; +// LLHandle<LLView> mPopupMenuHandle; std::vector<LLChat> mMessageArchive; }; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 751b3c9db8..3fb24f52c4 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -71,8 +71,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2)); // Right click menu handling - LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); - mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMContainer::checkContextMenuItem, floater_container, _2)); + mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem, this, _2)); mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2)); mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2)); } @@ -774,35 +773,40 @@ bool LLFloaterIMSessionTab::checkIfTornOff() void LLFloaterIMSessionTab::doToSelected(const LLSD& userdata) { // Get the list of selected items in the tab - // Note: By construction, those can only be participants so we do not check if they are sessions or something else std::string command = userdata.asString(); uuid_vec_t selected_uuids; getSelectedUUIDs(selected_uuids); - llinfos << "Merov debug : doToSelected, command = " << command << ", uuid size = " << selected_uuids.size() << llendl; - // Perform the command (IM, profile, etc...) on the list using the general conversation container method - // *TODO : Move this method to LLAvatarActions LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + // Note: By construction, those can only be participants so we can call doToParticipants() directly floater_container->doToParticipants(command, selected_uuids); } bool LLFloaterIMSessionTab::enableContextMenuItem(const LLSD& userdata) { // Get the list of selected items in the tab - // Note: By construction, those can only be participants so we do not check if they are sessions or something else std::string command = userdata.asString(); uuid_vec_t selected_uuids; getSelectedUUIDs(selected_uuids); - llinfos << "Merov debug : enableContextMenuItem, command = " << command << ", uuid size = " << selected_uuids.size() << llendl; - - // Perform the command (IM, profile, etc...) on the list using the general conversation container method - // *TODO : Move this method to LLAvatarActions + // Perform the item enable test on the list using the general conversation container method LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); return floater_container->enableContextMenuItem(command, selected_uuids); } +bool LLFloaterIMSessionTab::checkContextMenuItem(const LLSD& userdata) +{ + // Get the list of selected items in the tab + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; + getSelectedUUIDs(selected_uuids); + + // Perform the item check on the list using the general conversation container method + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + return floater_container->checkContextMenuItem(command, selected_uuids); +} + void LLFloaterIMSessionTab::getSelectedUUIDs(uuid_vec_t& selected_uuids) { const std::set<LLFolderViewItem*> selected_items = mConversationsRoot->getSelectionList(); diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 0154839287..8efa0955fc 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -158,9 +158,11 @@ protected: private: // Handling selection and contextual menu - void getSelectedUUIDs(uuid_vec_t& selected_uuids); void doToSelected(const LLSD& userdata); bool enableContextMenuItem(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); + + void getSelectedUUIDs(uuid_vec_t& selected_uuids); /// Refreshes the floater at a constant rate. virtual void refresh() = 0; -- cgit v1.2.3 From cbe90ebc9cbda965b03db2757cdb356d5f831d44 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Fri, 23 Nov 2012 19:05:28 +0200 Subject: Additional fix for CHUI-490 (Show "Display Name (user.name)" for the user that is calling) --- indra/newview/llimview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index f0e2f45db3..5aceb6c66b 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2137,7 +2137,7 @@ void LLIncomingCallDialog::onAvatarNameCache(const LLUUID& agent_id, const std::string& call_type) { std::string title = av_name.getCompleteName(); - setCallerName(title, av_name.mDisplayName, call_type); + setCallerName(title, av_name.getCompleteName(), call_type); } void LLIncomingCallDialog::onOpen(const LLSD& key) -- cgit v1.2.3 From a83676e1ab6ae6c12e28c5f568ac933c2e97408c Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Fri, 23 Nov 2012 19:56:59 +0200 Subject: CHUI-530 FIXED Don't switch to new conversation automatically --- indra/newview/llfloaterimsessiontab.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 0057ed3231..dcf1b52118 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -162,7 +162,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id) if (!conversp->isNearbyChat() || gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) { - floater_container->addFloater(conversp, TRUE, LLTabContainer::END); + floater_container->addFloater(conversp, FALSE, LLTabContainer::END); if (!floater_container->getVisible()) { -- cgit v1.2.3 From f37645554ce97026869563aedea8f8c6133d8044 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 23 Nov 2012 13:39:53 +0200 Subject: CHUI-528, CHUI-536, CHUI-538, CHUI-540 ADD. FIX (Built single processor of different types of notifications): repaired LLFlashTimer --- indra/llui/llflashtimer.cpp | 19 +++++++++++++++---- indra/llui/llflashtimer.h | 4 ++-- 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/llflashtimer.cpp b/indra/llui/llflashtimer.cpp index 2ad86b5751..de7a4ab265 100644 --- a/indra/llui/llflashtimer.cpp +++ b/indra/llui/llflashtimer.cpp @@ -34,6 +34,7 @@ LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) , mCallback(cb) , mCurrentTickCount(0) , mIsFlashingInProgress(false) + , mIsCurrentlyHighlighted(false) { mEventTimer.stop(); @@ -58,9 +59,7 @@ BOOL LLFlashTimer::tick() if (++mCurrentTickCount >= mFlashCount) { - mEventTimer.stop(); - mCurrentTickCount = 0; - mIsFlashingInProgress = false; + stopFlashing(); } return FALSE; @@ -69,14 +68,26 @@ BOOL LLFlashTimer::tick() void LLFlashTimer::startFlashing() { mIsFlashingInProgress = true; + mIsCurrentlyHighlighted = true; mEventTimer.start(); } void LLFlashTimer::stopFlashing() { + mEventTimer.stop(); mIsFlashingInProgress = false; mIsCurrentlyHighlighted = false; - mEventTimer.stop(); + mCurrentTickCount = 0; +} + +bool LLFlashTimer::isFlashingInProgress() +{ + return mIsFlashingInProgress; +} + +bool LLFlashTimer::isCurrentlyHighlighted() +{ + return mIsCurrentlyHighlighted; } diff --git a/indra/llui/llflashtimer.h b/indra/llui/llflashtimer.h index 538ee0fcca..5c8860b097 100644 --- a/indra/llui/llflashtimer.h +++ b/indra/llui/llflashtimer.h @@ -50,8 +50,8 @@ public: void startFlashing(); void stopFlashing(); - bool isFlashingInProgress() {return mIsFlashingInProgress;} - bool isCurrentlyHighlighted() {return mIsCurrentlyHighlighted;} + bool isFlashingInProgress(); + bool isCurrentlyHighlighted(); private: callback_t mCallback; -- cgit v1.2.3 From 01a43d0a04bdbd286ef61985c356029f3d12e324 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 23 Nov 2012 15:10:28 +0200 Subject: CHUI-528, CHUI-536, CHUI-538, CHUI-540 ADD. FIX (Built single processor of different types of notifications): changed item's highlighting --- indra/llui/llfolderviewitem.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 95407d2364..89c7e0d14a 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -711,12 +711,17 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); } } - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - bg_color, hasKeyboardFocus); - if (isHighlightActive()) + + if (!isHighlightAllowed() || isHighlightActive()) + { + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + bg_color, hasKeyboardFocus); + } + + if (mIsCurSelection) { gl_rect_2d(FOCUS_LEFT, focus_top, -- cgit v1.2.3 From 2ce98c8b14d86bb5c8078c762bfc32b6fc4d8346 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 23 Nov 2012 15:13:28 +0200 Subject: CHUI-528, CHUI-536, CHUI-538, CHUI-540 ADD. FIX (Built single processor of different types of notifications): include flashing for the nearby chat --- indra/newview/llviewermessage.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra') diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index e21db146db..dc8192105f 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -65,6 +65,7 @@ #include "llfloatersnapshot.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" +#include "llimview.h" #include "llinventoryfunctions.h" #include "llinventoryobserver.h" #include "llinventorypanel.h" @@ -120,6 +121,8 @@ #pragma warning (disable:4702) #endif +extern void on_new_message(const LLSD& msg); + // // Constants // @@ -3641,6 +3644,11 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) { LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args); } + + LLSD msg_notify = LLSD(LLSD::emptyMap()); + msg_notify["session_id"] = LLUUID(); + msg_notify["from_id"] = chat.mFromID; + on_new_message(msg_notify); } } -- cgit v1.2.3 From 890965faf5baa5f6f832e086991d59bb8d33b7bc Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 23 Nov 2012 15:14:17 +0200 Subject: CHUI-528, CHUI-536, CHUI-538, CHUI-540 ADD. FIX (Built single processor of different types of notifications): clean up code --- indra/newview/llimview.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 5aceb6c66b..db52a50aa1 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -118,17 +118,18 @@ void on_new_message(const LLSD& msg) { std::string action; LLUUID participant_id = msg["from_id"].asUUID(); - LLUUID session_id = msg["session_id"]; + LLUUID session_id = msg["session_id"].asUUID(); LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); // determine action for this session + if (session_id.isNull()) { action = gSavedSettings.getString("NotificationNearbyChatOptions"); } else if(session->isP2PSessionType()) { - if (LLAvatarTracker::instance().isBuddy(msg["from_id"].asUUID())) + if (LLAvatarTracker::instance().isBuddy(participant_id)) { action = gSavedSettings.getString("NotificationFriendIMOptions"); } @@ -152,10 +153,12 @@ void on_new_message(const LLSD& msg) return; } + // execution of the action + if ("toast" == action) { // Skip toasting if we have open window of IM with this session id - LLFloaterIMSession* open_im_floater = LLFloaterIMSession::findInstance(msg["session_id"]); + LLFloaterIMSession* open_im_floater = LLFloaterIMSession::findInstance(session_id); if ( open_im_floater && open_im_floater->isInVisibleChain() -- cgit v1.2.3 From a243a0475e9bc87ec4acf31700443461ebc58a54 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Mon, 26 Nov 2012 12:24:11 +0200 Subject: CHUI-542 (Torn off message in conversation panel is not cleared when torn off conversation is closed) --- indra/newview/llfloaterimcontainer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 304fb78260..d4b552deae 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1353,10 +1353,12 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c setFocus(TRUE); if(new_selection != NULL) { + if (mConversationsWidgets.size() == 1) + new_selection = new_selection->getParentFolder(); LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem()); if(vmi != NULL) { - selectConversation(vmi->getUUID()); + selectConversationPair(vmi->getUUID(), true); } } } -- cgit v1.2.3 From 1a3c5e574bb262f4b334b1c00c671db346c1c658 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 26 Nov 2012 17:49:16 -0800 Subject: CHUI-528, CHUI-536, CHUI-538, CHUI-540: Fixed the changed item's highlighting that broke multiselection in inventory and in conversations. --- indra/llui/llfolderviewitem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 89c7e0d14a..261f53d6b6 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -712,7 +712,7 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo } } - if (!isHighlightAllowed() || isHighlightActive()) + if (isHighlightAllowed() || isHighlightActive()) { gl_rect_2d(FOCUS_LEFT, focus_top, @@ -721,7 +721,7 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo bg_color, hasKeyboardFocus); } - if (mIsCurSelection) + if (isHighlightActive()) { gl_rect_2d(FOCUS_LEFT, focus_top, -- cgit v1.2.3 From 4105ae946707947e469793364e07adde7993cffe Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 26 Nov 2012 19:12:04 -0800 Subject: CHUI-529: Post code review changes. When showing a floater using LLFloater::showInstance() instead of setVisibleAndFrontmost(). Also made setVisibleAndFrontmost() public since both setVisible and setFrontmost are public functions. --- indra/llui/llfloater.h | 2 +- indra/newview/llfloaterimnearbychathandler.cpp | 8 +------- indra/newview/llimview.cpp | 8 +------- 3 files changed, 3 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index a657538eb7..9ad566a1a1 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -302,6 +302,7 @@ public: /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); // do not override void setFrontmost(BOOL take_focus = TRUE); + virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE); // Defaults to false. virtual BOOL canSaveAs() const { return FALSE; } @@ -373,7 +374,6 @@ protected: void setInstanceName(const std::string& name); virtual void bringToFront(S32 x, S32 y); - virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE); void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized const LLRect& getExpandedRect() const { return mExpandedRect; } diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 2d8a6d46fe..d9c461e836 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -622,13 +622,7 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, //Will show Conversations floater when chat preference is set else if(gSavedSettings.getString("NotificationNearbyChatOptions") == "openconversations") { - LLFloaterIMContainer * floaterIMContainer = LLFloaterIMContainer::getInstance(); - - if(floaterIMContainer) - { - floaterIMContainer->setVisible(TRUE); - floaterIMContainer->setFrontmost(TRUE); - } + LLFloaterReg::showInstance("im_container"); } } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index fc6be2cd97..581043a3d0 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -191,13 +191,7 @@ void on_new_message(const LLSD& msg) } else if("openconversations" == action) { - LLFloaterIMContainer * floaterIMContainer = LLFloaterIMContainer::getInstance(); - - if(floaterIMContainer) - { - floaterIMContainer->setVisible(TRUE); - floaterIMContainer->setFrontmost(TRUE); - } + LLFloaterReg::showInstance("im_container"); } } -- cgit v1.2.3 From d9ad20055330e0911a553af284359a5cf5711b7b Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Tue, 27 Nov 2012 17:55:50 +0200 Subject: CHUI-544 (Legacy name shows in conversation list for user that answers a voice call) --- indra/newview/llavataractions.cpp | 2 +- indra/newview/llvoicevivox.cpp | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index f5d8998ce5..1969a0bc5f 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -215,7 +215,7 @@ void LLAvatarActions::endIM(const LLUUID& id) static void on_avatar_name_cache_start_call(const LLUUID& agent_id, const LLAvatarName& av_name) { - std::string name = av_name.getCompleteName(); + std::string name = av_name.mDisplayName; LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id, true); if (session_id != LLUUID::null) { diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 3a26f14772..37491e5b58 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -6200,10 +6200,8 @@ void LLVivoxVoiceClient::lookupName(const LLUUID &id) void LLVivoxVoiceClient::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) { - // For Vivox, we use the legacy name because I'm uncertain whether or - // not their service can tolerate switching to Username or Display Name - std::string legacy_name = av_name.getLegacyName(); - avatarNameResolved(agent_id, legacy_name); + std::string display_name = av_name.mDisplayName; + avatarNameResolved(agent_id, display_name); } void LLVivoxVoiceClient::avatarNameResolved(const LLUUID &id, const std::string &name) -- cgit v1.2.3 From 3792a6aab8d8cf32fa82353fb7be1b895223e41b Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 28 Nov 2012 19:39:27 +0200 Subject: CHUI-546 FIXED Blank IM toast shown when a nearby chat toast is shown: Prosessing of the nearby chat was exluded from on_new_message() --- indra/newview/llimview.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 581043a3d0..e5dda7e8d8 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -171,8 +171,8 @@ void on_new_message(const LLSD& msg) return; } - // Skip toasting for system messages - if (participant_id.isNull()) + // Skip toasting for system messages and for nearby chat + if (participant_id.isNull() || session_id.isNull()) { return; } -- cgit v1.2.3 From 80f8a465eb2885246b0a1daca66077ecd1dcc61d Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 28 Nov 2012 11:35:59 -0800 Subject: CHUI-548: Now a p2p conversation is aligned with the nearby chat arrow. Just had to check for a p2p conversation type and then adjust then decrease the indentation. Also made LLFolderViewItem::drawOpenFolderArrow() a non-virtual function and adjusted code accordingly. --- indra/llui/llfolderviewitem.h | 2 +- indra/newview/llconversationview.cpp | 27 ++++++++++++--------------- indra/newview/llconversationview.h | 3 +-- indra/newview/llfloaterimcontainer.cpp | 6 ++++++ 4 files changed, 20 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index c5d6d26e84..2e633a39e5 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -264,7 +264,7 @@ public: // virtual void handleDropped(); virtual void draw(); - virtual void drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color); + void drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color); void drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor); void drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index e40d57c318..3aadc2986f 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -80,7 +80,8 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes mSessionTitle(NULL), mSpeakingIndicator(NULL), mVoiceClientObserver(NULL), - mMinimizedMode(false) + mMinimizedMode(false), + mHasArrow(true) { mFlashTimer = new LLFlashTimer(); } @@ -135,6 +136,7 @@ BOOL LLConversationViewSession::postBuild() icon->setVisible(true); icon->setValue(session->mOtherParticipantID); mSpeakingIndicator->setSpeakerId(gAgentID, session->mSessionID, true); + mHasArrow = false; } break; } @@ -183,11 +185,10 @@ void LLConversationViewSession::draw() const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); // we don't draw the open folder arrow in minimized mode - if (!mMinimizedMode) + if (mHasArrow && !mMinimizedMode) { // update the rotation angle of open folder arrow updateLabelRotation(); - drawOpenFolderArrow(default_params, sFgColor); } @@ -227,14 +228,18 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) // virtual S32 LLConversationViewSession::arrange(S32* width, S32* height) { - S32 h_pad = getIndentation() + mArrowSize; + //LLFolderViewFolder::arrange computes value for getIndentation() function below + S32 arranged = LLFolderViewFolder::arrange(width, height); + + S32 h_pad = mHasArrow ? getIndentation() + mArrowSize : getIndentation(); + LLRect rect(mMinimizedMode ? getLocalRect().mLeft : h_pad, getLocalRect().mTop, getLocalRect().mRight, getLocalRect().mTop - getItemHeight()); mItemPanel->setShape(rect); - return LLFolderViewFolder::arrange(width, height); + return arranged; } // virtual @@ -262,7 +267,8 @@ void LLConversationViewSession::toggleMinimizedMode(bool is_minimized) // except for the icon which we display in minimized mode getChild<LLView>("conversation_item_stack")->setVisible(!mMinimizedMode); - S32 h_pad = getIndentation() + mArrowSize; + S32 h_pad = mHasArrow ? getIndentation() + mArrowSize : getIndentation(); + mItemPanel->translate(mMinimizedMode ? -h_pad : h_pad, 0); } @@ -340,15 +346,6 @@ void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& sessi } } -void LLConversationViewSession::drawOpenFolderArrow(const LLFolderViewItem::Params& default_params, const LLUIColor& fg_color) -{ - LLConversationItem * itemp = dynamic_cast<LLConversationItem*>(getViewModelItem()); - if (itemp && itemp->getType() != LLConversationItem::CONV_SESSION_1_ON_1) - { - LLFolderViewFolder::drawOpenFolderArrow(default_params, fg_color); - } -} - // // Implementation of conversations list participant (avatar) widgets // diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index acd7128b7d..c6cb502355 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -74,8 +74,6 @@ public: /*virtual*/ bool isMinimized() { return mMinimizedMode; } - /*virtual*/ void drawOpenFolderArrow(const LLFolderViewItem::Params& default_params, const LLUIColor& fg_color); - void toggleMinimizedMode(bool is_minimized); void setVisibleIfDetached(BOOL visible); @@ -98,6 +96,7 @@ private: LLFlashTimer* mFlashTimer; bool mMinimizedMode; + bool mHasArrow; LLVoiceClientStatusObserver* mVoiceClientObserver; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 016a7723b6..5fbbfd1283 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1383,6 +1383,12 @@ LLConversationViewSession* LLFloaterIMContainer::createConversationItemWidget(LL params.tool_tip = params.name; params.container = this; + //Indentation for aligning the p2p converstation image with the nearby chat arrow + if(item->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + { + params.folder_indentation = 3; + } + return LLUICtrlFactory::create<LLConversationViewSession>(params); } -- cgit v1.2.3 From 45e8926f138a2b42c5054149d3a9f6f39df29247 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 28 Nov 2012 13:48:55 -0800 Subject: code cleanup: variables and functions were using the word 'minimized' to refer 'collapsed'. Renamed variables and functions to use the word 'collapsed' instead of 'minimized'. --- indra/newview/llconversationview.cpp | 16 ++++++++-------- indra/newview/llconversationview.h | 6 +++--- indra/newview/llfloaterimcontainer.cpp | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 3aadc2986f..1b1d61e6d6 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -80,7 +80,7 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes mSessionTitle(NULL), mSpeakingIndicator(NULL), mVoiceClientObserver(NULL), - mMinimizedMode(false), + mCollapsedMode(false), mHasArrow(true) { mFlashTimer = new LLFlashTimer(); @@ -185,7 +185,7 @@ void LLConversationViewSession::draw() const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); // we don't draw the open folder arrow in minimized mode - if (mHasArrow && !mMinimizedMode) + if (mHasArrow && !mCollapsedMode) { // update the rotation angle of open folder arrow updateLabelRotation(); @@ -233,7 +233,7 @@ S32 LLConversationViewSession::arrange(S32* width, S32* height) S32 h_pad = mHasArrow ? getIndentation() + mArrowSize : getIndentation(); - LLRect rect(mMinimizedMode ? getLocalRect().mLeft : h_pad, + LLRect rect(mCollapsedMode ? getLocalRect().mLeft : h_pad, getLocalRect().mTop, getLocalRect().mRight, getLocalRect().mTop - getItemHeight()); @@ -246,7 +246,7 @@ S32 LLConversationViewSession::arrange(S32* width, S32* height) void LLConversationViewSession::toggleOpen() { // conversations should not be opened while in minimized mode - if (!mMinimizedMode) + if (!mCollapsedMode) { LLFolderViewFolder::toggleOpen(); @@ -259,17 +259,17 @@ void LLConversationViewSession::toggleOpen() } } -void LLConversationViewSession::toggleMinimizedMode(bool is_minimized) +void LLConversationViewSession::toggleCollapsedMode(bool is_collapsed) { - mMinimizedMode = is_minimized; + mCollapsedMode = is_collapsed; // hide the layout stack which contains all item's child widgets // except for the icon which we display in minimized mode - getChild<LLView>("conversation_item_stack")->setVisible(!mMinimizedMode); + getChild<LLView>("conversation_item_stack")->setVisible(!mCollapsedMode); S32 h_pad = mHasArrow ? getIndentation() + mArrowSize : getIndentation(); - mItemPanel->translate(mMinimizedMode ? -h_pad : h_pad, 0); + mItemPanel->translate(mCollapsedMode ? -h_pad : h_pad, 0); } void LLConversationViewSession::setVisibleIfDetached(BOOL visible) diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index c6cb502355..a6f408403b 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -72,9 +72,9 @@ public: /*virtual*/ void toggleOpen(); - /*virtual*/ bool isMinimized() { return mMinimizedMode; } + /*virtual*/ bool isCollapsed() { return mCollapsedMode; } - void toggleMinimizedMode(bool is_minimized); + void toggleCollapsedMode(bool is_collapsed); void setVisibleIfDetached(BOOL visible); LLConversationViewParticipant* findParticipant(const LLUUID& participant_id); @@ -95,7 +95,7 @@ private: LLOutputMonitorCtrl* mSpeakingIndicator; LLFlashTimer* mFlashTimer; - bool mMinimizedMode; + bool mCollapsedMode; bool mHasArrow; LLVoiceClientStatusObserver* mVoiceClientObserver; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 5fbbfd1283..a04b8d79d6 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -640,7 +640,7 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); if (widget) { - widget->toggleMinimizedMode(collapse); + widget->toggleCollapsedMode(collapse); // force closing all open conversations when collapsing to minimized state if (collapse) @@ -1320,7 +1320,7 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& } // set the widget to minimized mode if conversations pane is collapsed - widget->toggleMinimizedMode(mConversationsPane->isCollapsed()); + widget->toggleCollapsedMode(mConversationsPane->isCollapsed()); if (isWidgetSelected) { -- cgit v1.2.3 From c8fceb426da13b2a5a47ee8d7b319ff3b15a1bb8 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 28 Nov 2012 14:51:39 -0800 Subject: CHUI-552 : Big clean up in nearby chat making it more consistent with LLFloaterIMSessionTab --- indra/newview/llfloaterimnearbychat.cpp | 71 +-------------------------------- indra/newview/llfloaterimnearbychat.h | 9 ----- 2 files changed, 2 insertions(+), 78 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 7002342c0b..7b97295703 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -95,7 +95,6 @@ LLFloaterIMNearbyChat::LLFloaterIMNearbyChat(const LLSD& llsd) { mIsP2PChat = false; mIsNearbyChat = true; - setIsChrome(TRUE); mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); mSessionID = LLUUID(); } @@ -119,29 +118,10 @@ BOOL LLFloaterIMNearbyChat::postBuild() mInputEditor->setFocusReceivedCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxFocusReceived, this)); mInputEditor->setLabel(LLTrans::getString("NearbyChatTitle")); -// mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); -// mOutputMonitor->setVisible(FALSE); - - // Register for font change notifications -// LLViewerChat::setFontChangedCallback(boost::bind(&LLFloaterIMNearbyChat::onChatFontChange, this, _1)); - - // title must be defined BEFORE call addConversationListItem() because - // it is used for show the item's name in the conversations list + // Title must be defined BEFORE call to addConversationListItem() because + // it is used to show the item's name in the conversations list setTitle(LLTrans::getString("NearbyChatTitle")); - //for menu -// LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; -// LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - -// enable_registrar.add("NearbyChat.Check", boost::bind(&LLFloaterIMNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); -// registrar.add("NearbyChat.Action", boost::bind(&LLFloaterIMNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); - -// LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -// if(menu) -// { -// mPopupMenuHandle = menu->getHandle(); -// } - // obsolete, but may be needed for backward compatibility? gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); @@ -168,43 +148,6 @@ void LLFloaterIMNearbyChat::refresh() } } -void LLFloaterIMNearbyChat::onNearbySpeakers() -{ - LLSD param; - param["people_panel_tab_name"] = "nearby_panel"; - LLFloaterSidePanelContainer::showPanel("people", "panel_people", param); -} - -void LLFloaterIMNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata) -{ -} - -bool LLFloaterIMNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata) -{ - std::string str = userdata.asString(); - if(str == "nearby_people") - onNearbySpeakers(); - return false; -} - - -BOOL LLFloaterIMNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask) -{ - //fix for EXT-6625 - //highlight NearbyChat history whenever mouseclick happen in NearbyChat - //setting focus to eidtor will force onFocusLost() call that in its turn will change - //background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. - - if(mChatHistory) - { - mChatHistory->setFocus(TRUE); - } - - BOOL handled = LLPanel::handleMouseDown(x, y, mask); - setFocus(handled); - return handled; -} - void LLFloaterIMNearbyChat::reloadMessages() { mChatHistory->clear(); @@ -641,16 +584,6 @@ void LLFloaterIMNearbyChat::displaySpeakingIndicator() break; } } - - if (!id.isNull()) - { - //mOutputMonitor->setVisible(TRUE); - //mOutputMonitor->setSpeakerId(id); - } - else - { - //mOutputMonitor->setVisible(FALSE); - } } void LLFloaterIMNearbyChat::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index 5ed639136b..a38824dc78 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -59,21 +59,17 @@ public: void reloadMessages(); void removeScreenChat(); - void addToHost(); void show(); bool isChatVisible() const; /** @param archive true - to save a message to the chat history log */ void addMessage (const LLChat& message,bool archive = true, const LLSD &args = LLSD()); - void onNearbyChatContextMenuItemClicked(const LLSD& userdata); - bool onNearbyChatCheckContextMenuItem(const LLSD& userdata); LLChatEntry* getChatBox() { return mInputEditor; } std::string getCurrentChat(); virtual BOOL handleKeyHere( KEY key, MASK mask ); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); static void startChat(const char* line); static void stopChat(); @@ -112,14 +108,9 @@ protected: S32 mExpandedHeight; private: - - void onNearbySpeakers (); - /*virtual*/ void refresh(); -// LLHandle<LLView> mPopupMenuHandle; std::vector<LLChat> mMessageArchive; - }; #endif // LL_LLFLOATERIMNEARBYCHAT_H -- cgit v1.2.3 From 15157ecb095838f402edb750b87ea0bdb9fb56f7 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Thu, 29 Nov 2012 03:27:45 +0200 Subject: CHUI-553 FIXED Remove the conversation chiclet --- indra/newview/llchiclet.cpp | 98 --------------------- indra/newview/llchiclet.h | 48 ---------- indra/newview/llchicletbar.cpp | 1 - indra/newview/llsyswellwindow.cpp | 38 +++----- .../default/textures/bottomtray/Unread_IM.png | Bin 458 -> 0 bytes indra/newview/skins/default/textures/textures.xml | 1 - .../skins/default/xui/en/menu_im_well_button.xml | 16 ---- .../skins/default/xui/en/panel_chiclet_bar.xml | 48 ---------- 8 files changed, 12 insertions(+), 238 deletions(-) delete mode 100644 indra/newview/skins/default/textures/bottomtray/Unread_IM.png delete mode 100644 indra/newview/skins/default/xui/en/menu_im_well_button.xml (limited to 'indra') diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index d6860640b7..a665aeb6bd 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -52,7 +52,6 @@ #include "llsyswellwindow.h" static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel"); -static LLDefaultChildRegistry::Register<LLIMWellChiclet> t2_0("chiclet_im_well"); static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification"); static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t3("chiclet_im_p2p"); static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t4("chiclet_im_group"); @@ -176,103 +175,6 @@ BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) return TRUE; } -/************************************************************************/ -/* LLIMWellChiclet implementation */ -/************************************************************************/ -LLIMWellChiclet::LLIMWellChiclet(const Params& p) -: LLSysWellChiclet(p) -{ - LLIMModel::instance().addNewMsgCallback(boost::bind(&LLIMWellChiclet::messageCountChanged, this, _1)); - LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(&LLIMWellChiclet::messageCountChanged, this, _1)); - - LLIMMgr::getInstance()->addSessionObserver(this); - - LLIMWellWindow::getInstance()->setSysWellChiclet(this); -} - -LLIMWellChiclet::~LLIMWellChiclet() -{ - LLIMWellWindow* im_well_window = LLIMWellWindow::findInstance(); - if (im_well_window) - { - im_well_window->setSysWellChiclet(NULL); - } - - LLIMMgr::getInstance()->removeSessionObserver(this); -} - -void LLIMWellChiclet::onMenuItemClicked(const LLSD& user_data) -{ - std::string action = user_data.asString(); - if("close all" == action) - { - LLIMWellWindow::getInstance()->closeAll(); - } -} - -bool LLIMWellChiclet::enableMenuItem(const LLSD& user_data) -{ - std::string item = user_data.asString(); - if (item == "can close all") - { - return !LLIMWellWindow::getInstance()->isWindowEmpty(); - } - return true; -} - -void LLIMWellChiclet::createMenu() -{ - if(mContextMenu) - { - llwarns << "Menu already exists" << llendl; - return; - } - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("IMWellChicletMenu.Action", - boost::bind(&LLIMWellChiclet::onMenuItemClicked, this, _2)); - - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - enable_registrar.add("IMWellChicletMenu.EnableItem", - boost::bind(&LLIMWellChiclet::enableMenuItem, this, _2)); - - mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu> - ("menu_im_well_button.xml", - LLMenuGL::sMenuContainer, - LLViewerMenuHolderGL::child_registry_t::instance()); -} - -void LLIMWellChiclet::messageCountChanged(const LLSD& session_data) -{ - // The singleton class LLChicletBar instance might be already deleted - // so don't create a new one. - if (!LLChicletBar::instanceExists()) - { - return; - } - - const LLUUID& session_id = session_data["session_id"]; - const S32 counter = LLChicletBar::getInstance()->getTotalUnreadIMCount(); - const bool im_not_visible = !LLFloaterReg::instanceVisible("im_container") - && !LLFloaterReg::instanceVisible("impanel", session_id); - - setNewMessagesState(counter > mCounter && im_not_visible); - - // we have to flash to 'Lit' state each time new unread message is coming. - if (counter > mCounter && im_not_visible) - { - mFlashToLitTimer->startFlashing(); - } - else if (counter == 0) - { - // if notification is resolved while well is flashing it can leave in the 'Lit' state - // when flashing finishes itself. Let break flashing here. - mFlashToLitTimer->stopFlashing(); - } - - setCounter(counter); -} - /************************************************************************/ /* LLNotificationChiclet implementation */ /************************************************************************/ diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 79ffad92ef..7f72c7f9e2 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -865,54 +865,6 @@ protected: LLContextMenu* mContextMenu; }; -/** - * Class represented a chiclet for IM Well Icon. - * - * It displays a count of unread messages from other participants in all IM sessions. - */ -class LLIMWellChiclet : public LLSysWellChiclet, LLIMSessionObserver -{ - friend class LLUICtrlFactory; -public: - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) {} - /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} - /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; - /*virtual*/ void sessionRemoved(const LLUUID& session_id) { messageCountChanged(LLSD()); } - /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {} - - ~LLIMWellChiclet(); -protected: - LLIMWellChiclet(const Params& p); - - /** - * Processes clicks on chiclet popup menu. - */ - virtual void onMenuItemClicked(const LLSD& user_data); - - /** - * Enables chiclet menu items. - */ - bool enableMenuItem(const LLSD& user_data); - - /** - * Creates menu. - */ - /*virtual*/ void createMenu(); - - /** - * Handles changes in a session (message was added, messages were read, etc.) - * - * It get total count of unread messages from a LLIMMgr in all opened sessions and display it. - * - * @param[in] session_data contains session related data, is not used now - * ["session_id"] - id of an appropriate session - * ["participant_unread"] - count of unread messages from "real" participants. - * - * @see LLIMMgr::getNumberOfUnreadParticipantMessages() - */ - void messageCountChanged(const LLSD& session_data); -}; - class LLNotificationChiclet : public LLSysWellChiclet { LOG_CLASS(LLNotificationChiclet); diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index c66ae1cdd0..cfcde64e7b 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -158,7 +158,6 @@ BOOL LLChicletBar::postBuild() mToolbarStack = getChild<LLLayoutStack>("toolbar_stack"); mChicletPanel = getChild<LLChicletPanel>("chiclet_list"); - showWellButton("im_well", !LLIMWellWindow::getInstance()->isWindowEmpty()); showWellButton("notification_well", !LLNotificationWellWindow::getInstance()->isWindowEmpty()); LLPanelTopInfoBar::instance().setResizeCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this)); diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 7c000f2dd0..3605129d48 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -98,8 +98,10 @@ void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask) void LLSysWellWindow::setSysWellChiclet(LLSysWellChiclet* chiclet) { mSysWellChiclet = chiclet; - if(mSysWellChiclet) - mSysWellChiclet->updateWidget(isWindowEmpty()); + if(NULL != mSysWellChiclet) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + } } //--------------------------------------------------------------------------------- LLSysWellWindow::~LLSysWellWindow() @@ -111,7 +113,10 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id) { if(mMessageList->removeItemByValue(id)) { - mSysWellChiclet->updateWidget(isWindowEmpty()); + if (NULL != mSysWellChiclet) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + } reshapeWindow(); } else @@ -685,11 +690,7 @@ void LLIMWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) { RowPanel* item = new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId); - if (mMessageList->addItem(item, sessionId)) - { - mSysWellChiclet->updateWidget(isWindowEmpty()); - } - else + if (!mMessageList->addItem(item, sessionId)) { llwarns << "Unable to add IM Row into the list, sessionID: " << sessionId << ", name: " << name @@ -710,11 +711,7 @@ void LLIMWellWindow::delIMRow(const LLUUID& sessionId) //But I didn't find why this happen.. gFocusMgr.clearLastFocusForGroup(this); - if (mMessageList->removeItemByValue(sessionId)) - { - mSysWellChiclet->updateWidget(isWindowEmpty()); - } - else + if (!mMessageList->removeItemByValue(sessionId)) { llwarns << "Unable to remove IM Row from the list, sessionID: " << sessionId << llendl; @@ -740,11 +737,7 @@ void LLIMWellWindow::addObjectRow(const LLUUID& notification_id, bool new_messag if (mMessageList->getItemByValue(notification_id) == NULL) { ObjectRowPanel* item = new ObjectRowPanel(notification_id, new_message); - if (mMessageList->addItem(item, notification_id)) - { - mSysWellChiclet->updateWidget(isWindowEmpty()); - } - else + if (!mMessageList->addItem(item, notification_id)) { llwarns << "Unable to add Object Row into the list, notificationID: " << notification_id << llendl; item->die(); @@ -755,14 +748,7 @@ void LLIMWellWindow::addObjectRow(const LLUUID& notification_id, bool new_messag void LLIMWellWindow::removeObjectRow(const LLUUID& notification_id) { - if (mMessageList->removeItemByValue(notification_id)) - { - if (mSysWellChiclet) - { - mSysWellChiclet->updateWidget(isWindowEmpty()); - } - } - else + if (!mMessageList->removeItemByValue(notification_id)) { llwarns << "Unable to remove Object Row from the list, notificationID: " << notification_id << llendl; } diff --git a/indra/newview/skins/default/textures/bottomtray/Unread_IM.png b/indra/newview/skins/default/textures/bottomtray/Unread_IM.png deleted file mode 100644 index 5c0c85b864..0000000000 Binary files a/indra/newview/skins/default/textures/bottomtray/Unread_IM.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index a124041565..8d9fa52309 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -642,7 +642,6 @@ with the same filename but different name <texture name="TrashItem_Press" file_name="icons/TrashItem_Press.png" preload="false" /> <texture name="Unread_Chiclet" file_name="bottomtray/Unread_Chiclet.png" preload="false" /> - <texture name="Unread_IM" file_name="bottomtray/Unread_IM.png" preload="false" /> <texture name="UpArrow_Off" file_name="icons/UpArrow_Off.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/en/menu_im_well_button.xml b/indra/newview/skins/default/xui/en/menu_im_well_button.xml deleted file mode 100644 index f8dfba91ff..0000000000 --- a/indra/newview/skins/default/xui/en/menu_im_well_button.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<context_menu - layout="topleft" - name="IM Well Button Context Menu"> - <menu_item_call - label="Close All" - layout="topleft" - name="Close All"> - <menu_item_call.on_click - function="IMWellChicletMenu.Action" - parameter="close all" /> - <menu_item_call.on_enable - function="IMWellChicletMenu.EnableItem" - parameter="can close all" /> - </menu_item_call> -</context_menu> diff --git a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml index ff0146490b..fc321fdd23 100644 --- a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml @@ -80,54 +80,6 @@ <layout_panel auto_resize="false" width="4" min_width="4"/> - <layout_panel - auto_resize="false" - follows="right" - height="28" - layout="topleft" - min_height="28" - min_width="37" - name="im_well_panel" - top="0" - width="37"> - <chiclet_im_well - follows="right" - height="28" - layout="topleft" - left="0" - max_displayed_count="99" - name="im_well" - top="0" - width="35"> - <!-- -Emulate 4 states of button by background images, see details in EXT-3147. The same should be for notification_well button -xml attribute Description -image_unselected "Unlit" - there are no new messages -image_selected "Unlit" + "Selected" - there are no new messages and the Well is open -image_pressed "Lit" - there are new messages -image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open - --> - <button - auto_resize="false" - follows="right" - halign="center" - height="23" - image_overlay="Unread_IM" - image_overlay_alignment="center" - image_pressed="WellButton_Lit" - image_pressed_selected="WellButton_Lit_Selected" - image_selected="PushButton_Press" - label_color="Black" - left="0" - name="Unread IM messages" - tool_tip="Conversations" - width="34"> - <init_callback - function="Button.SetDockableFloaterToggle" - parameter="im_well_window" /> - </button> - </chiclet_im_well> - </layout_panel> <layout_panel auto_resize="false" follows="right" -- cgit v1.2.3 From 4da50b21d5dc49cf6b39f7c29b44c1bb869a13cd Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 28 Nov 2012 19:40:06 -0800 Subject: CHUI-552 : Fixed : Do not update the avatars sorting when updating the speaking indicator, let the conversation list do that. --- indra/newview/llfloaterimnearbychat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 7b97295703..a20fce876c 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -572,7 +572,7 @@ void LLFloaterIMNearbyChat::displaySpeakingIndicator() LLUUID id; id.setNull(); - mSpeakerMgr->update(TRUE); + mSpeakerMgr->update(FALSE); mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) -- cgit v1.2.3 From 611797543a917f1596be73e9e79974578748086e Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 29 Nov 2012 15:03:35 -0800 Subject: CHUI-489: Removed the 'Group Messages' checkbox. This was a design change in the spec. --- indra/newview/app_settings/settings.xml | 11 ----------- indra/newview/skins/default/xui/en/panel_preferences_chat.xml | 11 +---------- 2 files changed, 1 insertion(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 253ac3b836..ece711a128 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6867,17 +6867,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>PlaySoundGroupChatMessages</key> - <map> - <key>Comment</key> - <string>Plays a sound when have a group chat message.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>PlaySoundIncomingVoiceCall</key> <map> <key>Comment</key> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 0c94b6b223..37bfbae991 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -341,22 +341,13 @@ top_pad="6" name="incoming_voice_call" width="150" /> - <check_box - enabled="false" - control_name="PlaySoundGroupChatMessages" - height="16" - label="Group chat messages" - layout="topleft" - top_pad="6" - name="group_chat_messages" - width="150" /> <check_box control_name="PlaySoundTeleportOffer" height="16" label="Teleport offer" layout="topleft" left_pad="35" - top_pad="-59" + top_pad="-38" name="teleport_offer" width="150" /> <check_box -- cgit v1.2.3 From 5238a39b5458a34b727ca842c456db47ef13d1b7 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 29 Nov 2012 20:33:17 -0800 Subject: CHUI-552 : Fixed : Filter out participant creation with the same id than the session id --- indra/newview/llparticipantlist.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 9f89b5f809..6c838f8a45 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -366,8 +366,11 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) { - // Do not add if already in there or excluded for some reason - if (findParticipant(avatar_id)) return; + // Do not add if already in there, is the session id (hence not an avatar) or excluded for some reason + if (findParticipant(avatar_id) || (avatar_id == mUUID)) + { + return; + } bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(avatar_id); @@ -391,7 +394,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) // *TODO : Need to update the online/offline status of the participant // Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id)) - + // Add the participant model to the session's children list addParticipant(participant); @@ -413,12 +416,12 @@ void LLParticipantList::adjustParticipant(const LLUUID& speaker_id) bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) { /** - * We need to filter speaking objects. These objects shouldn't appear in the list + * We need to filter speaking objects. These objects shouldn't appear in the list. * @see LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy */ const LLUUID& speaker_id = event->getValue().asUUID(); LLPointer<LLSpeaker> speaker = mParent.mSpeakerMgr->findSpeaker(speaker_id); - if(speaker.isNull() || speaker->mType == LLSpeaker::SPEAKER_OBJECT) + if (speaker.isNull() || (speaker->mType == LLSpeaker::SPEAKER_OBJECT)) { return false; } -- cgit v1.2.3 From 47a1a0468156153155f5e9b6c720b9b6cb62c263 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 30 Nov 2012 14:12:46 -0800 Subject: CHUI-570 : Fixed : Take the typing state when updating the title, also make refresh update less frequent (perf). --- indra/newview/llfloaterimsession.cpp | 26 +++++++++++--------------- indra/newview/llfloaterimsession.h | 1 - indra/newview/llfloaterimsessiontab.cpp | 2 +- 3 files changed, 12 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index e1dc5b91d0..0162b0ecd0 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -66,7 +66,6 @@ LLFloaterIMSession::LLFloaterIMSession(const LLUUID& session_id) : LLFloaterIMSessionTab(session_id), mLastMessageIndex(-1), mDialog(IM_NOTHING_SPECIAL), - mSavedTitle(), mTypingStart(), mShouldSendTypingState(false), mMeTyping(false), @@ -504,9 +503,13 @@ void LLFloaterIMSession::onVoiceChannelStateChanged( void LLFloaterIMSession::updateSessionName(const std::string& name) { - LLFloaterIMSessionTab::updateSessionName(name); - setTitle(name); - mTypingStart.setArg("[NAME]", name); + if (!name.empty()) + { + LLFloaterIMSessionTab::updateSessionName(name); + mTypingStart.setArg("[NAME]", name); + setTitle (mOtherTyping ? mTypingStart.getString() : name); + } + llinfos << "Merov debug : updateSessionName, title = " << name << ", typing title = " << mTypingStart.getString() << llendl; } //static @@ -1095,14 +1098,10 @@ BOOL LLFloaterIMSession::inviteToSession(const uuid_vec_t& ids) void LLFloaterIMSession::addTypingIndicator(const LLIMInfo* im_info) { // We may have lost a "stop-typing" packet, don't add it twice - if ( im_info && !mOtherTyping ) + if (im_info && !mOtherTyping) { mOtherTyping = true; - // Save and set new title - mSavedTitle = getTitle(); - setTitle (mTypingStart); - // Update speaker LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); if ( speaker_mgr ) @@ -1114,18 +1113,15 @@ void LLFloaterIMSession::addTypingIndicator(const LLIMInfo* im_info) void LLFloaterIMSession::removeTypingIndicator(const LLIMInfo* im_info) { - if ( mOtherTyping ) + if (mOtherTyping) { mOtherTyping = false; - // Revert the title to saved one - setTitle(mSavedTitle); - - if ( im_info ) + if (im_info) { // Update speaker LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if ( speaker_mgr ) + if (speaker_mgr) { speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE); } diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index f4ec2d457d..72a320041f 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -174,7 +174,6 @@ private: LLUUID mOtherParticipantUUID; bool mPositioned; - std::string mSavedTitle; LLUIString mTypingStart; bool mMeTyping; bool mOtherTyping; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 6e58a66bcd..d43381041b 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -43,7 +43,7 @@ #include "lltoolbarview.h" #include "llfloaterimnearbychat.h" -const F32 REFRESH_INTERVAL = 0.2f; +const F32 REFRESH_INTERVAL = 1.0f; LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) : LLTransientDockableFloater(NULL, true, session_id) -- cgit v1.2.3 From eab0ec402e7ea1eb151408b913c6f4e14c9c8cbe Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 30 Nov 2012 14:34:23 -0800 Subject: CHUI-570 : Delete a stray debug comment log. --- indra/newview/llfloaterimsession.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 0162b0ecd0..212b0df712 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -509,7 +509,6 @@ void LLFloaterIMSession::updateSessionName(const std::string& name) mTypingStart.setArg("[NAME]", name); setTitle (mOtherTyping ? mTypingStart.getString() : name); } - llinfos << "Merov debug : updateSessionName, title = " << name << ", typing title = " << mTypingStart.getString() << llendl; } //static -- cgit v1.2.3 From e53577c32db1a8d5e7e15cb33357c68da87acc44 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 30 Nov 2012 17:12:52 -0800 Subject: CHUI-404, CHUI-406 : Fixed : update ad-hoc conversation when participant logs off, update title of ad-hoc and P2P to be consistent with torn off and input field --- indra/newview/llconversationmodel.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 0837a49095..ba92022673 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" +#include "llagent.h" #include "llavatarnamecache.h" #include "llavataractions.h" #include "llevents.h" @@ -161,8 +162,8 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa void LLConversationItemSession::updateParticipantName(LLConversationItemParticipant* participant) { - // We modify the session name only in the case of an ad-hoc session, exit otherwise (nothing to do) - if (getType() != CONV_SESSION_AD_HOC) + // We modify the session name only in the case of an ad-hoc session or P2P session, exit otherwise (nothing to do) + if ((getType() != CONV_SESSION_AD_HOC) && (getType() != CONV_SESSION_1_ON_1)) { return; } @@ -171,26 +172,26 @@ void LLConversationItemSession::updateParticipantName(LLConversationItemParticip { return; } - // Build a string containing the participants names and check if ready for display (we don't want "(waiting)" in there) - bool all_names_resolved = true; + // Build a string containing the participants names (minus own agent) and check if ready for display (we don't want "(waiting)" in there) + // Note: we don't bind ourselves to the LLAvatarNameCache event as updateParticipantName() is called by + // onAvatarNameCache() which is itself attached to the same event. uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string child_list_t::iterator iter = mChildren.begin(); while (iter != mChildren.end()) { LLConversationItemParticipant* current_participant = dynamic_cast<LLConversationItemParticipant*>(*iter); - temp_uuids.push_back(current_participant->getUUID()); - LLAvatarName av_name; - if (!LLAvatarNameCache::get(current_participant->getUUID(), &av_name)) - { - // If the name is not in the cache yet, bail out - // Note: we don't bind ourselves to the LLAvatarNameCache event as we are called by - // onAvatarNameCache() which is itself attached to the same event. - all_names_resolved = false; - break; + // Add the avatar uuid to the list (except if it's the own agent uuid) + if (current_participant->getUUID() != gAgentID) + { + LLAvatarName av_name; + if (LLAvatarNameCache::get(current_participant->getUUID(), &av_name)) + { + temp_uuids.push_back(current_participant->getUUID()); + } } iter++; } - if (all_names_resolved) + if (temp_uuids.size() != 0) { std::string new_session_name; LLAvatarActions::buildResidentsString(temp_uuids, new_session_name); @@ -203,6 +204,7 @@ void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* { removeChild(participant); mNeedsRefresh = true; + updateParticipantName(participant); postEvent("remove_participant", this, participant); } -- cgit v1.2.3 From d48357f54765f84a35b73bbf28e88b978bcb5013 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 30 Nov 2012 19:07:58 -0800 Subject: CHUI-406 : Fixed again : Update of the P2P session name when not initiating a session was wrong. Add getting the participant name from the session. --- indra/newview/llconversationmodel.cpp | 39 +++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index ba92022673..728b1a3f4c 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -31,6 +31,7 @@ #include "llavatarnamecache.h" #include "llavataractions.h" #include "llevents.h" +#include "llfloaterimsession.h" #include "llsdutil.h" #include "llconversationmodel.h" #include "llimview.h" //For LLIMModel @@ -162,8 +163,9 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa void LLConversationItemSession::updateParticipantName(LLConversationItemParticipant* participant) { + EConversationType conversation_type = getType(); // We modify the session name only in the case of an ad-hoc session or P2P session, exit otherwise (nothing to do) - if ((getType() != CONV_SESSION_AD_HOC) && (getType() != CONV_SESSION_1_ON_1)) + if ((conversation_type != CONV_SESSION_AD_HOC) && (conversation_type != CONV_SESSION_1_ON_1)) { return; } @@ -172,24 +174,35 @@ void LLConversationItemSession::updateParticipantName(LLConversationItemParticip { return; } - // Build a string containing the participants names (minus own agent) and check if ready for display (we don't want "(waiting)" in there) - // Note: we don't bind ourselves to the LLAvatarNameCache event as updateParticipantName() is called by - // onAvatarNameCache() which is itself attached to the same event. uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string - child_list_t::iterator iter = mChildren.begin(); - while (iter != mChildren.end()) + if (conversation_type == CONV_SESSION_AD_HOC) { - LLConversationItemParticipant* current_participant = dynamic_cast<LLConversationItemParticipant*>(*iter); - // Add the avatar uuid to the list (except if it's the own agent uuid) - if (current_participant->getUUID() != gAgentID) + // Build a string containing the participants UUIDs (minus own agent) and check if ready for display (we don't want "(waiting)" in there) + // Note: we don't bind ourselves to the LLAvatarNameCache event as updateParticipantName() is called by + // onAvatarNameCache() which is itself attached to the same event. + child_list_t::iterator iter = mChildren.begin(); + while (iter != mChildren.end()) { - LLAvatarName av_name; - if (LLAvatarNameCache::get(current_participant->getUUID(), &av_name)) + LLConversationItemParticipant* current_participant = dynamic_cast<LLConversationItemParticipant*>(*iter); + // Add the avatar uuid to the list (except if it's the own agent uuid) + if (current_participant->getUUID() != gAgentID) { - temp_uuids.push_back(current_participant->getUUID()); + LLAvatarName av_name; + if (LLAvatarNameCache::get(current_participant->getUUID(), &av_name)) + { + temp_uuids.push_back(current_participant->getUUID()); + } } + iter++; } - iter++; + } + else if (conversation_type == CONV_SESSION_1_ON_1) + { + // In the case of a P2P conversersation, we need to grab the name of the other participant in the session instance itself + // as we do not create participants for such a session. + LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(mUUID); + LLUUID participantID = conversationFloater->getOtherParticipantUUID(); + temp_uuids.push_back(participantID); } if (temp_uuids.size() != 0) { -- cgit v1.2.3 From 168c1d5a85e8f4f4975ee4501e3dbb8f10d85334 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Mon, 3 Dec 2012 15:37:11 +0200 Subject: CHUI-432 (User that is muted in group call does not show as muted to other users in conversation list) --- indra/newview/llconversationview.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 1b1d61e6d6..7988cd1a03 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -448,6 +448,7 @@ void LLConversationViewParticipant::draw() drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); drawLabel(font, text_left, y, color, right_x); + refresh(); LLView::draw(); } -- cgit v1.2.3 From f888a3fd00ca32275ab2da6437cb011b3ab78f89 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Mon, 3 Dec 2012 16:21:48 +0200 Subject: CHUI-556 (Tooltip on call button incorrect when call is active) --- indra/newview/llfloaterimsessiontab.cpp | 7 ++++++- indra/newview/skins/default/xui/en/floater_im_session.xml | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index d43381041b..08c2b951df 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -691,8 +691,13 @@ void LLFloaterIMSessionTab::processChatHistoryStyleUpdate() void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive) { - getChild<LLButton>("voice_call_btn")->setImageOverlay( + LLButton* voiceButton = getChild<LLButton>("voice_call_btn"); + voiceButton->setImageOverlay( callIsActive? getString("call_btn_stop") : getString("call_btn_start")); + + voiceButton->setToolTip( + callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip")); + enableDisableCallBtn(); } diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 1d74f1bc25..faf54774f6 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -43,6 +43,12 @@ <floater.string name="tooltip_to_main_window" value="Move this conversation back to main window"/> + <floater.string + name="start_call_button_tooltip" + value="Open voice connection"/> + <floater.string + name="end_call_button_tooltip" + value="Close voice connection"/> <view follows="all" layout="topleft" -- cgit v1.2.3 From 1ce49f764fa00406088f7bcd7623603baedd5fe8 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 3 Dec 2012 19:20:11 +0200 Subject: CHUI-532 FIXED (Viewer crash when user in conversation is removed from participant list because they logged out or teleported away) delayed destroy of the timer --- indra/llui/llbutton.cpp | 2 +- indra/llui/llflashtimer.cpp | 9 ++++++++- indra/llui/llflashtimer.h | 6 ++++++ indra/newview/llconversationview.cpp | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 97547208ec..f82cdc64a9 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -286,7 +286,7 @@ LLButton::~LLButton() if (mFlashingTimer) { - delete mFlashingTimer; + mFlashingTimer->unset(); } } diff --git a/indra/llui/llflashtimer.cpp b/indra/llui/llflashtimer.cpp index de7a4ab265..e49628acd5 100644 --- a/indra/llui/llflashtimer.cpp +++ b/indra/llui/llflashtimer.cpp @@ -35,6 +35,7 @@ LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) , mCurrentTickCount(0) , mIsFlashingInProgress(false) , mIsCurrentlyHighlighted(false) + , mUnset(false) { mEventTimer.stop(); @@ -48,6 +49,12 @@ LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) } } +void LLFlashTimer::unset() +{ + mUnset = true; + mCallback = NULL; +} + BOOL LLFlashTimer::tick() { mIsCurrentlyHighlighted = !mIsCurrentlyHighlighted; @@ -62,7 +69,7 @@ BOOL LLFlashTimer::tick() stopFlashing(); } - return FALSE; + return mUnset; } void LLFlashTimer::startFlashing() diff --git a/indra/llui/llflashtimer.h b/indra/llui/llflashtimer.h index 5c8860b097..c60f99a8ea 100644 --- a/indra/llui/llflashtimer.h +++ b/indra/llui/llflashtimer.h @@ -52,6 +52,11 @@ public: bool isFlashingInProgress(); bool isCurrentlyHighlighted(); + /* + * Use this instead of deleting this object. + * The next call to tick() will return true and that will destroy this object. + */ + void unset(); private: callback_t mCallback; @@ -62,6 +67,7 @@ private: S32 mCurrentTickCount; bool mIsCurrentlyHighlighted; bool mIsFlashingInProgress; + bool mUnset; }; #endif /* LL_FLASHTIMER_H */ diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 1b1d61e6d6..40900dce54 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -95,7 +95,7 @@ LLConversationViewSession::~LLConversationViewSession() LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); } - delete mFlashTimer; + mFlashTimer->unset(); } bool LLConversationViewSession::isHighlightAllowed() -- cgit v1.2.3 From 2ee6bcab371a08791bccad3a4fa072c1d60cd6c9 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 3 Dec 2012 16:19:46 -0800 Subject: CHUI-571: Now when the 'Chat Preference' is set to 'Open Conversations window' the conversation line item with flash. The only time it does not flash is when the the conversation line item is already focused. Also fixed various focusing bugs when navigating between conversations and participants. --- indra/llui/llfolderviewitem.cpp | 7 ++++++- indra/newview/llconversationview.cpp | 18 ++++++++++++++---- indra/newview/llfloaterimcontainer.cpp | 26 +++++++++++++++++--------- indra/newview/llfloaterimnearbychathandler.cpp | 5 ----- indra/newview/llfloaterimsessiontab.cpp | 2 +- indra/newview/llimview.cpp | 6 ++++++ 6 files changed, 44 insertions(+), 20 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 261f53d6b6..9b54a7a467 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -501,7 +501,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) // No handler needed for focus lost since this class has no // state that depends on it. gFocusMgr.setMouseCapture( this ); - + if (!mIsSelected) { if(mask & MASK_CONTROL) @@ -518,6 +518,11 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) } make_ui_sound("UISndClick"); } + //Just re-select the item since it is clicked without ctrl or shift + else if(!(mask & (MASK_CONTROL | MASK_SHIFT))) + { + getRoot()->setSelection(this, FALSE); + } else { mSelectPending = TRUE; diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 1b1d61e6d6..a696fbdb47 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -218,9 +218,15 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) { LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem()); LLUUID session_id = item? item->getUUID() : LLUUID(); + //Will try to select a child node and then itself (if a child was not selected) BOOL result = LLFolderViewFolder::handleMouseDown(x, y, mask); - (LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"))-> - selectConversationPair(session_id, false); + + //This node (conversation) was selected and a child (participant) was not + if(result && getRoot()->getCurSelectedItem() == this) + { + (LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"))-> + selectConversationPair(session_id, false); + } return result; } @@ -548,8 +554,12 @@ BOOL LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask ) } LLUUID session_id = item? item->getUUID() : LLUUID(); BOOL result = LLFolderViewItem::handleMouseDown(x, y, mask); - (LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"))-> - selectConversationPair(session_id, false); + + if(result) + { + (LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"))-> + selectConversationPair(session_id, false); + } return result; } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a04b8d79d6..3a80491dae 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1165,21 +1165,16 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id) selectConversation(session_id); } -// Will select only the conversation item void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) { - LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); - if (widget) - { - (widget->getRoot())->setSelection(widget, FALSE, FALSE); + selectConversationPair(session_id, true); } -} - // Synchronous select the conversation item and the conversation floater BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget) { BOOL handled = TRUE; + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); /* widget processing */ if (select_widget) @@ -1198,7 +1193,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool // Store the active session setSelectedSession(session_id); - LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); + if (session_floater->getHost()) { @@ -1207,13 +1202,13 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool // Switch to the conversation floater that is being selected selectFloater(session_floater); } + } // Set the focus on the selected floater if (!session_floater->hasFocus()) { session_floater->setFocus(TRUE); } - } return handled; } @@ -1627,13 +1622,26 @@ void LLFloaterIMContainer::reSelectConversation() void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes) { + //Finds the conversation line item to flash using the session_id LLConversationViewSession * widget = dynamic_cast<LLConversationViewSession *>(get_ptr_in_map(mConversationsWidgets,session_id)); + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); + if (widget) { + //Start flash if (is_flashes) { + //Only flash when conversation is not active + if(session_floater + && (!session_floater->isInVisibleChain()) //conversation floater not displayed + || + (session_floater->isInVisibleChain() && session_floater->hasFocus() == false)) //conversation floater is displayed but doesn't have focus + + { widget->getFlashTimer()->startFlashing(); } + } + //Stop flash else { widget->getFlashTimer()->stopFlashing(); diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index d9c461e836..903c903381 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -619,11 +619,6 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, chat["message"] = toast_msg; channel->addChat(chat); } - //Will show Conversations floater when chat preference is set - else if(gSavedSettings.getString("NotificationNearbyChatOptions") == "openconversations") - { - LLFloaterReg::showInstance("im_container"); - } } } diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 6e58a66bcd..efc7be6dd6 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -306,7 +306,7 @@ void LLFloaterIMSessionTab::onFocusReceived() LLFloaterIMContainer* container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); if (container) { - container->selectConversationPair(mSessionID, true); + container->selectConversationPair(mSessionID, ! getHost()); container->showStub(! getHost()); } } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index e5dda7e8d8..b6fd3ec9c8 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -191,6 +191,12 @@ void on_new_message(const LLSD& msg) } else if("openconversations" == action) { + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + if (im_box) + { + im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item + } + LLFloaterReg::showInstance("im_container"); } } -- cgit v1.2.3 From f1155c4fa5e9a4eaa5b4d452fc46a2246fb305bd Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Tue, 4 Dec 2012 04:14:51 +0200 Subject: CHUI-573 FIXED Notification chiclet shown when object chiclets are shown --- indra/newview/llchiclet.cpp | 882 +-------------------- indra/newview/llchiclet.h | 555 +------------ indra/newview/llchicletbar.cpp | 104 +-- indra/newview/llchicletbar.h | 16 - indra/newview/llfloaterimsession.cpp | 10 +- indra/newview/llscriptfloater.cpp | 121 ++- indra/newview/llsyswellwindow.cpp | 289 +------ indra/newview/llsyswellwindow.h | 66 +- .../default/textures/bottomtray/Notices_Unread.png | Bin 3693 -> 0 bytes .../textures/bottomtray/VoicePTT_Lvl1_Dark.png | Bin 602 -> 0 bytes .../textures/bottomtray/VoicePTT_Lvl2_Dark.png | Bin 669 -> 0 bytes .../textures/bottomtray/VoicePTT_Lvl3_Dark.png | Bin 639 -> 0 bytes .../textures/bottomtray/VoicePTT_Off_Dark.png | Bin 547 -> 0 bytes .../textures/bottomtray/VoicePTT_On_Dark.png | Bin 526 -> 0 bytes indra/newview/skins/default/textures/textures.xml | 8 - .../skins/default/xui/da/menu_im_well_button.xml | 4 - .../xui/da/menu_notification_well_button.xml | 4 - .../skins/default/xui/de/menu_im_well_button.xml | 4 - .../xui/de/menu_notification_well_button.xml | 4 - .../xui/en/menu_notification_well_button.xml | 16 - .../skins/default/xui/en/panel_activeim_row.xml | 97 --- .../skins/default/xui/en/panel_chiclet_bar.xml | 44 - .../default/xui/en/widgets/chiclet_im_adhoc.xml | 55 -- .../default/xui/en/widgets/chiclet_im_group.xml | 56 -- .../default/xui/en/widgets/chiclet_im_p2p.xml | 56 -- .../skins/default/xui/es/menu_im_well_button.xml | 4 - .../xui/es/menu_notification_well_button.xml | 4 - .../skins/default/xui/fr/menu_im_well_button.xml | 4 - .../xui/fr/menu_notification_well_button.xml | 4 - .../skins/default/xui/it/menu_im_well_button.xml | 4 - .../xui/it/menu_notification_well_button.xml | 4 - .../skins/default/xui/ja/menu_im_well_button.xml | 4 - .../xui/ja/menu_notification_well_button.xml | 4 - .../skins/default/xui/pl/menu_im_well_button.xml | 4 - .../xui/pl/menu_notification_well_button.xml | 4 - .../skins/default/xui/pt/menu_im_well_button.xml | 4 - .../xui/pt/menu_notification_well_button.xml | 4 - .../skins/default/xui/ru/menu_im_well_button.xml | 4 - .../xui/ru/menu_notification_well_button.xml | 4 - .../skins/default/xui/tr/menu_im_well_button.xml | 4 - .../xui/tr/menu_notification_well_button.xml | 4 - .../skins/default/xui/zh/menu_im_well_button.xml | 4 - .../xui/zh/menu_notification_well_button.xml | 4 - 43 files changed, 100 insertions(+), 2363 deletions(-) delete mode 100644 indra/newview/skins/default/textures/bottomtray/Notices_Unread.png delete mode 100644 indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1_Dark.png delete mode 100644 indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2_Dark.png delete mode 100644 indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl3_Dark.png delete mode 100644 indra/newview/skins/default/textures/bottomtray/VoicePTT_Off_Dark.png delete mode 100644 indra/newview/skins/default/textures/bottomtray/VoicePTT_On_Dark.png delete mode 100644 indra/newview/skins/default/xui/da/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/da/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/de/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/de/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/en/panel_activeim_row.xml delete mode 100644 indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml delete mode 100644 indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml delete mode 100644 indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml delete mode 100644 indra/newview/skins/default/xui/es/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/es/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/fr/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/fr/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/it/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/it/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/ja/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/ja/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/pl/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/pl/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/pt/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/pt/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/ru/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/ru/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/tr/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/tr/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/zh/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/zh/menu_notification_well_button.xml (limited to 'indra') diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index a665aeb6bd..1acbdd32b7 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -27,35 +27,15 @@ #include "llviewerprecompiledheaders.h" // must be first include #include "llchiclet.h" -#include "llagent.h" -#include "llavataractions.h" -#include "llchicletbar.h" -#include "lleventtimer.h" -#include "llgroupactions.h" -#include "lliconctrl.h" #include "llfloaterimsession.h" #include "llfloaterimcontainer.h" -#include "llimview.h" #include "llfloaterreg.h" #include "lllocalcliprect.h" -#include "llmenugl.h" #include "llnotifications.h" -#include "llnotificationsutil.h" -#include "lloutputmonitorctrl.h" #include "llscriptfloater.h" -#include "llspeakers.h" -#include "lltextbox.h" -#include "llvoiceclient.h" -#include "llgroupmgr.h" -#include "llnotificationmanager.h" -#include "lltransientfloatermgr.h" -#include "llsyswellwindow.h" +#include "llsingleton.h" static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel"); -static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification"); -static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t3("chiclet_im_p2p"); -static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t4("chiclet_im_group"); -static LLDefaultChildRegistry::Register<LLAdHocChiclet> t5("chiclet_im_adhoc"); static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script"); static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer"); @@ -66,192 +46,6 @@ boost::signals2::signal<LLChiclet* (const LLUUID&), ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// - -LLSysWellChiclet::Params::Params() -: button("button") -, unread_notifications("unread_notifications") -, max_displayed_count("max_displayed_count", 99) -{ - button.name = "button"; - button.tab_stop = FALSE; - button.label = LLStringUtil::null; -} - -LLSysWellChiclet::LLSysWellChiclet(const Params& p) -: LLChiclet(p) -, mButton(NULL) -, mCounter(0) -, mMaxDisplayedCount(p.max_displayed_count) -, mIsNewMessagesState(false) -, mFlashToLitTimer(NULL) -, mContextMenu(NULL) -{ - LLButton::Params button_params = p.button; - mButton = LLUICtrlFactory::create<LLButton>(button_params); - addChild(mButton); - - - mFlashToLitTimer = new LLFlashTimer(boost::bind(&LLSysWellChiclet::changeLitState, this, _1)); -} - -LLSysWellChiclet::~LLSysWellChiclet() -{ - delete mFlashToLitTimer; -} - -void LLSysWellChiclet::setCounter(S32 counter) -{ - // do nothing if the same counter is coming. EXT-3678. - if (counter == mCounter) return; - - // note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter) - std::string s_count; - if(counter != 0) - { - static std::string more_messages_exist("+"); - std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : ""); - s_count = llformat("%d%s" - , llmin(counter, mMaxDisplayedCount) - , more_messages.c_str() - ); - } - - mButton->setLabel(s_count); - - mCounter = counter; -} - -boost::signals2::connection LLSysWellChiclet::setClickCallback( - const commit_callback_t& cb) -{ - return mButton->setClickedCallback(cb); -} - -void LLSysWellChiclet::setToggleState(BOOL toggled) { - mButton->setToggleState(toggled); -} - -void LLSysWellChiclet::changeLitState(bool blink) -{ - setNewMessagesState(!mIsNewMessagesState); -} - -void LLSysWellChiclet::setNewMessagesState(bool new_messages) -{ - /* - Emulate 4 states of button by background images, see detains in EXT-3147 - xml attribute Description - image_unselected "Unlit" - there are no new messages - image_selected "Unlit" + "Selected" - there are no new messages and the Well is open - image_pressed "Lit" - there are new messages - image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open - */ - mButton->setForcePressedState(new_messages); - - mIsNewMessagesState = new_messages; -} - -void LLSysWellChiclet::updateWidget(bool is_window_empty) -{ - mButton->setEnabled(!is_window_empty); - - if (LLChicletBar::instanceExists()) - { - LLChicletBar::getInstance()->showWellButton(getName(), !is_window_empty); - } -} -// virtual -BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - if(!mContextMenu) - { - createMenu(); - } - if (mContextMenu) - { - mContextMenu->show(x, y); - LLMenuGL::showPopup(this, mContextMenu, x, y); - } - return TRUE; -} - -/************************************************************************/ -/* LLNotificationChiclet implementation */ -/************************************************************************/ -LLNotificationChiclet::LLNotificationChiclet(const Params& p) -: LLSysWellChiclet(p), - mUreadSystemNotifications(0) -{ - mNotificationChannel.reset(new ChicletNotificationChannel(this)); - // ensure that notification well window exists, to synchronously - // handle toast add/delete events. - LLNotificationWellWindow::getInstance()->setSysWellChiclet(this); -} - -void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data) -{ - std::string action = user_data.asString(); - if("close all" == action) - { - LLNotificationWellWindow::getInstance()->closeAll(); - } -} - -bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data) -{ - std::string item = user_data.asString(); - if (item == "can close all") - { - return mUreadSystemNotifications != 0; - } - return true; -} - -void LLNotificationChiclet::createMenu() -{ - if(mContextMenu) - { - llwarns << "Menu already exists" << llendl; - return; - } - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("NotificationWellChicletMenu.Action", - boost::bind(&LLNotificationChiclet::onMenuItemClicked, this, _2)); - - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - enable_registrar.add("NotificationWellChicletMenu.EnableItem", - boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2)); - - mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu> - ("menu_notification_well_button.xml", - LLMenuGL::sMenuContainer, - LLViewerMenuHolderGL::child_registry_t::instance()); -} - -/*virtual*/ -void LLNotificationChiclet::setCounter(S32 counter) -{ - LLSysWellChiclet::setCounter(counter); - updateWidget(getCounter() == 0); - -} - -bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification ) -{ - if( !(notification->canLogToIM() && notification->hasFormElements()) - && (!notification->getPayload().has("give_inventory_notification") - || notification->getPayload()["give_inventory_notification"])) - { - return true; - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - LLChiclet::Params::Params() : show_counter("show_counter", true) , enable_counter("enable_counter", false) @@ -303,7 +97,9 @@ LLSD LLChiclet::getValue() const void LLChiclet::setValue(const LLSD& value) { if(value.isUUID()) + { setSessionId(value.asUUID()); + } } ////////////////////////////////////////////////////////////////////////// @@ -315,12 +111,9 @@ LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p) , mShowSpeaker(false) , mDefaultWidth(p.rect().getWidth()) , mNewMessagesIcon(NULL) -, mSpeakerCtrl(NULL) -, mCounterCtrl(NULL) , mChicletButton(NULL) , mPopupMenu(NULL) { - enableCounterControl(p.enable_counter); } /* virtual*/ @@ -331,107 +124,14 @@ BOOL LLIMChiclet::postBuild() mChicletButton->setDoubleClickCallback(boost::bind(&LLIMChiclet::onMouseDown, this)); return TRUE; } -void LLIMChiclet::setShowSpeaker(bool show) -{ - bool needs_resize = getShowSpeaker() != show; - if(needs_resize) - { - mShowSpeaker = show; - } - - toggleSpeakerControl(); -} - -void LLIMChiclet::enableCounterControl(bool enable) -{ - mCounterEnabled = enable; - if(!enable) - { - LLChiclet::setShowCounter(false); - } -} - -void LLIMChiclet::setShowCounter(bool show) -{ - if(!mCounterEnabled) - { - return; - } - - bool needs_resize = getShowCounter() != show; - if(needs_resize) - { - LLChiclet::setShowCounter(show); - toggleCounterControl(); - } -} - -void LLIMChiclet::initSpeakerControl() -{ - // virtual -} void LLIMChiclet::setRequiredWidth() { - bool show_speaker = getShowSpeaker(); - bool show_counter = getShowCounter(); S32 required_width = mDefaultWidth; - - if (show_counter) - { - required_width += mCounterCtrl->getRect().getWidth(); - } - if (show_speaker) - { - required_width += mSpeakerCtrl->getRect().getWidth(); - } - reshape(required_width, getRect().getHeight()); - onChicletSizeChanged(); } -void LLIMChiclet::toggleSpeakerControl() -{ - if(getShowSpeaker()) - { - // move speaker to the right of chiclet icon - LLRect speaker_rc = mSpeakerCtrl->getRect(); - speaker_rc.setLeftTopAndSize(mDefaultWidth, speaker_rc.mTop, speaker_rc.getWidth(), speaker_rc.getHeight()); - mSpeakerCtrl->setRect(speaker_rc); - - if(getShowCounter()) - { - // move speaker to the right of counter - mSpeakerCtrl->translate(mCounterCtrl->getRect().getWidth(), 0); - } - - initSpeakerControl(); - } - - setRequiredWidth(); - mSpeakerCtrl->setSpeakerId(LLUUID::null); - mSpeakerCtrl->setVisible(getShowSpeaker()); -} - -void LLIMChiclet::setCounter(S32 counter) -{ - if (mCounterCtrl->getCounter() == counter) - { - return; - } - - mCounterCtrl->setCounter(counter); - setShowCounter(counter); - setShowNewMessagesIcon(counter); -} - -void LLIMChiclet::toggleCounterControl() -{ - setRequiredWidth(); - mCounterCtrl->setVisible(getShowCounter()); -} - void LLIMChiclet::setShowNewMessagesIcon(bool show) { if(mNewMessagesIcon) @@ -449,7 +149,6 @@ bool LLIMChiclet::getShowNewMessagesIcon() void LLIMChiclet::onMouseDown() { LLFloaterIMSession::toggle(getSessionId()); - setCounter(0); } void LLIMChiclet::setToggleState(bool toggle) @@ -457,52 +156,6 @@ void LLIMChiclet::setToggleState(bool toggle) mChicletButton->setToggleState(toggle); } -void LLIMChiclet::draw() -{ - LLUICtrl::draw(); -} - -// static -LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id) -{ - EType type = TYPE_UNKNOWN; - - if(session_id.isNull()) - return type; - - EInstantMessage im_type = LLIMModel::getInstance()->getType(session_id); - if (IM_COUNT == im_type) - { - llassert_always(0 && "IM session not found"); // should never happen - return type; - } - - switch(im_type) - { - case IM_NOTHING_SPECIAL: - case IM_SESSION_P2P_INVITE: - type = TYPE_IM; - break; - case IM_SESSION_GROUP_START: - case IM_SESSION_INVITE: - if (gAgent.isInGroup(session_id)) - { - type = TYPE_GROUP; - } - else - { - type = TYPE_AD_HOC; - } - break; - case IM_SESSION_CONFERENCE_START: - type = TYPE_AD_HOC; - default: - break; - } - - return type; -} - BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) { if(!mPopupMenu) @@ -534,382 +187,6 @@ bool LLIMChiclet::canCreateMenu() return true; } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLIMP2PChiclet::Params::Params() -: avatar_icon("avatar_icon") -, chiclet_button("chiclet_button") -, unread_notifications("unread_notifications") -, speaker("speaker") -, new_message_icon("new_message_icon") -, show_speaker("show_speaker") -{ -} - -LLIMP2PChiclet::LLIMP2PChiclet(const Params& p) -: LLIMChiclet(p) -, mChicletIconCtrl(NULL) -{ - LLButton::Params button_params = p.chiclet_button; - mChicletButton = LLUICtrlFactory::create<LLButton>(button_params); - addChild(mChicletButton); - - LLIconCtrl::Params new_msg_params = p.new_message_icon; - mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); - addChild(mNewMessagesIcon); - - LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon; - mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params); - addChild(mChicletIconCtrl); - - LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications; - mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params); - addChild(mCounterCtrl); - - setCounter(getCounter()); - setShowCounter(getShowCounter()); - - LLChicletSpeakerCtrl::Params speaker_params = p.speaker; - mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params); - addChild(mSpeakerCtrl); - - sendChildToFront(mNewMessagesIcon); - setShowSpeaker(p.show_speaker); -} - -void LLIMP2PChiclet::initSpeakerControl() -{ - mSpeakerCtrl->setSpeakerId(getOtherParticipantId()); -} - -void LLIMP2PChiclet::setOtherParticipantId(const LLUUID& other_participant_id) -{ - LLIMChiclet::setOtherParticipantId(other_participant_id); - mChicletIconCtrl->setValue(getOtherParticipantId()); -} - -void LLIMP2PChiclet::updateMenuItems() -{ - if(!mPopupMenu) - return; - if(getSessionId().isNull()) - return; - - LLFloaterIMSession* open_im_floater = LLFloaterIMSession::findInstance(getSessionId()); - bool open_window_exists = open_im_floater && open_im_floater->getVisible(); - mPopupMenu->getChild<LLUICtrl>("Send IM")->setEnabled(!open_window_exists); - - bool is_friend = LLAvatarActions::isFriend(getOtherParticipantId()); - mPopupMenu->getChild<LLUICtrl>("Add Friend")->setEnabled(!is_friend); -} - -void LLIMP2PChiclet::createPopupMenu() -{ - if(!canCreateMenu()) - return; - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("IMChicletMenu.Action", boost::bind(&LLIMP2PChiclet::onMenuItemClicked, this, _2)); - - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> - ("menu_imchiclet_p2p.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -} - -void LLIMP2PChiclet::onMenuItemClicked(const LLSD& user_data) -{ - std::string level = user_data.asString(); - LLUUID other_participant_id = getOtherParticipantId(); - - if("profile" == level) - { - LLAvatarActions::showProfile(other_participant_id); - } - else if("im" == level) - { - LLAvatarActions::startIM(other_participant_id); - } - else if("add" == level) - { - LLAvatarActions::requestFriendshipDialog(other_participant_id); - } - else if("end" == level) - { - LLAvatarActions::endIM(other_participant_id); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLAdHocChiclet::Params::Params() -: avatar_icon("avatar_icon") -, chiclet_button("chiclet_button") -, unread_notifications("unread_notifications") -, speaker("speaker") -, new_message_icon("new_message_icon") -, show_speaker("show_speaker") -, avatar_icon_color("avatar_icon_color", LLColor4::green) -{ -} - -LLAdHocChiclet::LLAdHocChiclet(const Params& p) -: LLIMChiclet(p) -, mChicletIconCtrl(NULL) -{ - LLButton::Params button_params = p.chiclet_button; - mChicletButton = LLUICtrlFactory::create<LLButton>(button_params); - addChild(mChicletButton); - - LLIconCtrl::Params new_msg_params = p.new_message_icon; - mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); - addChild(mNewMessagesIcon); - - LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon; - mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params); - //Make the avatar modified - mChicletIconCtrl->setColor(p.avatar_icon_color); - addChild(mChicletIconCtrl); - - LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications; - mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params); - addChild(mCounterCtrl); - - setCounter(getCounter()); - setShowCounter(getShowCounter()); - - LLChicletSpeakerCtrl::Params speaker_params = p.speaker; - mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params); - addChild(mSpeakerCtrl); - - sendChildToFront(mNewMessagesIcon); - setShowSpeaker(p.show_speaker); -} - -void LLAdHocChiclet::setSessionId(const LLUUID& session_id) -{ - LLChiclet::setSessionId(session_id); - LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id); - mChicletIconCtrl->setValue(im_session->mOtherParticipantID); -} - -void LLAdHocChiclet::draw() -{ - switchToCurrentSpeaker(); - LLIMChiclet::draw(); -} - -void LLAdHocChiclet::initSpeakerControl() -{ - switchToCurrentSpeaker(); -} - -void LLAdHocChiclet::switchToCurrentSpeaker() -{ - LLUUID speaker_id; - LLSpeakerMgr::speaker_list_t speaker_list; - - LLIMModel::getInstance()->findIMSession(getSessionId())->mSpeakers->getSpeakerList(&speaker_list, FALSE); - for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) - { - LLPointer<LLSpeaker> s = *i; - if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) - { - speaker_id = s->mID; - break; - } - } - - mSpeakerCtrl->setSpeakerId(speaker_id); -} - -void LLAdHocChiclet::createPopupMenu() -{ - if(!canCreateMenu()) - return; - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("IMChicletMenu.Action", boost::bind(&LLAdHocChiclet::onMenuItemClicked, this, _2)); - - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> - ("menu_imchiclet_adhoc.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -} - -void LLAdHocChiclet::onMenuItemClicked(const LLSD& user_data) -{ - std::string level = user_data.asString(); - LLUUID group_id = getSessionId(); - - if("end" == level) - { - LLGroupActions::endIM(group_id); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLIMGroupChiclet::Params::Params() -: group_icon("group_icon") -, chiclet_button("chiclet_button") -, unread_notifications("unread_notifications") -, speaker("speaker") -, new_message_icon("new_message_icon") -, show_speaker("show_speaker") -{ -} - -LLIMGroupChiclet::LLIMGroupChiclet(const Params& p) -: LLIMChiclet(p) -, LLGroupMgrObserver(LLUUID::null) -, mChicletIconCtrl(NULL) -{ - LLButton::Params button_params = p.chiclet_button; - mChicletButton = LLUICtrlFactory::create<LLButton>(button_params); - addChild(mChicletButton); - - LLIconCtrl::Params new_msg_params = p.new_message_icon; - mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); - addChild(mNewMessagesIcon); - - LLChicletGroupIconCtrl::Params avatar_params = p.group_icon; - mChicletIconCtrl = LLUICtrlFactory::create<LLChicletGroupIconCtrl>(avatar_params); - addChild(mChicletIconCtrl); - - LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications; - mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params); - addChild(mCounterCtrl); - - setCounter(getCounter()); - setShowCounter(getShowCounter()); - - LLChicletSpeakerCtrl::Params speaker_params = p.speaker; - mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params); - addChild(mSpeakerCtrl); - - sendChildToFront(mNewMessagesIcon); - setShowSpeaker(p.show_speaker); -} - -LLIMGroupChiclet::~LLIMGroupChiclet() -{ - LLGroupMgr::getInstance()->removeObserver(this); -} - -void LLIMGroupChiclet::draw() -{ - if(getShowSpeaker()) - { - switchToCurrentSpeaker(); - } - LLIMChiclet::draw(); -} - -void LLIMGroupChiclet::initSpeakerControl() -{ - switchToCurrentSpeaker(); -} - -void LLIMGroupChiclet::switchToCurrentSpeaker() -{ - LLUUID speaker_id; - LLSpeakerMgr::speaker_list_t speaker_list; - - LLIMModel::getInstance()->findIMSession(getSessionId())->mSpeakers->getSpeakerList(&speaker_list, FALSE); - for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) - { - LLPointer<LLSpeaker> s = *i; - if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) - { - speaker_id = s->mID; - break; - } - } - - mSpeakerCtrl->setSpeakerId(speaker_id); -} - -void LLIMGroupChiclet::setSessionId(const LLUUID& session_id) -{ - LLChiclet::setSessionId(session_id); - - LLGroupMgr* grp_mgr = LLGroupMgr::getInstance(); - LLGroupMgrGroupData* group_data = grp_mgr->getGroupData(session_id); - if (group_data && group_data->mInsigniaID.notNull()) - { - mChicletIconCtrl->setValue(group_data->mInsigniaID); - } - else - { - if(getSessionId() != mID) - { - grp_mgr->removeObserver(this); - mID = getSessionId(); - grp_mgr->addObserver(this); - } - grp_mgr->sendGroupPropertiesRequest(session_id); - } -} - -void LLIMGroupChiclet::changed(LLGroupChange gc) -{ - if (GC_PROPERTIES == gc) - { - LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(getSessionId()); - if (group_data) - { - mChicletIconCtrl->setValue(group_data->mInsigniaID); - } - } -} - -void LLIMGroupChiclet::updateMenuItems() -{ - if(!mPopupMenu) - return; - if(getSessionId().isNull()) - return; - - LLFloaterIMSession* open_im_floater = LLFloaterIMSession::findInstance(getSessionId()); - bool open_window_exists = open_im_floater && open_im_floater->getVisible(); - mPopupMenu->getChild<LLUICtrl>("Chat")->setEnabled(!open_window_exists); -} - -void LLIMGroupChiclet::createPopupMenu() -{ - if(!canCreateMenu()) - return; - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("IMChicletMenu.Action", boost::bind(&LLIMGroupChiclet::onMenuItemClicked, this, _2)); - - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> - ("menu_imchiclet_group.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -} - -void LLIMGroupChiclet::onMenuItemClicked(const LLSD& user_data) -{ - std::string level = user_data.asString(); - LLUUID group_id = getSessionId(); - - if("group chat" == level) - { - LLGroupActions::startIM(group_id); - } - else if("info" == level) - { - LLGroupActions::show(group_id); - } - else if("end" == level) - { - LLGroupActions::endIM(group_id); - } -} - - ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -964,20 +241,6 @@ void LLChicletPanel::onMessageCountChanged(const LLSD& data) { unread = 0; } - - std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(session_id); - std::list<LLChiclet *>::iterator iter; - for (iter = chiclets.begin(); iter != chiclets.end(); iter++) { - LLChiclet* chiclet = *iter; - if (chiclet != NULL) - { - chiclet->setCounter(unread); - } - else - { - llwarns << "Unable to set counter for chiclet " << session_id << llendl; - } - } } void LLChicletPanel::objectChicletCallback(const LLSD& data) @@ -992,10 +255,6 @@ void LLChicletPanel::objectChicletCallback(const LLSD& data) LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*iter); if (chiclet != NULL) { - if(data.has("unread")) - { - chiclet->setCounter(data["unread"]); - } chiclet->setShowNewMessagesIcon(new_message); } } @@ -1037,7 +296,6 @@ void LLChicletPanel::onCurrentVoiceChannelChanged(const LLUUID& session_id) LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it); if(chiclet) { - chiclet->setShowSpeaker(true); if (gSavedSettings.getBOOL("OpenIMOnVoice")) { LLFloaterIMContainer::getInstance()->showConversation(session_id); @@ -1045,20 +303,6 @@ void LLChicletPanel::onCurrentVoiceChannelChanged(const LLUUID& session_id) } } - if(!s_previous_active_voice_session_id.isNull() && s_previous_active_voice_session_id != session_id) - { - chiclets = LLIMChiclet::sFindChicletsSignal(s_previous_active_voice_session_id); - - for(std::list<LLChiclet *>::iterator it = chiclets.begin(); it != chiclets.end(); ++it) - { - LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it); - if(chiclet) - { - chiclet->setShowSpeaker(false); - } - } - } - s_previous_active_voice_session_id = session_id; } @@ -1544,85 +788,6 @@ bool LLChicletPanel::isAnyIMFloaterDoked() return res; } -S32 LLChicletPanel::getTotalUnreadIMCount() -{ - S32 count = 0; - chiclet_list_t::const_iterator it = mChicletList.begin(); - for( ; mChicletList.end() != it; ++it) - { - LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it); - if(chiclet) - { - count += chiclet->getCounter(); - } - } - return count; -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -LLChicletNotificationCounterCtrl::Params::Params() -: max_displayed_count("max_displayed_count", 99) -{ -} - -LLChicletNotificationCounterCtrl::LLChicletNotificationCounterCtrl(const Params& p) - : LLTextBox(p) - , mCounter(0) - , mInitialWidth(0) - , mMaxDisplayedCount(p.max_displayed_count) -{ - mInitialWidth = getRect().getWidth(); -} - -void LLChicletNotificationCounterCtrl::setCounter(S32 counter) -{ - mCounter = counter; - - // note same code in LLSysWellChiclet::setCounter(S32 counter) - std::string s_count; - if(counter != 0) - { - static std::string more_messages_exist("+"); - std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : ""); - s_count = llformat("%d%s" - , llmin(counter, mMaxDisplayedCount) - , more_messages.c_str() - ); - } - - if(mCounter != 0) - { - setText(s_count); - } - else - { - setText(std::string("")); - } -} - -LLRect LLChicletNotificationCounterCtrl::getRequiredRect() -{ - LLRect rc; - S32 text_width = getTextPixelWidth(); - - rc.mRight = rc.mLeft + llmax(text_width, mInitialWidth); - - return rc; -} - -void LLChicletNotificationCounterCtrl::setValue(const LLSD& value) -{ - if(value.isInteger()) - setCounter(value.asInteger()); -} - -LLSD LLChicletNotificationCounterCtrl::getValue() const -{ - return LLSD(getCounter()); -} - ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -1632,28 +797,6 @@ LLChicletAvatarIconCtrl::LLChicletAvatarIconCtrl(const Params& p) { } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLChicletGroupIconCtrl::LLChicletGroupIconCtrl(const Params& p) -: LLIconCtrl(p) -, mDefaultIcon(p.default_icon) -{ - setValue(LLUUID::null); -} - -void LLChicletGroupIconCtrl::setValue(const LLSD& value ) -{ - if(value.asUUID().isNull()) - { - LLIconCtrl::setValue(mDefaultIcon); - } - else - { - LLIconCtrl::setValue(value); - } -} ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -1681,15 +824,6 @@ void LLChicletInvOfferIconCtrl::setValue(const LLSD& value ) ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p) - : LLOutputMonitorCtrl(p) -{ -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - LLScriptChiclet::Params::Params() : icon("icon") , chiclet_button("chiclet_button") @@ -1725,11 +859,6 @@ void LLScriptChiclet::setSessionId(const LLUUID& session_id) setToolTip(LLScriptFloaterManager::getObjectName(session_id)); } -void LLScriptChiclet::setCounter(S32 counter) -{ - setShowNewMessagesIcon( counter > 0 ); -} - void LLScriptChiclet::onMouseDown() { LLScriptFloaterManager::getInstance()->toggleScriptFloater(getSessionId()); @@ -1808,11 +937,6 @@ void LLInvOfferChiclet::setSessionId(const LLUUID& session_id) } } -void LLInvOfferChiclet::setCounter(S32 counter) -{ - setShowNewMessagesIcon( counter > 0 ); -} - void LLInvOfferChiclet::onMouseDown() { LLScriptFloaterManager::instance().toggleScriptFloater(getSessionId()); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 7f72c7f9e2..bd6c1a3e71 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -29,75 +29,10 @@ #include "llavatariconctrl.h" #include "llbutton.h" -#include "llflashtimer.h" -#include "llpanel.h" -#include "lltextbox.h" -#include "lloutputmonitorctrl.h" -#include "llgroupmgr.h" -#include "llimview.h" -#include "llnotifications.h" class LLMenuGL; class LLFloaterIMSession; -/** - * Class for displaying amount of messages/notifications(unread). - */ -class LLChicletNotificationCounterCtrl : public LLTextBox -{ -public: - - struct Params : public LLInitParam::Block<Params, LLTextBox::Params> - { - /** - * Contains maximum displayed count of unread messages. Default value is 9. - * - * If count is less than "max_unread_count" will be displayed as is. - * Otherwise 9+ will be shown (for default value). - */ - Optional<S32> max_displayed_count; - - Params(); - }; - - /** - * Sets number of notifications - */ - virtual void setCounter(S32 counter); - - /** - * Returns number of notifications - */ - virtual S32 getCounter() const { return mCounter; } - - /** - * Returns width, required to display amount of notifications in text form. - * Width is the only valid value. - */ - /*virtual*/ LLRect getRequiredRect(); - - /** - * Sets number of notifications using LLSD - */ - /*virtual*/ void setValue(const LLSD& value); - - /** - * Returns number of notifications wrapped in LLSD - */ - /*virtual*/ LLSD getValue() const; - -protected: - - LLChicletNotificationCounterCtrl(const Params& p); - friend class LLUICtrlFactory; - -private: - - S32 mCounter; - S32 mInitialWidth; - S32 mMaxDisplayedCount; -}; - /** * Class for displaying avatar's icon in P2P chiclet. */ @@ -121,35 +56,6 @@ protected: friend class LLUICtrlFactory; }; -/** - * Class for displaying group's icon in Group chiclet. - */ -class LLChicletGroupIconCtrl : public LLIconCtrl -{ -public: - - struct Params : public LLInitParam::Block<Params, LLIconCtrl::Params> - { - Optional<std::string> default_icon; - - Params() - : default_icon("default_icon", "Generic_Group") - {} - }; - - /** - * Sets icon, if value is LLUUID::null - default icon will be set. - */ - virtual void setValue(const LLSD& value ); - -protected: - - LLChicletGroupIconCtrl(const Params& p); - friend class LLUICtrlFactory; - - std::string mDefaultIcon; -}; - /** * Class for displaying icon in inventory offer chiclet. */ @@ -183,23 +89,6 @@ private: std::string mDefaultIcon; }; -/** - * Class for displaying of speaker's voice indicator - */ -class LLChicletSpeakerCtrl : public LLOutputMonitorCtrl -{ -public: - - struct Params : public LLInitParam::Block<Params, LLOutputMonitorCtrl::Params> - { - Params(){}; - }; -protected: - - LLChicletSpeakerCtrl(const Params&p); - friend class LLUICtrlFactory; -}; - /** * Base class for all chiclets. */ @@ -227,26 +116,6 @@ public: */ virtual const LLUUID& getSessionId() const { return mSessionId; } - /** - * Sets number of unread notifications. - */ - virtual void setCounter(S32 counter) = 0; - - /** - * Returns number of unread notifications. - */ - virtual S32 getCounter() = 0; - - /** - * Sets show counter state. - */ - virtual void setShowCounter(bool show) { mShowCounter = show; } - - /** - * Returns show counter state. - */ - virtual bool getShowCounter() {return mShowCounter;}; - /** * Connects chiclet clicked event with callback. */ @@ -324,62 +193,6 @@ public: * It is used for default setting up of chicklet:click handler, etc. */ BOOL postBuild(); - /** - * Sets IM session name. This name will be displayed in chiclet tooltip. - */ - virtual void setIMSessionName(const std::string& name) { setToolTip(name); } - - /** - * Sets id of person/group user is chatting with. - * Session id should be set before calling this - */ - virtual void setOtherParticipantId(const LLUUID& other_participant_id) { mOtherParticipantId = other_participant_id; } - - /** - * Gets id of person/group user is chatting with. - */ - virtual LLUUID getOtherParticipantId() { return mOtherParticipantId; } - - /** - * Init Speaker Control with speaker's ID - */ - virtual void initSpeakerControl(); - - /** - * set status (Shows/Hide) for voice control. - */ - virtual void setShowSpeaker(bool show); - - /** - * Returns voice chat status control visibility. - */ - virtual bool getShowSpeaker() {return mShowSpeaker;}; - - /** - * Shows/Hides for voice control for a chiclet. - */ - virtual void toggleSpeakerControl(); - - /** - * Sets number of unread messages. Will update chiclet's width if number text - * exceeds size of counter and notify it's parent about size change. - */ - virtual void setCounter(S32); - - /** - * Enables/disables the counter control for a chiclet. - */ - virtual void enableCounterControl(bool enable); - - /** - * Sets show counter state. - */ - virtual void setShowCounter(bool show); - - /** - * Shows/Hides for counter control for a chiclet. - */ - virtual void toggleCounterControl(); /** * Sets required width for a chiclet according to visible controls. @@ -396,21 +209,6 @@ public: */ virtual bool getShowNewMessagesIcon(); - virtual void draw(); - - /** - * Determine whether given ID refers to a group or an IM chat session. - * - * This is used when we need to chose what IM chiclet (P2P/group) - * class to instantiate. - * - * @param session_id session ID. - * @return TYPE_GROUP in case of group chat session, - * TYPE_IM in case of P2P session, - * TYPE_UNKNOWN otherwise. - */ - static EType getIMSessionType(const LLUUID& session_id); - /** * The action taken on mouse down event. * @@ -452,8 +250,6 @@ protected: S32 mDefaultWidth; LLIconCtrl* mNewMessagesIcon; - LLChicletNotificationCounterCtrl* mCounterCtrl; - LLChicletSpeakerCtrl* mSpeakerCtrl; LLButton* mChicletButton; /** the id of another participant, either an avatar id or a group id*/ @@ -481,137 +277,6 @@ public: sFindChicletsSignal; }; -/** - * Implements P2P chiclet. - */ -class LLIMP2PChiclet : public LLIMChiclet -{ -public: - struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params> - { - Optional<LLButton::Params> chiclet_button; - - Optional<LLChicletAvatarIconCtrl::Params> avatar_icon; - - Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications; - - Optional<LLChicletSpeakerCtrl::Params> speaker; - - Optional<LLIconCtrl::Params> new_message_icon; - - Optional<bool> show_speaker; - - Params(); - }; - - /* virtual */ void setOtherParticipantId(const LLUUID& other_participant_id); - - /** - * Init Speaker Control with speaker's ID - */ - /*virtual*/ void initSpeakerControl(); - - /** - * Returns number of unread messages. - */ - /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } - -protected: - LLIMP2PChiclet(const Params& p); - friend class LLUICtrlFactory; - - /** - * Creates chiclet popup menu. Will create P2P or Group IM Chat menu - * based on other participant's id. - */ - virtual void createPopupMenu(); - - /** - * Processes clicks on chiclet popup menu. - */ - virtual void onMenuItemClicked(const LLSD& user_data); - - /** - * Enables/disables menus based on relationship with other participant. - * Enables/disables "show session" menu item depending on visible IM floater existence. - */ - virtual void updateMenuItems(); - -private: - - LLChicletAvatarIconCtrl* mChicletIconCtrl; -}; - -/** - * Implements AD-HOC chiclet. - */ -class LLAdHocChiclet : public LLIMChiclet -{ -public: - struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params> - { - Optional<LLButton::Params> chiclet_button; - - Optional<LLChicletAvatarIconCtrl::Params> avatar_icon; - - Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications; - - Optional<LLChicletSpeakerCtrl::Params> speaker; - - Optional<LLIconCtrl::Params> new_message_icon; - - Optional<bool> show_speaker; - - Optional<LLColor4> avatar_icon_color; - - Params(); - }; - - /** - * Sets session id. - * Session ID for group chat is actually Group ID. - */ - /*virtual*/ void setSessionId(const LLUUID& session_id); - - /** - * Keep Speaker Control with actual speaker's ID - */ - /*virtual*/ void draw(); - - /** - * Init Speaker Control with speaker's ID - */ - /*virtual*/ void initSpeakerControl(); - - /** - * Returns number of unread messages. - */ - /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } - -protected: - LLAdHocChiclet(const Params& p); - friend class LLUICtrlFactory; - - /** - * Creates chiclet popup menu. Will create AdHoc Chat menu - * based on other participant's id. - */ - virtual void createPopupMenu(); - - /** - * Processes clicks on chiclet popup menu. - */ - virtual void onMenuItemClicked(const LLSD& user_data); - - /** - * Finds a current speaker and resets the SpeakerControl with speaker's ID - */ - /*virtual*/ void switchToCurrentSpeaker(); - -private: - - LLChicletAvatarIconCtrl* mChicletIconCtrl; -}; /** * Chiclet for script floaters. @@ -633,10 +298,6 @@ public: /*virtual*/ void setSessionId(const LLUUID& session_id); - /*virtual*/ void setCounter(S32 counter); - - /*virtual*/ S32 getCounter() { return 0; } - /** * Toggle script floater */ @@ -682,10 +343,6 @@ public: /*virtual*/ void setSessionId(const LLUUID& session_id); - /*virtual*/ void setCounter(S32 counter); - - /*virtual*/ S32 getCounter() { return 0; } - /** * Toggle script floater */ @@ -709,214 +366,6 @@ private: LLChicletInvOfferIconCtrl* mChicletIconCtrl; }; -/** - * Implements Group chat chiclet. - */ -class LLIMGroupChiclet : public LLIMChiclet, public LLGroupMgrObserver -{ -public: - - struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params> - { - Optional<LLButton::Params> chiclet_button; - - Optional<LLChicletGroupIconCtrl::Params> group_icon; - - Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications; - - Optional<LLChicletSpeakerCtrl::Params> speaker; - - Optional<LLIconCtrl::Params> new_message_icon; - - Optional<bool> show_speaker; - - Params(); - }; - - /** - * Sets session id. - * Session ID for group chat is actually Group ID. - */ - /*virtual*/ void setSessionId(const LLUUID& session_id); - - /** - * Keep Speaker Control with actual speaker's ID - */ - /*virtual*/ void draw(); - - /** - * Callback for LLGroupMgrObserver, we get this when group data is available or changed. - * Sets group icon. - */ - /*virtual*/ void changed(LLGroupChange gc); - - /** - * Init Speaker Control with speaker's ID - */ - /*virtual*/ void initSpeakerControl(); - - /** - * Returns number of unread messages. - */ - /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } - - ~LLIMGroupChiclet(); - -protected: - LLIMGroupChiclet(const Params& p); - friend class LLUICtrlFactory; - - /** - * Finds a current speaker and resets the SpeakerControl with speaker's ID - */ - /*virtual*/ void switchToCurrentSpeaker(); - - /** - * Creates chiclet popup menu. Will create P2P or Group IM Chat menu - * based on other participant's id. - */ - virtual void createPopupMenu(); - - /** - * Processes clicks on chiclet popup menu. - */ - virtual void onMenuItemClicked(const LLSD& user_data); - - /** - * Enables/disables "show session" menu item depending on visible IM floater existence. - */ - virtual void updateMenuItems(); - -private: - - LLChicletGroupIconCtrl* mChicletIconCtrl; -}; - -/** - * Implements notification chiclet. Used to display total amount of unread messages - * across all IM sessions, total amount of system notifications. See EXT-3147 for details - */ -class LLSysWellChiclet : public LLChiclet -{ -public: - - struct Params : public LLInitParam::Block<Params, LLChiclet::Params> - { - Optional<LLButton::Params> button; - - Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications; - - /** - * Contains maximum displayed count of unread messages. Default value is 9. - * - * If count is less than "max_unread_count" will be displayed as is. - * Otherwise 9+ will be shown (for default value). - */ - Optional<S32> max_displayed_count; - - Params(); - }; - - /*virtual*/ void setCounter(S32 counter); - - // *TODO: mantipov: seems getCounter is not necessary for LLNotificationChiclet - // but inherited interface requires it to implement. - // Probably it can be safe removed. - /*virtual*/S32 getCounter() { return mCounter; } - - boost::signals2::connection setClickCallback(const commit_callback_t& cb); - - /*virtual*/ ~LLSysWellChiclet(); - - void setToggleState(BOOL toggled); - - void setNewMessagesState(bool new_messages); - //this method should change a widget according to state of the SysWellWindow - virtual void updateWidget(bool is_window_empty); - -protected: - - LLSysWellChiclet(const Params& p); - friend class LLUICtrlFactory; - - /** - * Change Well 'Lit' state from 'Lit' to 'Unlit' and vice-versa. - * - * There is an assumption that it will be called 2*N times to do not change its start state. - * @see FlashToLitTimer - */ - void changeLitState(bool blink); - - /** - * Displays menu. - */ - virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - - virtual void createMenu() = 0; - -protected: - class FlashToLitTimer; - LLButton* mButton; - S32 mCounter; - S32 mMaxDisplayedCount; - bool mIsNewMessagesState; - - LLFlashTimer* mFlashToLitTimer; - LLContextMenu* mContextMenu; -}; - -class LLNotificationChiclet : public LLSysWellChiclet -{ - LOG_CLASS(LLNotificationChiclet); - - friend class LLUICtrlFactory; -public: - struct Params : public LLInitParam::Block<Params, LLSysWellChiclet::Params>{}; - -protected: - struct ChicletNotificationChannel : public LLNotificationChannel - { - ChicletNotificationChannel(LLNotificationChiclet* chiclet) - : LLNotificationChannel(LLNotificationChannel::Params().filter(filterNotification).name(chiclet->getSessionId().asString())), - mChiclet(chiclet) - { - // connect counter handlers to the signals - connectToChannel("Group Notifications"); - connectToChannel("Offer"); - connectToChannel("Notifications"); - } - - static bool filterNotification(LLNotificationPtr notify); - // connect counter updaters to the corresponding signals - /*virtual*/ void onAdd(LLNotificationPtr p) { mChiclet->setCounter(++mChiclet->mUreadSystemNotifications); } - /*virtual*/ void onDelete(LLNotificationPtr p) { mChiclet->setCounter(--mChiclet->mUreadSystemNotifications); } - - LLNotificationChiclet* const mChiclet; - }; - - boost::scoped_ptr<ChicletNotificationChannel> mNotificationChannel; - - LLNotificationChiclet(const Params& p); - - /** - * Processes clicks on chiclet menu. - */ - void onMenuItemClicked(const LLSD& user_data); - - /** - * Enables chiclet menu items. - */ - bool enableMenuItem(const LLSD& user_data); - - /** - * Creates menu. - */ - /*virtual*/ void createMenu(); - - /*virtual*/ void setCounter(S32 counter); - S32 mUreadSystemNotifications; -}; - /** * Storage class for all IM chiclets. Provides mechanism to display, * scroll, create, remove chiclets. @@ -1018,9 +467,7 @@ public: S32 getMinWidth() const { return mMinWidth; } - S32 getTotalUnreadIMCount(); - - S32 notifyParent(const LLSD& info); + /*virtual*/ S32 notifyParent(const LLSD& info); /** * Toggle chiclet by session id ON and toggle OFF all other chiclets. diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index cfcde64e7b..fde7764129 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -25,18 +25,11 @@ */ #include "llviewerprecompiledheaders.h" // must be first include - #include "llchicletbar.h" -// library includes -#include "llfloaterreg.h" -#include "lllayoutstack.h" - -// newview includes #include "llchiclet.h" -#include "llfloaterimsession.h" // for LLFloaterIMSession +#include "lllayoutstack.h" #include "llpaneltopinfobar.h" -#include "llsyswellwindow.h" namespace { @@ -60,106 +53,11 @@ LLChicletBar::LLChicletBar(const LLSD&) buildFromFile("panel_chiclet_bar.xml"); } -LLChicletBar::~LLChicletBar() -{ -} - -LLIMChiclet* LLChicletBar::createIMChiclet(const LLUUID& session_id) -{ - LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(session_id); - - switch (im_chiclet_type) - { - case LLIMChiclet::TYPE_IM: - return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id); - case LLIMChiclet::TYPE_GROUP: - return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id); - case LLIMChiclet::TYPE_AD_HOC: - return getChicletPanel()->createChiclet<LLAdHocChiclet>(session_id); - case LLIMChiclet::TYPE_UNKNOWN: - break; - } - - return NULL; -} - -//virtual -void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) -{ - if (!getChicletPanel()) return; - - LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); - if (!session) return; - - // no need to spawn chiclets for participants in P2P calls called through Avaline - if (session->isP2P() && session->isOtherParticipantAvaline()) return; - - // Do not spawn chiclet when using the new multitab conversation UI - if (LLFloaterIMSessionTab::isChatMultiTab()) - { - LLFloaterIMSessionTab::addToHost(session_id); - return; - } - - if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return; - - LLIMChiclet* chiclet = createIMChiclet(session_id); - if(chiclet) - { - chiclet->setIMSessionName(name); - chiclet->setOtherParticipantId(other_participant_id); - - LLFloaterIMSession::onIMChicletCreated(session_id); - - } - else - { - llwarns << "Could not create chiclet" << llendl; - } -} - -//virtual -void LLChicletBar::sessionRemoved(const LLUUID& session_id) -{ - if(getChicletPanel()) - { - // IM floater should be closed when session removed and associated chiclet closed - LLFloaterIMSession* im_floater = LLFloaterReg::findTypedInstance<LLFloaterIMSession>("impanel", session_id); - if (im_floater != NULL && !im_floater->getStartConferenceInSameFloater()) - { - // Close the IM floater only if we are not planning to close the P2P chat - // and start a new conference in the same floater. - im_floater->closeFloater(); - } - - getChicletPanel()->removeChiclet(session_id); - } -} - -void LLChicletBar::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) -{ - //this is only needed in case of outgoing ad-hoc/group chat sessions - LLChicletPanel* chiclet_panel = getChicletPanel(); - if (chiclet_panel) - { - //it should be ad-hoc im chiclet or group im chiclet - LLChiclet* chiclet = chiclet_panel->findChiclet<LLChiclet>(old_session_id); - if (chiclet) chiclet->setSessionId(new_session_id); - } -} - -S32 LLChicletBar::getTotalUnreadIMCount() -{ - return getChicletPanel()->getTotalUnreadIMCount(); -} - BOOL LLChicletBar::postBuild() { mToolbarStack = getChild<LLLayoutStack>("toolbar_stack"); mChicletPanel = getChild<LLChicletPanel>("chiclet_list"); - showWellButton("notification_well", !LLNotificationWellWindow::getInstance()->isWindowEmpty()); - LLPanelTopInfoBar::instance().setResizeCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this)); LLPanelTopInfoBar::instance().setVisibleCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this)); diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h index dc991ca772..956c82cb77 100644 --- a/indra/newview/llchicletbar.h +++ b/indra/newview/llchicletbar.h @@ -28,7 +28,6 @@ #define LL_LLCHICLETBAR_H #include "llpanel.h" -#include "llimview.h" class LLChicletPanel; class LLIMChiclet; @@ -38,32 +37,17 @@ class LLLayoutStack; class LLChicletBar : public LLSingleton<LLChicletBar> , public LLPanel - , public LLIMSessionObserver { LOG_CLASS(LLChicletBar); friend class LLSingleton<LLChicletBar>; public: - ~LLChicletBar(); BOOL postBuild(); LLChicletPanel* getChicletPanel() { return mChicletPanel; } - // LLIMSessionObserver observe triggers - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); - /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; - /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; - /*virtual*/ void sessionRemoved(const LLUUID& session_id); - /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); - - S32 getTotalUnreadIMCount(); - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent); - /** - * Creates IM Chiclet based on session type (IM chat or Group chat) - */ - LLIMChiclet* createIMChiclet(const LLUUID& session_id); /** * Shows/hides panel with specified well button (IM or Notification) diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 212b0df712..9829ae713c 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -616,10 +616,14 @@ void LLFloaterIMSession::setVisible(BOOL visible) if(!visible) { - LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(mSessionID); - if(chiclet) + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) { - chiclet->setToggleState(false); + LLIMChiclet * chicletp = chiclet_panelp->findChiclet<LLIMChiclet>(mSessionID); + if(NULL != chicletp) + { + chicletp->setToggleState(false); + } } } diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index dc12192697..0e0da6bdc7 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -95,7 +95,12 @@ bool LLScriptFloater::toggle(const LLUUID& notification_id) show(notification_id); } - LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(notification_id, true); + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + chiclet_panelp->setChicletToggleState(notification_id, true); + } + return true; } @@ -206,10 +211,14 @@ void LLScriptFloater::setVisible(BOOL visible) if(!visible) { - LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(getNotificationId()); - if(chiclet) + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) { - chiclet->setToggleState(false); + LLIMChiclet * chicletp = chiclet_panelp->findChiclet<LLIMChiclet>(getNotificationId()); + if(NULL != chicletp) + { + chicletp->setToggleState(false); + } } } } @@ -218,15 +227,19 @@ void LLScriptFloater::onMouseDown() { if(getNotificationId().notNull()) { - // Remove new message icon - LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(getNotificationId()); - if (chiclet == NULL) + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) { - llerror("Dock chiclet for LLScriptFloater doesn't exist", 0); - } - else - { - chiclet->setShowNewMessagesIcon(false); + LLIMChiclet * chicletp = chiclet_panelp->findChiclet<LLIMChiclet>(getNotificationId()); + // Remove new message icon + if (NULL == chicletp) + { + llerror("Dock chiclet for LLScriptFloater doesn't exist", 0); + } + else + { + chicletp->setShowNewMessagesIcon(false); + } } } } @@ -262,7 +275,11 @@ void LLScriptFloater::onFocusLost() { if(getNotificationId().notNull()) { - LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(getNotificationId(), false); + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + chiclet_panelp->setChicletToggleState(getNotificationId(), false); + } } } @@ -271,7 +288,11 @@ void LLScriptFloater::onFocusReceived() // first focus will be received before setObjectId() call - don't toggle chiclet if(getNotificationId().notNull()) { - LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(getNotificationId(), true); + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + chiclet_panelp->setChicletToggleState(getNotificationId(), true); + } } } @@ -279,28 +300,30 @@ void LLScriptFloater::dockToChiclet(bool dock) { if (getDockControl() == NULL) { - LLChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLChiclet>(getNotificationId()); - if (chiclet == NULL) - { - llwarns << "Dock chiclet for LLScriptFloater doesn't exist" << llendl; - return; - } - else + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) { - LLChicletBar::getInstance()->getChicletPanel()->scrollToChiclet(chiclet); - } + LLChiclet * chicletp = chiclet_panelp->findChiclet<LLChiclet>(getNotificationId()); + if (NULL == chicletp) + { + llwarns << "Dock chiclet for LLScriptFloater doesn't exist" << llendl; + return; + } - // Stop saving position while we dock floater - bool save = getSavePosition(); - setSavePosition(false); + chiclet_panelp->scrollToChiclet(chicletp); - setDockControl(new LLDockControl(chiclet, this, getDockTongue(), - LLDockControl::BOTTOM)); + // Stop saving position while we dock floater + bool save = getSavePosition(); + setSavePosition(false); - setDocked(dock); + setDockControl(new LLDockControl(chicletp, this, getDockTongue(), + LLDockControl::BOTTOM)); - // Restore saving - setSavePosition(save); + setDocked(dock); + + // Restore saving + setSavePosition(save); + } } } @@ -347,11 +370,15 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) script_notification_map_t::const_iterator it = findUsingObjectId(object_id); if(it != mNotifications.end()) { - LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(it->first); - if(chiclet) + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) { - // Pass the new_message icon state further. - set_new_message = chiclet->getShowNewMessagesIcon(); + LLIMChiclet * chicletp = chiclet_panelp->findChiclet<LLIMChiclet>(it->first); + if(NULL != chicletp) + { + // Pass the new_message icon state further. + set_new_message = chicletp->getShowNewMessagesIcon(); + } } LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", it->first); @@ -367,14 +394,18 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) mNotifications.insert(std::make_pair(notification_id, object_id)); - // Create inventory offer chiclet for offer type notifications - if( OBJ_GIVE_INVENTORY == obj_type ) + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) { - LLChicletBar::instance().getChicletPanel()->createChiclet<LLInvOfferChiclet>(notification_id); - } - else - { - LLChicletBar::getInstance()->getChicletPanel()->createChiclet<LLScriptChiclet>(notification_id); + // Create inventory offer chiclet for offer type notifications + if( OBJ_GIVE_INVENTORY == obj_type ) + { + chiclet_panelp->createChiclet<LLInvOfferChiclet>(notification_id); + } + else + { + chiclet_panelp->createChiclet<LLScriptChiclet>(notification_id); + } } LLIMWellWindow::getInstance()->addObjectRow(notification_id, set_new_message); @@ -410,7 +441,11 @@ void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id) // remove related chiclet if (LLChicletBar::instanceExists()) { - LLChicletBar::getInstance()->getChicletPanel()->removeChiclet(notification_id); + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + chiclet_panelp->removeChiclet(notification_id); + } } LLIMWellWindow* im_well_window = LLIMWellWindow::findInstance(); diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 3605129d48..8a43855a7d 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -23,35 +23,23 @@ * $/LicenseInfo$ */ - #include "llviewerprecompiledheaders.h" // must be first include - #include "llsyswellwindow.h" -#include "llagent.h" -#include "llavatarnamecache.h" - -#include "llflatlistview.h" -#include "llfloaterreg.h" -#include "llnotifications.h" - -#include "llscriptfloater.h" -#include "llviewercontrol.h" -#include "llviewerwindow.h" - #include "llchiclet.h" #include "llchicletbar.h" -#include "lltoastpanel.h" +#include "llflatlistview.h" +#include "llfloaterreg.h" #include "llnotificationmanager.h" #include "llnotificationsutil.h" +#include "llscriptfloater.h" #include "llspeakers.h" -#include "lltoolbarview.h" +#include "lltoastpanel.h" //--------------------------------------------------------------------------------- LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLTransientDockableFloater(NULL, true, key), mChannel(NULL), mMessageList(NULL), - mSysWellChiclet(NULL), NOTIFICATION_WELL_ANCHOR_NAME("notification_well_panel"), IM_WELL_ANCHOR_NAME("im_well_panel"), mIsReshapedByUser(false) @@ -68,10 +56,6 @@ BOOL LLSysWellWindow::postBuild() // get a corresponding channel initChannel(); - // click on SysWell Window should clear "new message" state (and 'Lit' status). EXT-3147. - // mouse up callback is not called in this case. - setMouseDownCallback(boost::bind(&LLSysWellWindow::releaseNewMessagesState, this)); - return LLTransientDockableFloater::postBuild(); } @@ -95,14 +79,6 @@ void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask) setVisible(TRUE); } -void LLSysWellWindow::setSysWellChiclet(LLSysWellChiclet* chiclet) -{ - mSysWellChiclet = chiclet; - if(NULL != mSysWellChiclet) - { - mSysWellChiclet->updateWidget(isWindowEmpty()); - } -} //--------------------------------------------------------------------------------- LLSysWellWindow::~LLSysWellWindow() { @@ -113,10 +89,6 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id) { if(mMessageList->removeItemByValue(id)) { - if (NULL != mSysWellChiclet) - { - mSysWellChiclet->updateWidget(isWindowEmpty()); - } reshapeWindow(); } else @@ -170,11 +142,6 @@ void LLSysWellWindow::setVisible(BOOL visible) mChannel->updateShowToastsState(); mChannel->redrawToasts(); } - - if (visible) - { - releaseNewMessagesState(); - } } //--------------------------------------------------------------------------------- @@ -224,135 +191,12 @@ void LLSysWellWindow::reshapeWindow() } } -void LLSysWellWindow::releaseNewMessagesState() -{ - if (NULL != mSysWellChiclet) - { - mSysWellChiclet->setNewMessagesState(false); - } -} - //--------------------------------------------------------------------------------- bool LLSysWellWindow::isWindowEmpty() { return mMessageList->size() == 0; } -/************************************************************************/ -/* RowPanel implementation */ -/************************************************************************/ - -//--------------------------------------------------------------------------------- -LLIMWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId, - S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) : - LLPanel(LLPanel::Params()), mChiclet(NULL), mParent(parent) -{ - buildFromFile( "panel_activeim_row.xml"); - - // Choose which of the pre-created chiclets (IM/group) to use. - // The other one gets hidden. - - LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(sessionId); - switch (im_chiclet_type) - { - case LLIMChiclet::TYPE_GROUP: - mChiclet = getChild<LLIMGroupChiclet>("group_chiclet"); - break; - case LLIMChiclet::TYPE_AD_HOC: - mChiclet = getChild<LLAdHocChiclet>("adhoc_chiclet"); - break; - case LLIMChiclet::TYPE_UNKNOWN: // assign mChiclet a non-null value anyway - case LLIMChiclet::TYPE_IM: - mChiclet = getChild<LLIMP2PChiclet>("p2p_chiclet"); - break; - } - - // Initialize chiclet. - mChiclet->setChicletSizeChangedCallback(boost::bind(&LLIMWellWindow::RowPanel::onChicletSizeChanged, this, mChiclet, _2)); - mChiclet->enableCounterControl(true); - mChiclet->setCounter(chicletCounter); - mChiclet->setSessionId(sessionId); - mChiclet->setIMSessionName(name); - mChiclet->setOtherParticipantId(otherParticipantId); - mChiclet->setVisible(true); - - if (im_chiclet_type == LLIMChiclet::TYPE_IM) - { - LLAvatarNameCache::get(otherParticipantId, - boost::bind(&LLIMWellWindow::RowPanel::onAvatarNameCache, - this, _1, _2)); - } - else - { - LLTextBox* contactName = getChild<LLTextBox>("contact_name"); - contactName->setValue(name); - } - - mCloseBtn = getChild<LLButton>("hide_btn"); - mCloseBtn->setCommitCallback(boost::bind(&LLIMWellWindow::RowPanel::onClosePanel, this)); -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::RowPanel::onAvatarNameCache(const LLUUID& agent_id, - const LLAvatarName& av_name) -{ - LLTextBox* contactName = getChild<LLTextBox>("contact_name"); - contactName->setValue( av_name.getCompleteName() ); -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::RowPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param) -{ - LLTextBox* text = getChild<LLTextBox>("contact_name"); - S32 new_text_left = mChiclet->getRect().mRight + CHICLET_HPAD; - LLRect text_rect = text->getRect(); - text_rect.mLeft = new_text_left; - text->setShape(text_rect); -} - -//--------------------------------------------------------------------------------- -LLIMWellWindow::RowPanel::~RowPanel() -{ -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::RowPanel::onClosePanel() -{ - gIMMgr->leaveSession(mChiclet->getSessionId()); - // This row panel will be removed from the list in LLSysWellWindow::sessionRemoved(). -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::RowPanel::onMouseEnter(S32 x, S32 y, MASK mask) -{ - setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected")); -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::RowPanel::onMouseLeave(S32 x, S32 y, MASK mask) -{ - setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected")); -} - -//--------------------------------------------------------------------------------- -// virtual -BOOL LLIMWellWindow::RowPanel::handleMouseDown(S32 x, S32 y, MASK mask) -{ - // Pass the mouse down event to the chiclet (EXT-596). - if (!mChiclet->pointInView(x, y) && !mCloseBtn->getRect().pointInRect(x, y)) // prevent double call of LLIMChiclet::onMouseDown() - { - mChiclet->onMouseDown(); - return TRUE; - } - - return LLPanel::handleMouseDown(x, y, mask); -} - -// virtual -BOOL LLIMWellWindow::RowPanel::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - return mChiclet->handleRightMouseDown(x, y, mask); -} /************************************************************************/ /* ObjectRowPanel implementation */ /************************************************************************/ @@ -490,9 +334,7 @@ void LLNotificationWellWindow::addItem(LLSysWellItem::Params p) LLSysWellItem* new_item = new LLSysWellItem(p); if (mMessageList->addItem(new_item, value, ADD_TOP)) { - mSysWellChiclet->updateWidget(isWindowEmpty()); reshapeWindow(); - new_item->setOnItemCloseCallback(boost::bind(&LLNotificationWellWindow::onItemClose, this, _1)); new_item->setOnItemClickCallback(boost::bind(&LLNotificationWellWindow::onItemClick, this, _1)); } @@ -576,9 +418,6 @@ void LLNotificationWellWindow::onAdd( LLNotificationPtr notify ) removeItemByID(notify->getID()); } - - - /************************************************************************/ /* LLIMWellWindow implementation */ /************************************************************************/ @@ -588,12 +427,10 @@ void LLNotificationWellWindow::onAdd( LLNotificationPtr notify ) LLIMWellWindow::LLIMWellWindow(const LLSD& key) : LLSysWellWindow(key) { - LLIMMgr::getInstance()->addSessionObserver(this); } LLIMWellWindow::~LLIMWellWindow() { - LLIMMgr::getInstance()->removeSessionObserver(this); } // static @@ -614,47 +451,11 @@ BOOL LLIMWellWindow::postBuild() BOOL rv = LLSysWellWindow::postBuild(); setTitle(getString("title_im_well_window")); - LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findIMChiclet, this, _1)); LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findObjectChiclet, this, _1)); return rv; } -//virtual -void LLIMWellWindow::sessionAdded(const LLUUID& session_id, - const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) -{ - LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); - if (!session) return; - - // no need to spawn chiclets for participants in P2P calls called through Avaline - if (session->isP2P() && session->isOtherParticipantAvaline()) return; - - if (mMessageList->getItemByValue(session_id)) return; - - addIMRow(session_id, 0, name, other_participant_id); - reshapeWindow(); -} - -//virtual -void LLIMWellWindow::sessionRemoved(const LLUUID& sessionId) -{ - delIMRow(sessionId); - reshapeWindow(); -} - -//virtual -void LLIMWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) -{ - //for outgoing ad-hoc and group im sessions only - LLChiclet* chiclet = findIMChiclet(old_session_id); - if (chiclet) - { - chiclet->setSessionId(new_session_id); - mMessageList->updateValue(old_session_id, new_session_id); - } -} - LLChiclet* LLIMWellWindow::findObjectChiclet(const LLUUID& notification_id) { if (!mMessageList) return NULL; @@ -671,66 +472,6 @@ LLChiclet* LLIMWellWindow::findObjectChiclet(const LLUUID& notification_id) ////////////////////////////////////////////////////////////////////////// // PRIVATE METHODS -LLChiclet* LLIMWellWindow::findIMChiclet(const LLUUID& sessionId) -{ - if (!mMessageList) return NULL; - - LLChiclet* res = NULL; - RowPanel* panel = mMessageList->getTypedItemByValue<RowPanel>(sessionId); - if (panel != NULL) - { - res = panel->mChiclet; - } - - return res; -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter, - const std::string& name, const LLUUID& otherParticipantId) -{ - RowPanel* item = new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId); - if (!mMessageList->addItem(item, sessionId)) - { - llwarns << "Unable to add IM Row into the list, sessionID: " << sessionId - << ", name: " << name - << ", other participant ID: " << otherParticipantId - << llendl; - - item->die(); - } -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::delIMRow(const LLUUID& sessionId) -{ - //fix for EXT-3252 - //without this line LLIMWellWindow receive onFocusLost - //and hide itself. It was becaue somehow LLIMChicklet was in focus group for - //LLIMWellWindow... - //But I didn't find why this happen.. - gFocusMgr.clearLastFocusForGroup(this); - - if (!mMessageList->removeItemByValue(sessionId)) - { - llwarns << "Unable to remove IM Row from the list, sessionID: " << sessionId - << llendl; - } - - // remove all toasts that belong to this session from a screen - if(mChannel) - mChannel->removeToastsBySessionID(sessionId); - - // hide chiclet window if there are no items left - if(isWindowEmpty()) - { - setVisible(FALSE); - } - else - { - setFocus(true); - } -} void LLIMWellWindow::addObjectRow(const LLUUID& notification_id, bool new_message/* = false*/) { @@ -761,21 +502,6 @@ void LLIMWellWindow::removeObjectRow(const LLUUID& notification_id) } } - -void LLIMWellWindow::addIMRow(const LLUUID& session_id) -{ - if (hasIMRow(session_id)) return; - - LLIMModel* im_model = LLIMModel::getInstance(); - addIMRow(session_id, 0, im_model->getName(session_id), im_model->getOtherParticipantID(session_id)); - reshapeWindow(); -} - -bool LLIMWellWindow::hasIMRow(const LLUUID& session_id) -{ - return mMessageList->getItemByValue(session_id); -} - void LLIMWellWindow::closeAll() { // Generate an ignorable alert dialog if there is an active voice IM sesion @@ -820,13 +546,6 @@ void LLIMWellWindow::closeAllImpl() { LLPanel* panel = mMessageList->getItemByValue(*iter); - RowPanel* im_panel = dynamic_cast <RowPanel*> (panel); - if (im_panel) - { - gIMMgr->leaveSession(*iter); - continue; - } - ObjectRowPanel* obj_panel = dynamic_cast <ObjectRowPanel*> (panel); if (obj_panel) { diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index d6480f1fc6..406ab1b59e 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -27,32 +27,26 @@ #ifndef LL_LLSYSWELLWINDOW_H #define LL_LLSYSWELLWINDOW_H -#include "llsyswellitem.h" - -#include "lltransientdockablefloater.h" -#include "llbutton.h" -#include "llscreenchannel.h" -#include "llscrollcontainer.h" #include "llimview.h" #include "llnotifications.h" - -#include "boost/shared_ptr.hpp" +#include "llscreenchannel.h" +#include "llsyswellitem.h" +#include "lltransientdockablefloater.h" class LLAvatarName; -class LLFlatListView; class LLChiclet; +class LLFlatListView; class LLIMChiclet; class LLScriptChiclet; class LLSysWellChiclet; - class LLSysWellWindow : public LLTransientDockableFloater { public: LOG_CLASS(LLSysWellWindow); LLSysWellWindow(const LLSD& key); - ~LLSysWellWindow(); + virtual ~LLSysWellWindow(); BOOL postBuild(); // other interface functions @@ -72,8 +66,6 @@ public: void onStartUpToastClick(S32 x, S32 y, MASK mask); - void setSysWellChiclet(LLSysWellChiclet* chiclet); - // size constants for the window and for its elements static const S32 MAX_WINDOW_HEIGHT = 200; static const S32 MIN_WINDOW_WIDTH = 318; @@ -87,17 +79,11 @@ protected: virtual const std::string& getAnchorViewName() = 0; void reshapeWindow(); - void releaseNewMessagesState(); // pointer to a corresponding channel's instance LLNotificationsUI::LLScreenChannel* mChannel; LLFlatListView* mMessageList; - /** - * Reference to an appropriate Well chiclet to release "new message" state. EXT-3147 - */ - LLSysWellChiclet* mSysWellChiclet; - bool mIsReshapedByUser; }; @@ -157,7 +143,7 @@ private: * * It contains a list list of all active IM sessions. */ -class LLIMWellWindow : public LLSysWellWindow, LLIMSessionObserver, LLInitClass<LLIMWellWindow> +class LLIMWellWindow : public LLSysWellWindow, LLInitClass<LLIMWellWindow> { public: LLIMWellWindow(const LLSD& key); @@ -169,59 +155,19 @@ public: /*virtual*/ BOOL postBuild(); - // LLIMSessionObserver observe triggers - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); - /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} - /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; - /*virtual*/ void sessionRemoved(const LLUUID& session_id); - /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); - void addObjectRow(const LLUUID& notification_id, bool new_message = false); void removeObjectRow(const LLUUID& notification_id); - - void addIMRow(const LLUUID& session_id); - bool hasIMRow(const LLUUID& session_id); - void closeAll(); protected: /*virtual*/ const std::string& getAnchorViewName() { return IM_WELL_ANCHOR_NAME; } private: - LLChiclet * findIMChiclet(const LLUUID& sessionId); LLChiclet* findObjectChiclet(const LLUUID& notification_id); - void addIMRow(const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId); - void delIMRow(const LLUUID& sessionId); bool confirmCloseAll(const LLSD& notification, const LLSD& response); void closeAllImpl(); - /** - * Scrolling row panel. - */ - class RowPanel: public LLPanel - { - public: - RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId, S32 chicletCounter, - const std::string& name, const LLUUID& otherParticipantId); - virtual ~RowPanel(); - void onMouseEnter(S32 x, S32 y, MASK mask); - void onMouseLeave(S32 x, S32 y, MASK mask); - BOOL handleMouseDown(S32 x, S32 y, MASK mask); - BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - - private: - static const S32 CHICLET_HPAD = 10; - void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); - void onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param); - void onClosePanel(); - public: - LLIMChiclet* mChiclet; - private: - LLButton* mCloseBtn; - const LLSysWellWindow* mParent; - }; - class ObjectRowPanel: public LLPanel { public: diff --git a/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png b/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png deleted file mode 100644 index 0ac5b72b8f..0000000000 Binary files a/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1_Dark.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1_Dark.png deleted file mode 100644 index 857fa1e047..0000000000 Binary files a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1_Dark.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2_Dark.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2_Dark.png deleted file mode 100644 index 453bb53673..0000000000 Binary files a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2_Dark.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl3_Dark.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl3_Dark.png deleted file mode 100644 index 135a66ca0d..0000000000 Binary files a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl3_Dark.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Off_Dark.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Off_Dark.png deleted file mode 100644 index a63aec5e6d..0000000000 Binary files a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Off_Dark.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_On_Dark.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_On_Dark.png deleted file mode 100644 index 1719eb3e84..0000000000 Binary files a/indra/newview/skins/default/textures/bottomtray/VoicePTT_On_Dark.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 8d9fa52309..bf6e933dfd 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -365,8 +365,6 @@ with the same filename but different name <texture name="Nearby_chat_icon" file_name="icons/nearby_chat_icon.png" preload="false" /> - <texture name="Notices_Unread" file_name="bottomtray/Notices_Unread.png" preload="true" /> - <texture name="NoEntryLines" file_name="world/NoEntryLines.png" use_mips="true" preload="false" /> <texture name="NoEntryPassLines" file_name="world/NoEntryPassLines.png" use_mips="true" preload="false" /> @@ -654,12 +652,6 @@ with the same filename but different name <texture name="VoicePTT_Off" file_name="bottomtray/VoicePTT_Off.png" preload="false" /> <texture name="VoicePTT_On" file_name="bottomtray/VoicePTT_On.png" preload="false" /> - <texture name="VoicePTT_Lvl1_Dark" file_name="bottomtray/VoicePTT_Lvl1_Dark.png" preload="false" /> - <texture name="VoicePTT_Lvl2_Dark" file_name="bottomtray/VoicePTT_Lvl2_Dark.png" preload="false" /> - <texture name="VoicePTT_Lvl3_Dark" file_name="bottomtray/VoicePTT_Lvl3_Dark.png" preload="false" /> - <texture name="VoicePTT_Off_Dark" file_name="bottomtray/VoicePTT_Off_Dark.png" preload="false" /> - <texture name="VoicePTT_On_Dark" file_name="bottomtray/VoicePTT_On_Dark.png" preload="false" /> - <texture name="Wearables_Divider" file_name="windows/Wearables_Divider.png" preload="false" /> <texture name="Web_Profile_Off" file_name="icons/Web_Profile_Off.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/da/menu_im_well_button.xml b/indra/newview/skins/default/xui/da/menu_im_well_button.xml deleted file mode 100644 index 4889230919..0000000000 --- a/indra/newview/skins/default/xui/da/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="IM Well Button Context Menu"> - <menu_item_call label="Luk alle" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/da/menu_notification_well_button.xml b/indra/newview/skins/default/xui/da/menu_notification_well_button.xml deleted file mode 100644 index 40b35b5fdd..0000000000 --- a/indra/newview/skins/default/xui/da/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Notification Well Button Context Menu"> - <menu_item_call label="Luk alle" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/de/menu_im_well_button.xml b/indra/newview/skins/default/xui/de/menu_im_well_button.xml deleted file mode 100644 index f464b71f4a..0000000000 --- a/indra/newview/skins/default/xui/de/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="IM Well Button Context Menu"> - <menu_item_call label="Alle schließen" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/de/menu_notification_well_button.xml b/indra/newview/skins/default/xui/de/menu_notification_well_button.xml deleted file mode 100644 index 0f2784f160..0000000000 --- a/indra/newview/skins/default/xui/de/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Notification Well Button Context Menu"> - <menu_item_call label="Alle schließen" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_notification_well_button.xml b/indra/newview/skins/default/xui/en/menu_notification_well_button.xml deleted file mode 100644 index 263ac40f4e..0000000000 --- a/indra/newview/skins/default/xui/en/menu_notification_well_button.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<context_menu - layout="topleft" - name="Notification Well Button Context Menu"> - <menu_item_call - label="Close All" - layout="topleft" - name="Close All"> - <menu_item_call.on_click - function="NotificationWellChicletMenu.Action" - parameter="close all" /> - <menu_item_call.on_enable - function="NotificationWellChicletMenu.EnableItem" - parameter="can close all" /> - </menu_item_call> -</context_menu> diff --git a/indra/newview/skins/default/xui/en/panel_activeim_row.xml b/indra/newview/skins/default/xui/en/panel_activeim_row.xml deleted file mode 100644 index 9369d1b5cf..0000000000 --- a/indra/newview/skins/default/xui/en/panel_activeim_row.xml +++ /dev/null @@ -1,97 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - name="panel_activeim_row" - layout="topleft" - follows="left|right" - top="0" - left="0" - height="35" - width="318" - background_opaque="false" - background_visible="true" - bg_alpha_color="0.0 0.0 0.0 0.0" > - <chiclet_im_p2p - name="p2p_chiclet" - layout="topleft" - follows="left" - top="3" - left="5" - height="25" - width="25" - visible="false" - speaker.name="speaker_p2p" - speaker.width="20" - speaker.height="25" - speaker.left="25" - speaker.top="25" - speaker.auto_update="true" - speaker.draw_border="false" - speaker.visible="false"> - </chiclet_im_p2p> - <chiclet_im_group - name="group_chiclet" - layout="topleft" - follows="left" - top="3" - left="5" - height="25" - width="25" - visible="false" - speaker.name="speaker_grp" - speaker.width="20" - speaker.height="25" - speaker.left="25" - speaker.top="25" - speaker.auto_update="true" - speaker.draw_border="false" - speaker.visible="false"> - </chiclet_im_group> - <chiclet_im_adhoc - name="adhoc_chiclet" - layout="topleft" - follows="left" - top="3" - left="5" - height="25" - width="25" - visible="false" - speaker.name="speaker_hoc" - speaker.width="20" - speaker.height="25" - speaker.left="25" - speaker.top="25" - speaker.auto_update="true" - speaker.draw_border="false" - speaker.visible="false"> - </chiclet_im_adhoc> - <text - translate="false" - type="string" - name="contact_name" - layout="topleft" - top="10" - left_pad="10" - height="14" - width="250" - length="1" - follows="right|left" - parse_urls="false" - use_ellipses="true" - font="SansSerifBold"> - TestString PleaseIgnore - </text> - <button - top="10" - right="-5" - width="17" - height="17" - layout="topleft" - follows="right" - name="hide_btn" - mouse_opaque="true" - label="" - tab_stop="false" - image_unselected="Toast_CloseBtn" - image_selected="Toast_CloseBtn" - /> -</panel> \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml index fc321fdd23..390047d493 100644 --- a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml @@ -77,49 +77,5 @@ width="12" /> </chiclet_panel> </layout_panel> - <layout_panel auto_resize="false" - width="4" - min_width="4"/> - <layout_panel - auto_resize="false" - follows="right" - height="28" - layout="topleft" - min_height="28" - min_width="37" - name="notification_well_panel" - top="0" - width="37"> - <chiclet_notification - follows="right" - height="23" - layout="topleft" - left="0" - max_displayed_count="99" - name="notification_well" - top="5" - width="35"> - <button - auto_resize="false" - bottom_pad="3" - follows="right" - halign="center" - height="23" - image_overlay="Notices_Unread" - image_overlay_alignment="center" - image_pressed="WellButton_Lit" - image_pressed_selected="WellButton_Lit_Selected" - image_selected="PushButton_Press" - label_color="Black" - left="0" - name="Unread" - tool_tip="Notifications" - width="34"> - <init_callback - function="Button.SetDockableFloaterToggle" - parameter="notification_well_window" /> - </button> - </chiclet_notification> - </layout_panel> </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml deleted file mode 100644 index 0e29ed0d0b..0000000000 --- a/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml +++ /dev/null @@ -1,55 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<chiclet_im_adhoc - height="23" - name="im_adhoc_chiclet" - show_speaker="false" - width="25"> - <chiclet_im_adhoc.chiclet_button - height="25" - image_selected="PushButton_On" - image_unselected="PushButton_Off" - name="chiclet_button" - tab_stop="false" - width="25" /> - <chiclet_im_adhoc.speaker - image_mute="Parcel_VoiceNo_Light" - image_off="VoicePTT_Off_Dark" - image_on="VoicePTT_On_Dark" - image_level_1="VoicePTT_Lvl1_Dark" - image_level_2="VoicePTT_Lvl2_Dark" - image_level_3="VoicePTT_Lvl3_Dark" - auto_update="true" - draw_border="false" - height="24" - left="25" - bottom="1" - name="speaker" - visible="false" - width="20" /> - <chiclet_im_adhoc.avatar_icon - bottom="3" - follows="left|top|bottom" - height="20" - left="2" - mouse_opaque="false" - name="adhoc_icon" - width="21" /> - <chiclet_im_adhoc.unread_notifications - halign="center" - height="23" - left="25" - mouse_opaque="false" - name="unread" - text_color="white" - v_pad="3" - visible="false" - width="20" /> - <chiclet_im_adhoc.new_message_icon - bottom="11" - height="14" - image_name="Unread_Chiclet" - left="12" - name="new_message_icon" - visible="false" - width="14" /> -</chiclet_im_adhoc> \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml deleted file mode 100644 index 77011139bf..0000000000 --- a/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml +++ /dev/null @@ -1,56 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<chiclet_im_group - height="23" - name="im_group_chiclet" - show_speaker="false" - width="25"> - <chiclet_im_group.chiclet_button - height="25" - image_selected="PushButton_On" - image_unselected="PushButton_Off" - name="chiclet_button" - tab_stop="false" - width="25" /> - <chiclet_im_group.speaker - image_mute="Parcel_VoiceNo_Light" - image_off="VoicePTT_Off_Dark" - image_on="VoicePTT_On_Dark" - image_level_1="VoicePTT_Lvl1_Dark" - image_level_2="VoicePTT_Lvl2_Dark" - image_level_3="VoicePTT_Lvl3_Dark" - auto_update="true" - draw_border="false" - height="24" - left="25" - bottom="1" - name="speaker" - visible="false" - width="20" /> - <chiclet_im_group.group_icon - bottom="3" - default_icon="Generic_Group" - follows="left|top|bottom" - height="20" - left="2" - mouse_opaque="false" - name="group_icon" - width="21" /> - <chiclet_im_group.unread_notifications - height="23" - halign="center" - left="25" - mouse_opaque="false" - name="unread" - text_color="white" - v_pad="3" - visible="false" - width="20"/> - <chiclet_im_group.new_message_icon -bottom="11" - height="14" - image_name="Unread_Chiclet" - left="12" - name="new_message_icon" - visible="false" - width="14" /> -</chiclet_im_group> \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml deleted file mode 100644 index 8b56a8f0f6..0000000000 --- a/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml +++ /dev/null @@ -1,56 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<chiclet_im_p2p - height="23" - name="im_p2p_chiclet" - show_speaker="false" - width="25"> - <chiclet_im_p2p.chiclet_button - height="25" - image_selected="PushButton_On" - image_unselected="PushButton_Off" - name="chiclet_button" - tab_stop="false" - width="25"/> - <chiclet_im_p2p.speaker - image_mute="Parcel_VoiceNo_Light" - image_off="VoicePTT_Off_Dark" - image_on="VoicePTT_On_Dark" - image_level_1="VoicePTT_Lvl1_Dark" - image_level_2="VoicePTT_Lvl2_Dark" - image_level_3="VoicePTT_Lvl3_Dark" - auto_update="true" - draw_border="false" - height="24" - left="25" - bottom="1" - name="speaker" - visible="false" - width="20" /> - <chiclet_im_p2p.avatar_icon - bottom="3" - color="white" - follows="left|top|bottom" - height="20" - left="2" - mouse_opaque="false" - name="avatar_icon" - width="21" /> - <chiclet_im_p2p.unread_notifications - height="23" - halign="center" - left="25" - mouse_opaque="false" - name="unread" - text_color="white" - v_pad="3" - visible="false" - width="20"/> - <chiclet_im_p2p.new_message_icon - bottom="11" - height="14" - image_name="Unread_Chiclet" - left="12" - name="new_message_icon" - visible="false" - width="14" /> -</chiclet_im_p2p> diff --git a/indra/newview/skins/default/xui/es/menu_im_well_button.xml b/indra/newview/skins/default/xui/es/menu_im_well_button.xml deleted file mode 100644 index c8f6c217cc..0000000000 --- a/indra/newview/skins/default/xui/es/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="IM Well Button Context Menu"> - <menu_item_call label="Cerrar todo" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/es/menu_notification_well_button.xml b/indra/newview/skins/default/xui/es/menu_notification_well_button.xml deleted file mode 100644 index 0562d35be7..0000000000 --- a/indra/newview/skins/default/xui/es/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Notification Well Button Context Menu"> - <menu_item_call label="Cerrar todo" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/fr/menu_im_well_button.xml b/indra/newview/skins/default/xui/fr/menu_im_well_button.xml deleted file mode 100644 index 8ef1529e6b..0000000000 --- a/indra/newview/skins/default/xui/fr/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="IM Well Button Context Menu"> - <menu_item_call label="Tout fermer" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/fr/menu_notification_well_button.xml b/indra/newview/skins/default/xui/fr/menu_notification_well_button.xml deleted file mode 100644 index 323bfdbf16..0000000000 --- a/indra/newview/skins/default/xui/fr/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Notification Well Button Context Menu"> - <menu_item_call label="Tout fermer" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/it/menu_im_well_button.xml b/indra/newview/skins/default/xui/it/menu_im_well_button.xml deleted file mode 100644 index 9e471b771c..0000000000 --- a/indra/newview/skins/default/xui/it/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="IM Well Button Context Menu"> - <menu_item_call label="Chiudi tutto" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/it/menu_notification_well_button.xml b/indra/newview/skins/default/xui/it/menu_notification_well_button.xml deleted file mode 100644 index 8c82e30f0e..0000000000 --- a/indra/newview/skins/default/xui/it/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Notification Well Button Context Menu"> - <menu_item_call label="Chiudi tutto" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/ja/menu_im_well_button.xml b/indra/newview/skins/default/xui/ja/menu_im_well_button.xml deleted file mode 100644 index 3397004bd7..0000000000 --- a/indra/newview/skins/default/xui/ja/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="IM Well Button Context Menu"> - <menu_item_call label="すべて閉じる" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/ja/menu_notification_well_button.xml b/indra/newview/skins/default/xui/ja/menu_notification_well_button.xml deleted file mode 100644 index 913bae8958..0000000000 --- a/indra/newview/skins/default/xui/ja/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Notification Well Button Context Menu"> - <menu_item_call label="すべて閉じる" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/pl/menu_im_well_button.xml b/indra/newview/skins/default/xui/pl/menu_im_well_button.xml deleted file mode 100644 index 207bc2211b..0000000000 --- a/indra/newview/skins/default/xui/pl/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="IM Well Button Context Menu"> - <menu_item_call label="Zamknij wszystkie" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/pl/menu_notification_well_button.xml b/indra/newview/skins/default/xui/pl/menu_notification_well_button.xml deleted file mode 100644 index bd3d42f9b1..0000000000 --- a/indra/newview/skins/default/xui/pl/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Notification Well Button Context Menu"> - <menu_item_call label="Zamknij" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/pt/menu_im_well_button.xml b/indra/newview/skins/default/xui/pt/menu_im_well_button.xml deleted file mode 100644 index 2d37cefd6f..0000000000 --- a/indra/newview/skins/default/xui/pt/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="IM Well Button Context Menu"> - <menu_item_call label="Fechar tudo" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/pt/menu_notification_well_button.xml b/indra/newview/skins/default/xui/pt/menu_notification_well_button.xml deleted file mode 100644 index 43ad4134ec..0000000000 --- a/indra/newview/skins/default/xui/pt/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Notification Well Button Context Menu"> - <menu_item_call label="Fechar tudo" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/ru/menu_im_well_button.xml b/indra/newview/skins/default/xui/ru/menu_im_well_button.xml deleted file mode 100644 index 5a5bde61b9..0000000000 --- a/indra/newview/skins/default/xui/ru/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="IM Well Button Context Menu"> - <menu_item_call label="Закрыть все" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/ru/menu_notification_well_button.xml b/indra/newview/skins/default/xui/ru/menu_notification_well_button.xml deleted file mode 100644 index 4d067e232a..0000000000 --- a/indra/newview/skins/default/xui/ru/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Notification Well Button Context Menu"> - <menu_item_call label="Закрыть все" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/tr/menu_im_well_button.xml b/indra/newview/skins/default/xui/tr/menu_im_well_button.xml deleted file mode 100644 index c3e559a723..0000000000 --- a/indra/newview/skins/default/xui/tr/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="IM Well Button Context Menu"> - <menu_item_call label="Tümünü Kapat" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/tr/menu_notification_well_button.xml b/indra/newview/skins/default/xui/tr/menu_notification_well_button.xml deleted file mode 100644 index 39c66268f5..0000000000 --- a/indra/newview/skins/default/xui/tr/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Notification Well Button Context Menu"> - <menu_item_call label="Tümünü Kapat" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_im_well_button.xml b/indra/newview/skins/default/xui/zh/menu_im_well_button.xml deleted file mode 100644 index 4b9b4b2758..0000000000 --- a/indra/newview/skins/default/xui/zh/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="IM Well Button Context Menu"> - <menu_item_call label="全部關閉" name="Close All"/> -</context_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_notification_well_button.xml b/indra/newview/skins/default/xui/zh/menu_notification_well_button.xml deleted file mode 100644 index b629f73584..0000000000 --- a/indra/newview/skins/default/xui/zh/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Notification Well Button Context Menu"> - <menu_item_call label="全部關閉" name="Close All"/> -</context_menu> -- cgit v1.2.3 From 60c72c85e2360284ecc3326871dcc76fcce0e945 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Mon, 3 Dec 2012 19:06:52 -0800 Subject: Cleaning up some unreferenced member variables and related types from LLNotifications. --- indra/llui/CMakeLists.txt | 2 - indra/llui/llnotifications.cpp | 3 - indra/llui/llnotifications.h | 4 - indra/llui/llnotificationslistener.cpp | 354 --------------------------------- indra/llui/llnotificationslistener.h | 69 ------- indra/llui/llnotificationtemplate.h | 1 - 6 files changed, 433 deletions(-) delete mode 100644 indra/llui/llnotificationslistener.cpp delete mode 100644 indra/llui/llnotificationslistener.h (limited to 'indra') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index ccc7aa8cec..9c961d67d6 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -71,7 +71,6 @@ set(llui_SOURCE_FILES llmultislider.cpp llmultisliderctrl.cpp llnotifications.cpp - llnotificationslistener.cpp llnotificationsutil.cpp llpanel.cpp llprogressbar.cpp @@ -181,7 +180,6 @@ set(llui_HEADER_FILES llmultislider.h llnotificationptr.h llnotifications.h - llnotificationslistener.h llnotificationsutil.h llnotificationtemplate.h llnotificationvisibilityrule.h diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 66144671c9..61d5dcf12c 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -39,7 +39,6 @@ #include "lldir.h" #include "llsdserialize.h" #include "lltrans.h" -#include "llnotificationslistener.h" #include "llstring.h" #include "llsdparam.h" #include "llsdutil.h" @@ -1167,8 +1166,6 @@ LLNotifications::LLNotifications() mIgnoreAllNotifications(false) { LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2)); - - mListener.reset(new LLNotificationsListener(*this)); } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 088931858a..a41e9fa5a3 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -92,7 +92,6 @@ #include "llevents.h" #include "llfunctorregistry.h" #include "llinitparam.h" -#include "llnotificationslistener.h" #include "llnotificationptr.h" #include "llpointer.h" #include "llrefcount.h" @@ -672,7 +671,6 @@ namespace LLNotificationComparators }; typedef boost::function<bool (LLNotificationPtr)> LLNotificationFilter; -typedef boost::function<bool (LLNotificationPtr, LLNotificationPtr)> LLNotificationComparator; typedef std::set<LLNotificationPtr, LLNotificationComparators::orderByUUID> LLNotificationSet; typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap; @@ -822,7 +820,6 @@ public: private: std::string mName; std::string mParent; - LLNotificationComparator mComparator; }; // An interface class to provide a clean linker seam to the LLNotifications class. @@ -942,7 +939,6 @@ private: bool mIgnoreAllNotifications; - boost::scoped_ptr<LLNotificationsListener> mListener; std::vector<LLNotificationChannelPtr> mDefaultChannels; }; diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp deleted file mode 100644 index e4e127336b..0000000000 --- a/indra/llui/llnotificationslistener.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/** - * @file llnotificationslistener.cpp - * @author Brad Kittenbrink - * @date 2009-07-08 - * @brief Implementation for llnotificationslistener. - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llnotificationslistener.h" -#include "llnotifications.h" -#include "llnotificationtemplate.h" -#include "llsd.h" -#include "llui.h" - -LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) : - LLEventAPI("LLNotifications", - "LLNotifications listener to (e.g.) pop up a notification"), - mNotifications(notifications) -{ - add("requestAdd", - "Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n" - "If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.", - &LLNotificationsListener::requestAdd); - add("listChannels", - "Post to [\"reply\"] a map of info on existing channels", - &LLNotificationsListener::listChannels, - LLSD().with("reply", LLSD())); - add("listChannelNotifications", - "Post to [\"reply\"] an array of info on notifications in channel [\"channel\"]", - &LLNotificationsListener::listChannelNotifications, - LLSD().with("reply", LLSD()).with("channel", LLSD())); - add("respond", - "Respond to notification [\"uuid\"] with data in [\"response\"]", - &LLNotificationsListener::respond, - LLSD().with("uuid", LLSD())); - add("cancel", - "Cancel notification [\"uuid\"]", - &LLNotificationsListener::cancel, - LLSD().with("uuid", LLSD())); - add("ignore", - "Ignore future notification [\"name\"]\n" - "(from <notification name= > in notifications.xml)\n" - "according to boolean [\"ignore\"].\n" - "If [\"name\"] is omitted or undefined, [un]ignore all future notifications.\n" - "Note that ignored notifications are not forwarded unless intercepted before\n" - "the \"Ignore\" channel.", - &LLNotificationsListener::ignore); - add("forward", - "Forward to [\"pump\"] future notifications on channel [\"channel\"]\n" - "according to boolean [\"forward\"]. When enabled, only types matching\n" - "[\"types\"] are forwarded, as follows:\n" - "omitted or undefined: forward all notifications\n" - "string: forward only the specific named [sig]type\n" - "array of string: forward any notification matching any named [sig]type.\n" - "When boolean [\"respond\"] is true, we auto-respond to each forwarded\n" - "notification.", - &LLNotificationsListener::forward, - LLSD().with("channel", LLSD())); -} - -// This is here in the .cpp file so we don't need the definition of class -// Forwarder in the header file. -LLNotificationsListener::~LLNotificationsListener() -{ -} - -void LLNotificationsListener::requestAdd(const LLSD& event_data) const -{ - if(event_data.has("reply")) - { - mNotifications.add(event_data["name"], - event_data["substitutions"], - event_data["payload"], - boost::bind(&LLNotificationsListener::NotificationResponder, - this, - event_data["reply"].asString(), - _1, _2 - ) - ); - } - else - { - mNotifications.add(event_data["name"], - event_data["substitutions"], - event_data["payload"]); - } -} - -void LLNotificationsListener::NotificationResponder(const std::string& reply_pump, - const LLSD& notification, - const LLSD& response) const -{ - LLSD reponse_event; - reponse_event["notification"] = notification; - reponse_event["response"] = response; - LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event); -} - -void LLNotificationsListener::listChannels(const LLSD& params) const -{ - LLReqID reqID(params); - LLSD response(reqID.makeResponse()); - for (LLNotificationChannel::instance_iter cmi(LLNotificationChannel::beginInstances()), - cmend(LLNotificationChannel::endInstances()); - cmi != cmend; ++cmi) - { - LLSD channelInfo; - //channelInfo["parent"] = cmi->second->getParentChannelName(); - response[cmi->getName()] = channelInfo; - } - LLEventPumps::instance().obtain(params["reply"]).post(response); -} - -void LLNotificationsListener::listChannelNotifications(const LLSD& params) const -{ - LLReqID reqID(params); - LLSD response(reqID.makeResponse()); - LLNotificationChannelPtr channel(mNotifications.getChannel(params["channel"])); - if (channel) - { - LLSD notifications(LLSD::emptyArray()); - for (LLNotificationChannel::Iterator ni(channel->begin()), nend(channel->end()); - ni != nend; ++ni) - { - notifications.append(asLLSD(*ni)); - } - response["notifications"] = notifications; - } - LLEventPumps::instance().obtain(params["reply"]).post(response); -} - -void LLNotificationsListener::respond(const LLSD& params) const -{ - LLNotificationPtr notification(mNotifications.find(params["uuid"])); - if (notification) - { - notification->respond(params["response"]); - } -} - -void LLNotificationsListener::cancel(const LLSD& params) const -{ - LLNotificationPtr notification(mNotifications.find(params["uuid"])); - if (notification) - { - mNotifications.cancel(notification); - } -} - -void LLNotificationsListener::ignore(const LLSD& params) const -{ - // Calling a method named "ignore", but omitting its "ignore" Boolean - // argument, should by default cause something to be ignored. Explicitly - // pass ["ignore"] = false to cancel ignore. - bool ignore = true; - if (params.has("ignore")) - { - ignore = params["ignore"].asBoolean(); - } - // This method can be used to affect either a single notification name or - // all future notifications. The two use substantially different mechanisms. - if (params["name"].isDefined()) - { - // ["name"] was passed: ignore just that notification - LLNotificationTemplatePtr templatep = mNotifications.getTemplate(params["name"]); - if (templatep) - { - templatep->mForm->setIgnored(ignore); - } - } - else - { - // no ["name"]: ignore all future notifications - mNotifications.setIgnoreAllNotifications(ignore); - } -} - -class LLNotificationsListener::Forwarder: public LLEventTrackable -{ - LOG_CLASS(LLNotificationsListener::Forwarder); -public: - Forwarder(LLNotifications& llnotifications, const std::string& channel): - mNotifications(llnotifications), - mRespond(false) - { - // Connect to the specified channel on construction. Because - // LLEventTrackable is a base, we should automatically disconnect when - // destroyed. - LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel)); - if (channelptr) - { - // Insert our processing as a "passed filter" listener. This way - // we get to run before all the "changed" listeners, and we get to - // swipe it (hide it from the other listeners) if desired. - channelptr->connectPassedFilter(boost::bind(&Forwarder::handle, this, _1)); - } - } - - void setPumpName(const std::string& name) { mPumpName = name; } - void setTypes(const LLSD& types) { mTypes = types; } - void setRespond(bool respond) { mRespond = respond; } - -private: - bool handle(const LLSD& notification) const; - bool matchType(const LLSD& filter, const std::string& type) const; - - LLNotifications& mNotifications; - std::string mPumpName; - LLSD mTypes; - bool mRespond; -}; - -void LLNotificationsListener::forward(const LLSD& params) -{ - std::string channel(params["channel"]); - // First decide whether we're supposed to start forwarding or stop it. - // Default to true. - bool forward = true; - if (params.has("forward")) - { - forward = params["forward"].asBoolean(); - } - if (! forward) - { - // This is a request to stop forwarding notifications on the specified - // channel. The rest of the params don't matter. - // Because mForwarders contains scoped_ptrs, erasing the map entry - // DOES delete the heap Forwarder object. Because Forwarder derives - // from LLEventTrackable, destroying it disconnects it from the - // channel. - mForwarders.erase(channel); - return; - } - // From here on, we know we're being asked to start (or modify) forwarding - // on the specified channel. Find or create an appropriate Forwarder. - ForwarderMap::iterator - entry(mForwarders.insert(ForwarderMap::value_type(channel, ForwarderMap::mapped_type())).first); - if (! entry->second) - { - entry->second.reset(new Forwarder(mNotifications, channel)); - } - // Now, whether this Forwarder is brand-new or not, update it with the new - // request info. - Forwarder& fwd(*entry->second); - fwd.setPumpName(params["pump"]); - fwd.setTypes(params["types"]); - fwd.setRespond(params["respond"]); -} - -bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const -{ - LL_INFOS("LLNotificationsListener") << "handle(" << notification << ")" << LL_ENDL; - if (notification["sigtype"].asString() == "delete") - { - LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL; - // let other listeners see the "delete" operation - return false; - } - LLNotificationPtr note(mNotifications.find(notification["id"])); - if (! note) - { - LL_INFOS("LLNotificationsListener") << notification["id"] << " not found" << LL_ENDL; - return false; - } - if (! matchType(mTypes, note->getType())) - { - LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL; - // We're not supposed to intercept this particular notification. Let - // other listeners process it. - return false; - } - LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL; - // This is a notification we care about. Forward it through specified - // LLEventPump. - LLEventPumps::instance().obtain(mPumpName).post(asLLSD(note)); - // Are we also being asked to auto-respond? - if (mRespond) - { - LL_INFOS("LLNotificationsListener") << "should respond" << LL_ENDL; - note->respond(LLSD::emptyMap()); - // Did that succeed in removing the notification? Only cancel() if - // it's still around -- otherwise we get an LL_ERRS crash! - note = mNotifications.find(notification["id"]); - if (note) - { - LL_INFOS("LLNotificationsListener") << "respond() didn't clear, canceling" << LL_ENDL; - mNotifications.cancel(note); - } - } - // If we've auto-responded to this notification, then it's going to be - // deleted. Other listeners would get the change operation, try to look it - // up and be baffled by lookup failure. So when we auto-respond, suppress - // this notification: don't pass it to other listeners. - return mRespond; -} - -bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const -{ - // Decide whether this notification matches filter: - // undefined: forward all notifications - if (filter.isUndefined()) - { - return true; - } - // array of string: forward any notification matching any named type - if (filter.isArray()) - { - for (LLSD::array_const_iterator ti(filter.beginArray()), tend(filter.endArray()); - ti != tend; ++ti) - { - if (ti->asString() == type) - { - return true; - } - } - // Didn't match any entry in the array - return false; - } - // string: forward only the specific named type - return (filter.asString() == type); -} - -LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note) -{ - LLSD notificationInfo(note->asLLSD()); - // For some reason the following aren't included in LLNotification::asLLSD(). - notificationInfo["summary"] = note->summarize(); - notificationInfo["id"] = note->id(); - notificationInfo["type"] = note->getType(); - notificationInfo["message"] = note->getMessage(); - notificationInfo["label"] = note->getLabel(); - return notificationInfo; -} diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h deleted file mode 100644 index f9f7641de6..0000000000 --- a/indra/llui/llnotificationslistener.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @file llnotificationslistener.h - * @author Brad Kittenbrink - * @date 2009-07-08 - * @brief Wrap subset of LLNotifications API in event API for test scripts. - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLNOTIFICATIONSLISTENER_H -#define LL_LLNOTIFICATIONSLISTENER_H - -#include "lleventapi.h" -#include "llnotificationptr.h" -#include <boost/shared_ptr.hpp> -#include <map> -#include <string> - -class LLNotifications; -class LLSD; - -class LLNotificationsListener : public LLEventAPI -{ -public: - LLNotificationsListener(LLNotifications & notifications); - ~LLNotificationsListener(); - -private: - void requestAdd(LLSD const & event_data) const; - - void NotificationResponder(const std::string& replypump, - const LLSD& notification, - const LLSD& response) const; - - void listChannels(const LLSD& params) const; - void listChannelNotifications(const LLSD& params) const; - void respond(const LLSD& params) const; - void cancel(const LLSD& params) const; - void ignore(const LLSD& params) const; - void forward(const LLSD& params); - - static LLSD asLLSD(LLNotificationPtr); - - class Forwarder; - typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap; - ForwarderMap mForwarders; - LLNotifications & mNotifications; -}; - -#endif // LL_LLNOTIFICATIONSLISTENER_H diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index 906b83a400..18a82190b5 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -49,7 +49,6 @@ //#include "llfunctorregistry.h" //#include "llpointer.h" #include "llinitparam.h" -//#include "llnotificationslistener.h" //#include "llnotificationptr.h" //#include "llcachename.h" #include "llnotifications.h" -- cgit v1.2.3 From 8c24cc8e3635888b766e30001749966eddc0dc7e Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Tue, 4 Dec 2012 14:38:19 +0200 Subject: CHUI-527 FIXED Changed term to "Multi-person chat" --- indra/newview/skins/default/xui/en/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index a884ac94d6..c75bd98c38 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3400,7 +3400,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. Connecting... </string> <string name="conference-title"> - Ad-hoc Conference + Multi-person chat </string> <string name="conference-title-incoming"> Conference with [AGENT_NAME] -- cgit v1.2.3 From ed9e48bf6bd440a004c0d82da79503de34261610 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Tue, 4 Dec 2012 14:48:59 +0200 Subject: CHUI-530 FIXED Using selectConversationPair will show appropriate session floater. --- indra/newview/llfloaterimcontainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 3a80491dae..c1daea0aeb 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1162,7 +1162,7 @@ bool LLFloaterIMContainer::checkContextMenuItem(const std::string& item, uuid_ve void LLFloaterIMContainer::showConversation(const LLUUID& session_id) { setVisibleAndFrontmost(false); - selectConversation(session_id); + selectConversationPair(session_id, true); } void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) -- cgit v1.2.3 From 7527431bedce5529d33add21ec53336800f48fd0 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Wed, 5 Dec 2012 13:54:55 +0200 Subject: CHUI-572 FIXED Changed initial position for floaters according to description. --- indra/newview/skins/default/xui/en/floater_camera.xml | 2 +- indra/newview/skins/default/xui/en/floater_destinations.xml | 7 ++++--- indra/newview/skins/default/xui/en/floater_im_container.xml | 9 +++++---- indra/newview/skins/default/xui/en/floater_moveview.xml | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index 22bc488a92..4b4821a383 100644 --- a/indra/newview/skins/default/xui/en/floater_camera.xml +++ b/indra/newview/skins/default/xui/en/floater_camera.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater positioning="specified" - left="458" + left="643" bottom="-80" follows="left|bottom" legacy_header_height="18" diff --git a/indra/newview/skins/default/xui/en/floater_destinations.xml b/indra/newview/skins/default/xui/en/floater_destinations.xml index 39aa8e07bb..41b57530fc 100644 --- a/indra/newview/skins/default/xui/en/floater_destinations.xml +++ b/indra/newview/skins/default/xui/en/floater_destinations.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - positioning="cascading" ignore_ui_scale="false" legacy_header_height="225" can_minimize="true" @@ -12,16 +11,18 @@ height="230" layout="topleft" name="Destinations" + right="-10" + bottom="-80" single_instance="true" help_topic="destinations" save_rect="true" save_visibility="true" title="DESTINATIONS" - width="840"> + width="550"> <web_browser top="25" height="200" - width="840" + width="550" follows="all" name="destination_guide_contents" trusted_content="true"/> diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 4aa7c88312..152c897120 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -3,7 +3,7 @@ can_close="true" can_minimize="true" can_resize="true" - height="430" + height="230" layout="topleft" min_height="50" name="floater_im_box" @@ -13,7 +13,8 @@ single_instance="true" reuse_instance="true" title="CONVERSATIONS" - width="680"> + bottom="-80" + width="450"> <string name="collapse_icon" value="Conv_toolbar_collapse"/> @@ -23,13 +24,13 @@ <layout_stack animate="true" follows="all" - height="430" + height="230" layout="topleft" left="0" name="conversations_stack" orientation="horizontal" top="0" - width="680"> + width="450"> <layout_panel auto_resize="true" user_resize="true" diff --git a/indra/newview/skins/default/xui/en/floater_moveview.xml b/indra/newview/skins/default/xui/en/floater_moveview.xml index 4e7ee7913f..02d9805ddf 100644 --- a/indra/newview/skins/default/xui/en/floater_moveview.xml +++ b/indra/newview/skins/default/xui/en/floater_moveview.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater positioning="specified" - left="320" + left="505" bottom="-80" legacy_header_height="18" can_dock="false" -- cgit v1.2.3 From 04dee1bad92da5910394f920247db60bade9ecc1 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 4 Dec 2012 20:49:42 +0200 Subject: CHUI-504 FIXED Open Conversation floater on first login. added toggleInstanceOrBringToFront("im_container") to LLStartup; typo corr. --- indra/newview/llstartup.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 1704ad9055..34259658ea 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1520,7 +1520,7 @@ bool idle_startup() } //--------------------------------------------------------------------- - // Agent Send + // World Wait //--------------------------------------------------------------------- if(STATE_WORLD_WAIT == LLStartUp::getStartupState()) { @@ -1846,6 +1846,10 @@ bool idle_startup() // Set the show start location to true, now that the user has logged // on with this install. gSavedSettings.setBOOL("ShowStartLocation", TRUE); + + // Open Conversation floater on first login. + LLFloaterReg::toggleInstanceOrBringToFront("im_container"); + } display_startup(); @@ -2167,7 +2171,6 @@ bool idle_startup() LLStartUp::setStartupState( STATE_STARTED ); display_startup(); - // Unmute audio if desired and setup volumes. // Unmute audio if desired and setup volumes. // This is a not-uncommon crash site, so surround it with // llinfos output to aid diagnosis. -- cgit v1.2.3 From b43c8afc36a11c34fa76443be85430cac6c72c42 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 4 Dec 2012 14:51:33 -0800 Subject: CHUI-550, CHUI-551 : Fixed : Changed conversation sorting according to designer's desires. --- indra/newview/llconversationmodel.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 728b1a3f4c..0b7c3939df 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -528,12 +528,8 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL { // If both are sessions U32 sort_order = getSortOrderSessions(); - if ((type_a == LLConversationItem::CONV_SESSION_NEARBY) || (type_b == LLConversationItem::CONV_SESSION_NEARBY)) - { - // If one is the nearby session, put nearby session *always* first - return (type_a == LLConversationItem::CONV_SESSION_NEARBY); - } - else if (sort_order == LLConversationFilter::SO_DATE) + + if (sort_order == LLConversationFilter::SO_DATE) { // Sort by time F64 time_a = 0.0; @@ -552,14 +548,22 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL } // If no time available, we'll default to sort by name at the end of this method } - else if (sort_order == LLConversationFilter::SO_SESSION_TYPE) + else { - if (type_a != type_b) + if ((type_a == LLConversationItem::CONV_SESSION_NEARBY) || (type_b == LLConversationItem::CONV_SESSION_NEARBY)) { - // Lowest types come first. See LLConversationItem definition of types - return (type_a < type_b); + // If one is the nearby session, put nearby session *always* last + return (type_b == LLConversationItem::CONV_SESSION_NEARBY); } + else if (sort_order == LLConversationFilter::SO_SESSION_TYPE) + { + if (type_a != type_b) + { + // Lowest types come first. See LLConversationItem definition of types + return (type_a < type_b); + } // If types are identical, we'll default to sort by name at the end of this method + } } } else -- cgit v1.2.3 From 8642088d65ec340b50661e2a3bf74820ec595010 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 4 Dec 2012 19:23:36 -0800 Subject: CHUI-571: Fixed bug where when the converation floater was torn off and a new im received, the incorrect conversation would be displayed and focused. In order to do this removed the conversation floater panels from being focused immediately when set visible. Also there was a bug when showing the stub panel for torn off conversations. The tab container was not setting the stub panel index properly to 0, which is where the stub panel existed in the tab container's list. This is post code review submit. Will submit another with minor code review changes. --- indra/llui/lltabcontainer.cpp | 3 ++- indra/newview/llfloaterimcontainer.cpp | 14 +++----------- indra/newview/llfloaterimnearbychat.cpp | 1 - indra/newview/llfloaterimsession.cpp | 1 - indra/newview/llfloaterimsessiontab.cpp | 2 +- indra/newview/llimview.cpp | 20 ++++++++++++++++---- 6 files changed, 22 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 3c1dfc1184..0dd63c2632 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1559,7 +1559,8 @@ BOOL LLTabContainer::setTab(S32 which) void LLTabContainer::hideAllTabs() { - setCurrentPanelIndex(-1); + + setCurrentPanelIndex(0); for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { (* iter)->mTabPanel->setVisible(FALSE); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c1daea0aeb..d50581a314 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -546,8 +546,10 @@ void LLFloaterIMContainer::setVisible(BOOL visible) // *TODO: find a way to move this to XML as a default panel or something like that LLSD name("nearby_chat"); LLFloaterReg::toggleInstanceOrBringToFront(name); + setSelectedSession(LLUUID(NULL)); } openNearbyChat(); + selectConversationPair(getSelectedSession(), false); } nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); @@ -571,7 +573,6 @@ void LLFloaterIMContainer::setVisible(BOOL visible) // Now, do the normal multifloater show/hide LLMultiFloater::setVisible(visible); - } void LLFloaterIMContainer::collapseMessagesPane(bool collapse) @@ -1624,22 +1625,13 @@ void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, { //Finds the conversation line item to flash using the session_id LLConversationViewSession * widget = dynamic_cast<LLConversationViewSession *>(get_ptr_in_map(mConversationsWidgets,session_id)); - LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); if (widget) { //Start flash if (is_flashes) { - //Only flash when conversation is not active - if(session_floater - && (!session_floater->isInVisibleChain()) //conversation floater not displayed - || - (session_floater->isInVisibleChain() && session_floater->hasFocus() == false)) //conversation floater is displayed but doesn't have focus - - { - widget->getFlashTimer()->startFlashing(); - } + widget->getFlashTimer()->startFlashing(); } //Stop flash else diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index a20fce876c..80a41e2f37 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -228,7 +228,6 @@ void LLFloaterIMNearbyChat::setVisible(BOOL visible) { removeScreenChat(); } - setFocus(visible); } // virtual diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 212b0df712..cb730c6237 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -629,7 +629,6 @@ void LLFloaterIMSession::setVisible(BOOL visible) } - setFocus(visible); } BOOL LLFloaterIMSession::getVisible() diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index d04fa2674d..da25f95ffe 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -60,6 +60,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) , mRefreshTimer(new LLTimer()) , mIsHostAttached(false) { + setAutoFocus(FALSE); mSession = LLIMModel::getInstance()->findIMSession(mSessionID); mCommitCallbackRegistrar.add("IMSession.Menu.Action", @@ -124,7 +125,6 @@ void LLFloaterIMSessionTab::setVisible(BOOL visible) { LLFloaterIMSessionTab::addToHost(mSessionID); } - setFocus(visible); } /*virtual*/ diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index b6fd3ec9c8..821e62c4e6 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -192,12 +192,24 @@ void on_new_message(const LLSD& msg) else if("openconversations" == action) { LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); - if (im_box) + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); + + //Don't flash and show conversation floater when conversation already active (has focus) + if(session_floater + && (!session_floater->isInVisibleChain()) //conversation floater not displayed + || + (session_floater->isInVisibleChain() && session_floater->hasFocus() == false)) //conversation floater is displayed but doesn't have focus + { - im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item + //Flash line item + if (im_box) + { + im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item + } + + //Surface conversations floater + LLFloaterReg::showInstance("im_container"); } - - LLFloaterReg::showInstance("im_container"); } } -- cgit v1.2.3 From e1b7153b4782ec4d1f8b028b435e7e4f0cf98dc2 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Wed, 5 Dec 2012 17:08:38 +0200 Subject: CHUI-530 Additional fix --- indra/newview/llfloaterimcontainer.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c1daea0aeb..36eb9435e9 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1599,6 +1599,7 @@ void LLFloaterIMContainer::openNearbyChat() LLConversationViewSession* nearby_chat = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,LLUUID())); if (nearby_chat) { + selectConversation(LLUUID()); nearby_chat->setOpen(TRUE); } } -- cgit v1.2.3 From e0b1b063c14081a7c53ab5620db20385e1f2bbbd Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Wed, 5 Dec 2012 20:03:15 +0200 Subject: CHUI-577 FIXED "Mute text" and "Block voice" items are added to context menu instead of "Block\unblock" --- indra/newview/llconversationmodel.cpp | 1 + indra/newview/llfloaterimcontainer.cpp | 29 ++++++++++++++++++++-- indra/newview/llfloaterimcontainer.h | 1 + .../skins/default/xui/en/menu_conversation.xml | 11 ++++++-- 4 files changed, 38 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 0b7c3939df..4328c60b1a 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -115,6 +115,7 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items) items.push_back(std::string("share")); items.push_back(std::string("pay")); items.push_back(std::string("block_unblock")); + items.push_back(std::string("MuteText")); if(this->getType() != CONV_SESSION_1_ON_1) { diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 8e7edba0c0..a5b93f3692 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -926,7 +926,11 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec } else if ("block_unblock" == command) { - LLAvatarActions::toggleBlock(userID); + toggleMute(userID, LLMute::flagVoiceChat); + } + else if ("mute_unmute" == command) + { + toggleMute(userID, LLMute::flagTextChat); } else if ("selected" == command || "mute_all" == command || "unmute_all" == command) { @@ -1144,8 +1148,12 @@ bool LLFloaterIMContainer::checkContextMenuItem(const std::string& item, uuid_ve { if ("is_blocked" == item) { - return LLAvatarActions::isBlocked(uuids.front()); + return LLMuteList::getInstance()->isMuted(uuids.front(), LLMute::flagVoiceChat); } + else if (item == "is_muted") + { + return LLMuteList::getInstance()->isMuted(uuids.front(), LLMute::flagTextChat); + } else if ("is_allowed_text_chat" == item) { const LLSpeaker * speakerp = getSpeakerOfSelectedParticipant(getSpeakerMgrForSelectedParticipant()); @@ -1591,6 +1599,23 @@ void LLFloaterIMContainer::toggleAllowTextChat(const LLUUID& participant_uuid) } } +void LLFloaterIMContainer::toggleMute(const LLUUID& participant_id, U32 flags) +{ + BOOL is_muted = LLMuteList::getInstance()->isMuted(participant_id, flags); + std::string name; + gCacheName->getFullName(participant_id, name); + LLMute mute(participant_id, name, LLMute::AGENT); + + if (!is_muted) + { + LLMuteList::getInstance()->add(mute, flags); + } + else + { + LLMuteList::getInstance()->remove(mute, flags); + } +} + void LLFloaterIMContainer::openNearbyChat() { // If there's only one conversation in the container and that conversation is the nearby chat diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 1badce0d2d..c9987bffe8 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -150,6 +150,7 @@ private: void moderateVoiceAllParticipants(bool unmute); void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); void toggleAllowTextChat(const LLUUID& participant_uuid); + void toggleMute(const LLUUID& participant_id, U32 flags); void openNearbyChat(); LLButton* mExpandCollapseBtn; diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index 908b2c174f..e8265fe482 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -105,14 +105,21 @@ <on_enable function="Avatar.EnableItem" parameter="can_pay" /> </menu_item_call> <menu_item_check - label="Block / unblock" + label="Block Voice" layout="topleft" name="block_unblock"> <on_click function="Avatar.DoToSelected" parameter="block_unblock" /> <on_check function="Avatar.CheckItem" parameter="is_blocked" /> <on_enable function="Avatar.EnableItem" parameter="can_block" /> </menu_item_check> - <menu_item_call + <menu_item_check + label="Block Text" + layout="topleft" + name="MuteText"> + <on_click function="Avatar.DoToSelected" parameter="mute_unmute"/> + <on_check function="Avatar.CheckItem" parameter="is_muted" /> + <on_enable function="Avatar.EnableItem" parameter="can_block" /> + <menu_item_call label="Group Profile" layout="topleft" name="group_profile"> -- cgit v1.2.3 From fc000880b40143534c47c475a7a0aba6ab75039e Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 5 Dec 2012 20:47:21 +0200 Subject: CHUI-519 FIXED Do not put offered items into the trash while in Busy / DND mode --- indra/llui/llnotifications.cpp | 3 ++- indra/llui/llnotifications.h | 13 +++++++++++-- indra/newview/llnotificationofferhandler.cpp | 1 + indra/newview/llviewermessage.cpp | 5 ++++- indra/newview/skins/default/xui/en/menu_conversation.xml | 3 ++- 5 files changed, 20 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 66144671c9..fd9bfec203 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -475,7 +475,8 @@ LLNotification::LLNotification(const LLSDParamAdapter<Params>& p) : mCancelled(false), mIgnored(false), mResponderObj(NULL), - mId(p.id.isProvided() ? p.id : LLUUID::generateNewID()) + mId(p.id.isProvided() ? p.id : LLUUID::generateNewID()), + mOfferFromAgent(p.offer_from_agent) { if (p.functor.name.isChosen()) { diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 088931858a..372b9ce46f 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -316,6 +316,7 @@ public: expiry; Optional<LLNotificationContext*> context; Optional<void*> responder; + Optional<bool> offer_from_agent; struct Functor : public LLInitParam::ChoiceBlock<Functor> { @@ -339,7 +340,8 @@ public: payload("payload"), form_elements("form"), substitutions("substitutions"), - expiry("expiry") + expiry("expiry"), + offer_from_agent("offer_from_agent", false) { time_stamp = LLDate::now(); responder = NULL; @@ -352,7 +354,8 @@ public: payload("payload"), form_elements("form"), substitutions("substitutions"), - expiry("expiry") + expiry("expiry"), + offer_from_agent("offer_from_agent", false) { functor.name = _name; name = _name; @@ -378,6 +381,7 @@ private: LLNotificationFormPtr mForm; void* mResponderObj; // TODO - refactor/remove this field LLNotificationResponderPtr mResponder; + bool mOfferFromAgent; // a reference to the template LLNotificationTemplatePtr mTemplatep; @@ -513,6 +517,11 @@ public: return mTimestamp; } + bool getOfferFromAgent() const + { + return mOfferFromAgent; + } + std::string getType() const; std::string getMessage() const; std::string getFooter() const; diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 91003c7d53..ff5b5e21f7 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -113,6 +113,7 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) p.panel = notify_box; // we not save offer notifications to the syswell floater that should be added to the IM floater p.can_be_stored = !add_notif_to_im; + p.force_show = notification->getOfferFromAgent(); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index dc8192105f..ea804508c8 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1971,6 +1971,7 @@ void inventory_offer_handler(LLOfferInfo* info) p.substitutions(args).payload(payload).functor.responder(LLNotificationResponderPtr(info)); info->mPersist = true; p.name = "UserGiveItem"; + p.offer_from_agent = true; // Prefetch the item into your local inventory. LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID); @@ -2738,7 +2739,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Same as closing window info->forceResponse(IOR_DECLINE); } - else if (is_do_not_disturb && dialog != IM_TASK_INVENTORY_OFFERED) // busy mode must not affect interaction with objects (STORM-565) + // old logic: busy mode must not affect interaction with objects (STORM-565) + // new logic: inventory offers from in-world objects should be auto-declined (CHUI-519) + else if (is_do_not_disturb && dialog == IM_TASK_INVENTORY_OFFERED) { // Until throttling is implemented, do not disturb mode should reject inventory instead of silently // accepting it. SEE SL-39554 diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index e8265fe482..01ef8ebdb5 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -116,9 +116,10 @@ label="Block Text" layout="topleft" name="MuteText"> - <on_click function="Avatar.DoToSelected" parameter="mute_unmute"/> + <on_click function="Avatar.DoToSelected" parameter="mute_unmute" /> <on_check function="Avatar.CheckItem" parameter="is_muted" /> <on_enable function="Avatar.EnableItem" parameter="can_block" /> + </menu_item_check> <menu_item_call label="Group Profile" layout="topleft" -- cgit v1.2.3 From ffe80818064572a19b52d4f39f0e14538f701275 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 5 Dec 2012 12:40:44 -0800 Subject: CHUI 571: Code review changes, now LLFloaterIMContainer::showStub inlines code for hiding all tab panels and then showing the stub panel. Before the function would call hideAllTabs() --- indra/llui/lltabcontainer.cpp | 12 ------------ indra/llui/lltabcontainer.h | 4 +--- indra/newview/llfloaterimcontainer.cpp | 27 +++++++++++++++++++++++---- 3 files changed, 24 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 0dd63c2632..91527c68f2 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1556,18 +1556,6 @@ BOOL LLTabContainer::setTab(S32 which) return is_visible; } - -void LLTabContainer::hideAllTabs() -{ - - setCurrentPanelIndex(0); - for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) - { - (* iter)->mTabPanel->setVisible(FALSE); - } -} - - BOOL LLTabContainer::selectTabByName(const std::string& name) { LLPanel* panel = getPanelByName(name); diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index a9cdf22b16..57862fc626 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -192,7 +192,7 @@ public: BOOL selectTabPanel( LLPanel* child ); BOOL selectTab(S32 which); BOOL selectTabByName(const std::string& title); - void hideAllTabs(); + void setCurrentPanelIndex(S32 index) { mCurrentTabIdx = index; } BOOL getTabPanelFlashing(LLPanel* child); void setTabPanelFlashing(LLPanel* child, BOOL state); @@ -243,8 +243,6 @@ private: void setTabsHidden(BOOL hidden) { mTabsHidden = hidden; } BOOL getTabsHidden() const { return mTabsHidden; } - - void setCurrentPanelIndex(S32 index) { mCurrentTabIdx = index; } void scrollPrev() { mScrollPos = llmax(0, mScrollPos-1); } // No wrap void scrollNext() { mScrollPos = llmin(mScrollPos+1, mMaxScrollPos); } // No wrap diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a5b93f3692..23c21d5309 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -516,13 +516,32 @@ void LLFloaterIMContainer::tabClose() } } +//Shows/hides the stub panel when a conversation floater is torn off void LLFloaterIMContainer::showStub(bool stub_is_visible) { - if (stub_is_visible) - { - mTabContainer->hideAllTabs(); - } + S32 tabCount = 0; + LLPanel * tabPanel = NULL; + + if(stub_is_visible) + { + tabCount = mTabContainer->getTabCount(); + + //Hide all tabs even stub + for(S32 i = 0; i < tabCount; ++i) + { + tabPanel = mTabContainer->getPanelByIndex(i); + + if(tabPanel) + { + tabPanel->setVisible(false); + } + } + + //Set the index to the stub panel since we will be showing the stub + mTabContainer->setCurrentPanelIndex(0); + } + //Now show/hide the stub mStubPanel->setVisible(stub_is_visible); } -- cgit v1.2.3 From a4a2cc62c3411f0391b90d9720a13b49b0e123ef Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 5 Dec 2012 16:08:17 -0800 Subject: CHUI-509 : Fixed : Add params to inventory widgets to control font colors (required for library items and links). --- indra/llui/llfolderviewitem.cpp | 39 ++++++++++++++++++------------------- indra/llui/llfolderviewitem.h | 10 +++++++--- indra/newview/llinventorybridge.cpp | 5 +++++ indra/newview/llinventorybridge.h | 1 + indra/newview/llinventorypanel.cpp | 24 +++++++++++++++++++++++ indra/newview/llinventorypanel.h | 7 +++++++ 6 files changed, 63 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 9b54a7a467..60a6d3e3ea 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -47,16 +47,14 @@ static LLDefaultChildRegistry::Register<LLFolderViewItem> r("folder_view_item"); // statics std::map<U8, LLFontGL*> LLFolderViewItem::sFonts; // map of styles to fonts +bool LLFolderViewItem::sColorSetInitialized = false; LLUIColor LLFolderViewItem::sFgColor; LLUIColor LLFolderViewItem::sHighlightBgColor; -LLUIColor LLFolderViewItem::sHighlightFgColor; LLUIColor LLFolderViewItem::sFocusOutlineColor; LLUIColor LLFolderViewItem::sMouseOverColor; LLUIColor LLFolderViewItem::sFilterBGColor; LLUIColor LLFolderViewItem::sFilterTextColor; LLUIColor LLFolderViewItem::sSuffixColor; -LLUIColor LLFolderViewItem::sLibraryColor; -LLUIColor LLFolderViewItem::sLinkColor; LLUIColor LLFolderViewItem::sSearchStatusColor; // only integers can be initialized in header @@ -106,6 +104,8 @@ LLFolderViewItem::Params::Params() item_top_pad("item_top_pad"), creation_date(), allow_open("allow_open", true), + font_color("font_color"), + font_highlight_color("font_highlight_color"), left_pad("left_pad", 0), icon_pad("icon_pad", 0), icon_width("icon_width", 0), @@ -113,7 +113,7 @@ LLFolderViewItem::Params::Params() text_pad_right("text_pad_right", 0), arrow_size("arrow_size", 0), max_folder_item_overlap("max_folder_item_overlap", 0) -{} +{ } // Default constructor LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) @@ -137,6 +137,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mViewModelItem(p.listener), mIsMouseOverTitle(false), mAllowOpen(p.allow_open), + mFontColor(p.font_color), + mFontHighlightColor(p.font_highlight_color), mLeftPad(p.left_pad), mIconPad(p.icon_pad), mIconWidth(p.icon_width), @@ -145,17 +147,18 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mArrowSize(p.arrow_size), mMaxFolderItemOverlap(p.max_folder_item_overlap) { - sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); - sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); - sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); - sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); - sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); - sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); - sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); - sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); - sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); - sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); - sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); + if (!sColorSetInitialized) + { + sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); + sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); + sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); + sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); + sColorSetInitialized = true; + } if (mViewModelItem) { @@ -785,10 +788,6 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo void LLFolderViewItem::drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x) { - //TODO RN: implement this in terms of getColor() - //if (highlight_link) color = sLinkColor; - //if (gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; - //--------------------------------------------------------------------------------// // Draw the actual label text // @@ -857,7 +856,7 @@ void LLFolderViewItem::draw() box_image->draw(box_rect, sFilterBGColor); } - LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; + LLColor4 color = (mIsSelected && filled) ? mFontHighlightColor : mFontColor; drawLabel(font, text_left, y, color, right_x); //--------------------------------------------------------------------------------// diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 2e633a39e5..f33f21c8f8 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -61,6 +61,9 @@ public: Optional<time_t> creation_date; Optional<bool> allow_open; + Optional<LLUIColor> font_color; + Optional<LLUIColor> font_highlight_color; + Optional<S32> left_pad, icon_pad, icon_width, @@ -116,19 +119,20 @@ protected: mIsMouseOverTitle, mAllowOpen, mSelectPending; + + LLUIColor mFontColor; + LLUIColor mFontHighlightColor; // For now assuming all colors are the same in derived classes. + static bool sColorSetInitialized; static LLUIColor sFgColor; static LLUIColor sFgDisabledColor; static LLUIColor sHighlightBgColor; - static LLUIColor sHighlightFgColor; static LLUIColor sFocusOutlineColor; static LLUIColor sMouseOverColor; static LLUIColor sFilterBGColor; static LLUIColor sFilterTextColor; static LLUIColor sSuffixColor; - static LLUIColor sLibraryColor; - static LLUIColor sLinkColor; static LLUIColor sSearchStatusColor; // this is an internal method used for adding items to folders. A diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 73631f4ba8..cf8253ca4d 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -255,6 +255,11 @@ BOOL LLInvFVBridge::isLink() const return mIsLink; } +BOOL LLInvFVBridge::isLibraryItem() const +{ + return gInventory.isObjectDescendentOf(getUUID(),gInventory.getLibraryRootFolderID()); +} + /*virtual*/ /** * @brief Adds this item into clipboard storage diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 5e96f00920..5c6cf0f0f0 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -107,6 +107,7 @@ public: virtual BOOL isItemMovable() const; virtual BOOL isItemInTrash() const; virtual BOOL isLink() const; + virtual BOOL isLibraryItem() const; //virtual BOOL removeItem() = 0; virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); virtual void move(LLFolderViewModelItem* new_parent_bridge) {} diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 098a44b9d8..81e7f166e1 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -57,6 +57,15 @@ const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("Recent const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); static const LLInventoryFolderViewModelBuilder INVENTORY_BRIDGE_BUILDER; +// statics +bool LLInventoryPanel::sColorSetInitialized = false; +LLUIColor LLInventoryPanel::sDefaultColor; +LLUIColor LLInventoryPanel::sDefaultHighlightColor; +LLUIColor LLInventoryPanel::sLibraryColor; +LLUIColor LLInventoryPanel::sLinkColor; + +const LLColor4U DEFAULT_WHITE(255, 255, 255); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryPanelObserver // @@ -140,6 +149,15 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : { mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER; + if (!sColorSetInitialized) + { + sDefaultColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + sDefaultHighlightColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); + sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); + sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); + sColorSetInitialized = true; + } + // context menu callbacks mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2)); mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)); @@ -705,6 +723,9 @@ LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * br params.listener = bridge; params.tool_tip = params.name; + params.font_color = (bridge->isLibraryItem() ? sLibraryColor : (bridge->isLink() ? sLinkColor : sDefaultColor)); + params.font_highlight_color = (bridge->isLibraryItem() ? sLibraryColor : (bridge->isLink() ? sLinkColor : sDefaultHighlightColor)); + return LLUICtrlFactory::create<LLFolderViewFolder>(params); } @@ -718,6 +739,9 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge params.listener = bridge; params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; + + params.font_color = (bridge->isLibraryItem() ? sLibraryColor : (bridge->isLink() ? sLinkColor : sDefaultColor)); + params.font_highlight_color = (bridge->isLibraryItem() ? sLibraryColor : (bridge->isLink() ? sLinkColor : sDefaultHighlightColor)); return LLUICtrlFactory::create<LLFolderViewItem>(params); } diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index c4f3c1b47d..9639086c11 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -275,6 +275,13 @@ protected: // Builds the UI. Call this once the inventory is usable. void initializeViews(); + // Specific inventory colors + static bool sColorSetInitialized; + static LLUIColor sDefaultColor; + static LLUIColor sDefaultHighlightColor; + static LLUIColor sLibraryColor; + static LLUIColor sLinkColor; + LLFolderViewItem* buildNewViews(const LLUUID& id); BOOL getIsHiddenFolderType(LLFolderType::EType folder_type) const; -- cgit v1.2.3 From 3a49beed0e96a797a6d663bcae5e932437ca3661 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 5 Dec 2012 20:25:46 -0800 Subject: CHUI-580 : WIP : Change the display name cache system, deprecating the old protocol and using the cap (People API) whenever available. Still has occurence of Resident as last name to clean up. --- indra/llcommon/llavatarname.cpp | 69 ++++++++++++++++++++++++++++++- indra/llcommon/llavatarname.h | 57 ++++++++++++++++++------- indra/llmessage/llavatarnamecache.cpp | 56 ++++++++----------------- indra/llmessage/llavatarnamecache.h | 2 + indra/llmessage/llcachename.cpp | 6 ++- indra/llui/llscrolllistctrl.cpp | 2 +- indra/llui/llurlentry.cpp | 4 +- indra/newview/llavataractions.cpp | 16 +++---- indra/newview/llavatariconctrl.cpp | 2 +- indra/newview/llavatarlist.cpp | 9 ++-- indra/newview/llavatarlistitem.cpp | 4 +- indra/newview/llcallingcard.cpp | 6 +-- indra/newview/llchathistory.cpp | 14 +++---- indra/newview/llconversationmodel.cpp | 4 +- indra/newview/llfavoritesbar.cpp | 10 ++--- indra/newview/llfloateravatarpicker.cpp | 12 ++---- indra/newview/llfloaterdisplayname.cpp | 10 ++--- indra/newview/llfloaterimnearbychat.cpp | 2 +- indra/newview/llfloaterscriptlimits.cpp | 15 +------ indra/newview/llfloatersellland.cpp | 2 +- indra/newview/llfloatertopobjects.cpp | 14 ++----- indra/newview/llfloatervoicevolume.cpp | 2 +- indra/newview/llfriendcard.cpp | 2 +- indra/newview/llimview.cpp | 20 +++------ indra/newview/llinspectavatar.cpp | 6 +-- indra/newview/llinventorybridge.cpp | 5 +-- indra/newview/llnamelistctrl.cpp | 4 +- indra/newview/llpanelblockedlist.cpp | 2 +- indra/newview/llpanelgroupinvite.cpp | 4 +- indra/newview/llpanelgroupnotices.cpp | 5 +-- indra/newview/llpanelgrouproles.cpp | 4 +- indra/newview/llparticipantlist.cpp | 2 +- indra/newview/lltoastgroupnotifypanel.cpp | 6 +-- indra/newview/lltoolpie.cpp | 3 +- indra/newview/llviewerdisplayname.cpp | 6 +-- indra/newview/llviewermenu.cpp | 6 +-- indra/newview/llviewermessage.cpp | 15 ++----- indra/newview/llvoavatar.cpp | 24 +++++------ indra/newview/llvoicevivox.cpp | 4 +- 39 files changed, 224 insertions(+), 212 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp index 3206843bf4..b49e6a7aac 100644 --- a/indra/llcommon/llavatarname.cpp +++ b/indra/llcommon/llavatarname.cpp @@ -30,6 +30,7 @@ #include "llavatarname.h" #include "lldate.h" +#include "llframetimer.h" #include "llsd.h" // Store these in pre-built std::strings to avoid memory allocations in @@ -42,6 +43,8 @@ static const std::string IS_DISPLAY_NAME_DEFAULT("is_display_name_default"); static const std::string DISPLAY_NAME_EXPIRES("display_name_expires"); static const std::string DISPLAY_NAME_NEXT_UPDATE("display_name_next_update"); +bool LLAvatarName::sUseDisplayNames = true; + LLAvatarName::LLAvatarName() : mUsername(), mDisplayName(), @@ -61,6 +64,17 @@ bool LLAvatarName::operator<(const LLAvatarName& rhs) const return mUsername < rhs.mUsername; } +//static +void LLAvatarName::setUseDisplayNames(bool use) +{ + sUseDisplayNames = use; +} +//static +bool LLAvatarName::useDisplayNames() +{ + return sUseDisplayNames; +} + LLSD LLAvatarName::asLLSD() const { LLSD sd; @@ -85,6 +99,33 @@ void LLAvatarName::fromLLSD(const LLSD& sd) mExpires = expires.secondsSinceEpoch(); LLDate next_update = sd[DISPLAY_NAME_NEXT_UPDATE]; mNextUpdate = next_update.secondsSinceEpoch(); + + // Some avatars don't have explicit display names set. Force a legible display name here. + if (mDisplayName.empty()) + { + mDisplayName = mUsername; + } +} + +void LLAvatarName::fromString(const std::string& full_name, F64 expires) +{ + mDisplayName = full_name; + std::string::size_type index = full_name.find(' '); + if (index != std::string::npos) + { + mLegacyFirstName = full_name.substr(0, index); + mLegacyLastName = full_name.substr(index+1); + mUsername = mLegacyFirstName + " " + mLegacyLastName; + } + else + { + mLegacyFirstName = full_name; + mLegacyLastName = ""; + mUsername = full_name; + } + mIsDisplayNameDefault = true; + mIsTemporaryName = true; + mExpires = LLFrameTimer::getTotalSeconds() + expires; } std::string LLAvatarName::getCompleteName() const @@ -104,9 +145,22 @@ std::string LLAvatarName::getCompleteName() const return name; } -std::string LLAvatarName::getLegacyName() const +std::string LLAvatarName::getDisplayName() const +{ + if (sUseDisplayNames) + { + return mDisplayName; + } + else + { + return getUserName(); + } +} + +std::string LLAvatarName::getUserName() const { - if (mLegacyFirstName.empty() && mLegacyLastName.empty()) // display names disabled? + // If we cannot create a user name from the legacy strings, use the display name + if (mLegacyFirstName.empty() && mLegacyLastName.empty()) { return mDisplayName; } @@ -118,3 +172,14 @@ std::string LLAvatarName::getLegacyName() const name += mLegacyLastName; return name; } + +void LLAvatarName::dump() const +{ + llinfos << "Merov debug : display = " << mDisplayName << ", user = " << mUsername << ", complete = " << getCompleteName() << ", legacy = " << getUserName() << " first = " << mLegacyFirstName << " last = " << mLegacyLastName << llendl; + LL_DEBUGS("AvNameCache") << "LLAvatarName: " + << "user '" << mUsername << "' " + << "display '" << mDisplayName << "' " + << "expires in " << mExpires - LLFrameTimer::getTotalSeconds() << " seconds" + << LL_ENDL; +} + diff --git a/indra/llcommon/llavatarname.h b/indra/llcommon/llavatarname.h index ba258d6d52..cf9eb27b03 100644 --- a/indra/llcommon/llavatarname.h +++ b/indra/llcommon/llavatarname.h @@ -43,19 +43,50 @@ public: void fromLLSD(const LLSD& sd); + // Used only in legacy mode when the display name capability is not provided server side + void fromString(const std::string& full_name, F64 expires = 0.0f); + + static void setUseDisplayNames(bool use); + static bool useDisplayNames(); + + // Name is valid if not temporary and not yet expired + bool isValidName(F64 max_unrefreshed = 0.0f) const { return !mIsTemporaryName && (mExpires >= max_unrefreshed); } + + // + bool isDisplayNameDefault() const { return mIsDisplayNameDefault; } + // For normal names, returns "James Linden (james.linden)" // When display names are disabled returns just "James Linden" std::string getCompleteName() const; - - // Returns "James Linden" or "bobsmith123 Resident" for backwards - // compatibility with systems like voice and muting - // *TODO: Eliminate this in favor of username only - std::string getLegacyName() const; - + + // "José Sanchez" or "James Linden", UTF-8 encoded Unicode + // Takes the display name preference into account. This is truly the name that should + // be used for all UI where an avatar name has to be used unless we truly want something else (rare) + std::string getDisplayName() const; + + // Returns "James Linden" or "bobsmith123 Resident" + // Used where we explicitely prefer or need a non UTF-8 legacy (ASCII) name + // Also used for backwards compatibility with systems like voice and muting + std::string getUserName() const; + + // Debug print of the object + void dump() const; + + // Names can change, so need to keep track of when name was + // last checked. + // Unix time-from-epoch seconds for efficiency + F64 mExpires; + + // You can only change your name every N hours, so record + // when the next update is allowed + // Unix time-from-epoch seconds + F64 mNextUpdate; + +private: // "bobsmith123" or "james.linden", US-ASCII only std::string mUsername; - // "Jose' Sanchez" or "James Linden", UTF-8 encoded Unicode + // "José Sanchez" or "James Linden", UTF-8 encoded Unicode // Contains data whether or not user has explicitly set // a display name; may duplicate their username. std::string mDisplayName; @@ -81,15 +112,9 @@ public: // shown in UI, but are not serialized. bool mIsTemporaryName; - // Names can change, so need to keep track of when name was - // last checked. - // Unix time-from-epoch seconds for efficiency - F64 mExpires; - - // You can only change your name every N hours, so record - // when the next update is allowed - // Unix time-from-epoch seconds - F64 mNextUpdate; + // Global flag indicating if display name should be used or not + // This will affect the output of the high level "get" methods + static bool sUseDisplayNames; }; #endif diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 700525e1fa..329871d8eb 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -43,10 +43,6 @@ namespace LLAvatarNameCache { use_display_name_signal_t mUseDisplayNamesSignal; - // Manual override for display names - can disable even if the region - // supports it. - bool sUseDisplayNames = true; - // Cache starts in a paused state until we can determine if the // current region supports display names. bool sRunning = false; @@ -209,17 +205,8 @@ public: // Use expiration time from header av_name.mExpires = expires; - // Some avatars don't have explicit display names set - if (av_name.mDisplayName.empty()) - { - av_name.mDisplayName = av_name.mUsername; - } - - LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << " " - << "user '" << av_name.mUsername << "' " - << "display '" << av_name.mDisplayName << "' " - << "expires in " << expires - now << " seconds" - << LL_ENDL; + LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << LL_ENDL; + av_name.dump(); // cache it and fire signals LLAvatarNameCache::processName(agent_id, av_name, true); @@ -291,12 +278,9 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id) LLAvatarNameCache::sPendingQueue.erase(agent_id); LLAvatarName& av_name = existing->second; - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent " - << agent_id - << "user '" << av_name.mUsername << "' " - << "display '" << av_name.mDisplayName << "' " - << "expires in " << av_name.mExpires - LLFrameTimer::getTotalSeconds() << " seconds" - << LL_ENDL; + LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent " << agent_id << LL_ENDL; + av_name.dump(); + av_name.mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME; // reset expiry time so we don't constantly rerequest. } } @@ -476,7 +460,7 @@ void LLAvatarNameCache::exportFile(std::ostream& ostr) const LLUUID& agent_id = it->first; const LLAvatarName& av_name = it->second; // Do not write temporary or expired entries to the stored cache - if (!av_name.mIsTemporaryName && av_name.mExpires >= max_unrefreshed) + if (av_name.isValidName(max_unrefreshed)) { // key must be a string agents[agent_id.asString()] = av_name.asLLSD(); @@ -513,7 +497,7 @@ void LLAvatarNameCache::idle() if (!sAskQueue.empty()) { - if (useDisplayNames()) + if (hasNameLookupURL()) { requestNamesViaCapability(); } @@ -565,7 +549,7 @@ void LLAvatarNameCache::eraseUnrefreshed() { const LLUUID& agent_id = it->first; LL_DEBUGS("AvNameCache") << agent_id - << " user '" << av_name.mUsername << "' " + << " user '" << av_name.getUserName() << "' " << "expired " << now - av_name.mExpires << " secs ago" << LL_ENDL; sCache.erase(it++); @@ -583,14 +567,12 @@ void LLAvatarNameCache::buildLegacyName(const std::string& full_name, LLAvatarName* av_name) { llassert(av_name); - av_name->mUsername = ""; - av_name->mDisplayName = full_name; - av_name->mIsDisplayNameDefault = true; - av_name->mIsTemporaryName = true; - av_name->mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME; + av_name->fromString(full_name,TEMP_CACHE_ENTRY_LIFETIME); LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::buildLegacyName " << full_name << LL_ENDL; + // DEBUG ONLY!!! DO NOT COMMIT!!! + av_name->dump(); } // fills in av_name if it has it in the cache, even if expired (can check expiry time) @@ -600,7 +582,7 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) if (sRunning) { // ...only do immediate lookups when cache is running - if (useDisplayNames()) + if (hasNameLookupURL()) { // ...use display names cache std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id); @@ -662,7 +644,7 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& ag if (sRunning) { // ...only do immediate lookups when cache is running - if (useDisplayNames()) + if (hasNameLookupURL()) { // ...use new cache std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id); @@ -720,20 +702,16 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& ag void LLAvatarNameCache::setUseDisplayNames(bool use) { - if (use != sUseDisplayNames) + if (use != LLAvatarName::useDisplayNames()) { - sUseDisplayNames = use; - // flush our cache - sCache.clear(); - + LLAvatarName::setUseDisplayNames(use); mUseDisplayNamesSignal(); } } -bool LLAvatarNameCache::useDisplayNames() +void LLAvatarNameCache::flushCache() { - // Must be both manually set on and able to look up names. - return sUseDisplayNames && !sNameLookupURL.empty(); + sCache.clear(); } void LLAvatarNameCache::erase(const LLUUID& agent_id) diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index 79f170f7c8..e172601432 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -81,6 +81,8 @@ namespace LLAvatarNameCache void setUseDisplayNames(bool use); bool useDisplayNames(); + void flushCache(); + void erase(const LLUUID& agent_id); /// Provide some fallback for agents that return errors diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 479efabb5f..da07c9ae42 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -524,6 +524,7 @@ std::string LLCacheName::cleanFullName(const std::string& full_name) } //static +// Transform hard-coded name provided by server to a more legible username std::string LLCacheName::buildUsername(const std::string& full_name) { // rare, but handle hard-coded error names returned from server @@ -549,8 +550,9 @@ std::string LLCacheName::buildUsername(const std::string& full_name) return username; } - // if the input wasn't a correctly formatted legacy name just return it unchanged - return full_name; + // if the input wasn't a correctly formatted legacy name, just return it + // cleaned up from a potential terminal "Resident" + return cleanFullName(full_name); } //static diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 3e0653e9a4..7ed7042aff 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1832,7 +1832,7 @@ void LLScrollListCtrl::copyNameToClipboard(std::string id, bool is_group) { LLAvatarName av_name; LLAvatarNameCache::get(LLUUID(id), &av_name); - name = av_name.getLegacyName(); + name = av_name.getUserName(); } LLUrlAction::copyURLToClipboard(name); } diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index a9e8fbb4e4..fd2635c73a 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -597,7 +597,7 @@ LLUrlEntryAgentDisplayName::LLUrlEntryAgentDisplayName() std::string LLUrlEntryAgentDisplayName::getName(const LLAvatarName& avatar_name) { - return avatar_name.mDisplayName; + return avatar_name.getDisplayName(); } // @@ -613,7 +613,7 @@ LLUrlEntryAgentUserName::LLUrlEntryAgentUserName() std::string LLUrlEntryAgentUserName::getName(const LLAvatarName& avatar_name) { - return avatar_name.mUsername.empty() ? avatar_name.getLegacyName() : avatar_name.mUsername; + return avatar_name.getUserName(); } // diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 1969a0bc5f..59b862503c 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -135,7 +135,7 @@ void LLAvatarActions::removeFriendsDialog(const uuid_vec_t& ids) LLAvatarName av_name; if(LLAvatarNameCache::get(agent_id, &av_name)) { - args["NAME"] = av_name.mDisplayName; + args["NAME"] = av_name.getDisplayName(); } msgType = "RemoveFromFriends"; @@ -180,7 +180,7 @@ void LLAvatarActions::offerTeleport(const uuid_vec_t& ids) static void on_avatar_name_cache_start_im(const LLUUID& agent_id, const LLAvatarName& av_name) { - std::string name = av_name.mDisplayName; + std::string name = av_name.getDisplayName(); LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id); if (session_id != LLUUID::null) { @@ -215,7 +215,7 @@ void LLAvatarActions::endIM(const LLUUID& id) static void on_avatar_name_cache_start_call(const LLUUID& agent_id, const LLAvatarName& av_name) { - std::string name = av_name.mDisplayName; + std::string name = av_name.getDisplayName(); LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id, true); if (session_id != LLUUID::null) { @@ -315,11 +315,7 @@ static const char* get_profile_floater_name(const LLUUID& avatar_id) static void on_avatar_name_show_profile(const LLUUID& agent_id, const LLAvatarName& av_name) { - std::string username = av_name.mUsername; - if (username.empty()) - { - username = LLCacheName::buildUsername(av_name.mDisplayName); - } + std::string username = av_name.getUserName(); llinfos << "opening web profile for " << username << llendl; std::string url = getProfileURL(username); @@ -379,7 +375,7 @@ void LLAvatarActions::showOnMap(const LLUUID& id) return; } - gFloaterWorldMap->trackAvatar(id, av_name.mDisplayName); + gFloaterWorldMap->trackAvatar(id, av_name.getDisplayName()); LLFloaterReg::showInstance("world_map"); } @@ -709,7 +705,7 @@ void LLAvatarActions::buildResidentsString(std::vector<LLAvatarName> avatar_name const std::string& separator = LLTrans::getString("words_separator"); for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; ) { - residents_string.append((*it).mDisplayName); + residents_string.append((*it).getDisplayName()); if (++it == avatar_names.end()) { break; diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index b7278d4a3a..0db38c947c 100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -318,7 +318,7 @@ void LLAvatarIconCtrl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarN { // Most avatar icon controls are next to a UI element that shows // a display name, so only show username. - mFullName = av_name.mUsername; + mFullName = av_name.getUserName(); if (mDrawTooltip) { diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 771419f60a..e54e47180f 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -278,7 +278,7 @@ void LLAvatarList::refresh() LLAvatarName av_name; have_names &= LLAvatarNameCache::get(buddy_id, &av_name); - if (!have_filter || findInsensitive(av_name.mDisplayName, mNameFilter)) + if (!have_filter || findInsensitive(av_name.getDisplayName(), mNameFilter)) { if (nadded >= ADD_LIMIT) { @@ -296,8 +296,9 @@ void LLAvatarList::refresh() } else { + std::string display_name = av_name.getDisplayName(); addNewItem(buddy_id, - av_name.mDisplayName.empty() ? waiting_str : av_name.mDisplayName, + display_name.empty() ? waiting_str : display_name, LLAvatarTracker::instance().isBuddyOnline(buddy_id)); } @@ -325,7 +326,7 @@ void LLAvatarList::refresh() const LLUUID& buddy_id = it->asUUID(); LLAvatarName av_name; have_names &= LLAvatarNameCache::get(buddy_id, &av_name); - if (!findInsensitive(av_name.mDisplayName, mNameFilter)) + if (!findInsensitive(av_name.getDisplayName(), mNameFilter)) { removeItemByUUID(buddy_id); modified = true; @@ -398,7 +399,7 @@ bool LLAvatarList::filterHasMatches() // If name has not been loaded yet we consider it as a match. // When the name will be loaded the filter will be applied again(in refresh()). - if (have_name && !findInsensitive(av_name.mDisplayName, mNameFilter)) + if (have_name && !findInsensitive(av_name.getDisplayName(), mNameFilter)) { continue; } diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 7ff1b39573..84e177d4a4 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -449,8 +449,8 @@ void LLAvatarListItem::setNameInternal(const std::string& name, const std::strin void LLAvatarListItem::onAvatarNameCache(const LLAvatarName& av_name) { - setAvatarName(av_name.mDisplayName); - setAvatarToolTip(av_name.mUsername); + setAvatarName(av_name.getDisplayName()); + setAvatarToolTip(av_name.getUserName()); //requesting the list to resort notifyParent(LLSD().with("sort", LLSD())); diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 60d60abd45..9a295faa73 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -723,7 +723,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, // Popup a notify box with online status of this agent // Use display name only because this user is your friend LLSD args; - args["NAME"] = av_name.mDisplayName; + args["NAME"] = av_name.getDisplayName(); args["STATUS"] = online ? LLTrans::getString("OnlineStatus") : LLTrans::getString("OfflineStatus"); LLNotificationPtr notification; @@ -869,7 +869,7 @@ bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id, LLRelationship { LLAvatarName av_name; LLAvatarNameCache::get( buddy_id, &av_name); - buddy_map_t::value_type value(av_name.mDisplayName, buddy_id); + buddy_map_t::value_type value(av_name.getDisplayName(), buddy_id); if(buddy->isOnline() && buddy->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)) { mMappable.insert(value); @@ -892,7 +892,7 @@ bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* bud { LLAvatarName av_name; LLAvatarNameCache::get(buddy_id, &av_name); - mFullName = av_name.mDisplayName; + mFullName = av_name.getDisplayName(); buddy_map_t::value_type value(mFullName, buddy_id); if(buddy->isOnline()) { diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index a33bd88273..3e25d9c457 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -553,15 +553,15 @@ private: void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) { - mFrom = av_name.mDisplayName; + mFrom = av_name.getDisplayName(); LLTextBox* user_name = getChild<LLTextBox>("user_name"); - user_name->setValue( LLSD(av_name.mDisplayName ) ); - user_name->setToolTip( av_name.mUsername ); + user_name->setValue( LLSD(av_name.getDisplayName() ) ); + user_name->setToolTip( av_name.getUserName() ); if (gSavedSettings.getBOOL("NameTagShowUsernames") && - LLAvatarNameCache::useDisplayNames() && - !av_name.mIsDisplayNameDefault) + av_name.useDisplayNames() && + !av_name.isDisplayNameDefault()) { LLStyle::Params style_params_name; LLColor4 userNameColor = LLUIColorTable::instance().getColor("EmphasisColor"); @@ -569,9 +569,9 @@ private: style_params_name.font.name("SansSerifSmall"); style_params_name.font.style("NORMAL"); style_params_name.readonly_color(userNameColor); - user_name->appendText(" - " + av_name.mUsername, FALSE, style_params_name); + user_name->appendText(" - " + av_name.getUserName(), FALSE, style_params_name); } - setToolTip( av_name.mUsername ); + setToolTip( av_name.getUserName() ); // name might have changed, update width updateMinUserNameWidth(); } diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 728b1a3f4c..76c422f34d 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -443,8 +443,8 @@ void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) { - mName = (av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername); - mDisplayName = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); + mName = av_name.getUserName(); + mDisplayName = av_name.getDisplayName(); mNeedsRefresh = true; if(mParent != NULL) { diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index c68577db75..ff0e01a200 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -1520,8 +1520,8 @@ void LLFavoritesOrderStorage::saveFavoritesSLURLs() LLAvatarName av_name; LLAvatarNameCache::get( gAgentID, &av_name ); - lldebugs << "Saved favorites for " << av_name.getLegacyName() << llendl; - fav_llsd[av_name.getLegacyName()] = user_llsd; + lldebugs << "Saved favorites for " << av_name.getUserName() << llendl; + fav_llsd[av_name.getUserName()] = user_llsd; llofstream file; file.open(filename); @@ -1539,10 +1539,10 @@ void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() LLAvatarName av_name; LLAvatarNameCache::get( gAgentID, &av_name ); - lldebugs << "Removed favorites for " << av_name.getLegacyName() << llendl; - if (fav_llsd.has(av_name.getLegacyName())) + lldebugs << "Removed favorites for " << av_name.getUserName() << llendl; + if (fav_llsd.has(av_name.getUserName())) { - fav_llsd.erase(av_name.getLegacyName()); + fav_llsd.erase(av_name.getUserName()); } llofstream out_file; diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 6ada809cdb..f7dd4a4a6b 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -307,9 +307,9 @@ void LLFloaterAvatarPicker::populateNearMe() else { element["columns"][0]["column"] = "name"; - element["columns"][0]["value"] = av_name.mDisplayName; + element["columns"][0]["value"] = av_name.getDisplayName(); element["columns"][1]["column"] = "username"; - element["columns"][1]["value"] = av_name.mUsername; + element["columns"][1]["value"] = av_name.getUserName(); sAvatarNameMap[av] = av_name; } @@ -505,9 +505,7 @@ void LLFloaterAvatarPicker::find() LLViewerRegion* region = gAgent.getRegion(); url = region->getCapability("AvatarPickerSearch"); // Prefer use of capabilities to search on both SLID and display name - // but allow display name search to be manually turned off for test - if (!url.empty() - && LLAvatarNameCache::useDisplayNames()) + if (!url.empty()) { // capability urls don't end in '/', but we need one to parse // query parameters correctly @@ -679,9 +677,7 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void* found_one = TRUE; LLAvatarName av_name; - av_name.mLegacyFirstName = first_name; - av_name.mLegacyLastName = last_name; - av_name.mDisplayName = avatar_name; + av_name.fromString(avatar_name); const LLUUID& agent_id = avatar_id; sAvatarNameMap[agent_id] = av_name; diff --git a/indra/newview/llfloaterdisplayname.cpp b/indra/newview/llfloaterdisplayname.cpp index ac8f107928..be1ee77152 100644 --- a/indra/newview/llfloaterdisplayname.cpp +++ b/indra/newview/llfloaterdisplayname.cpp @@ -164,10 +164,9 @@ void LLFloaterDisplayName::onCancel() void LLFloaterDisplayName::onReset() { - if (LLAvatarNameCache::useDisplayNames()) + if (LLAvatarNameCache::hasNameLookupURL()) { - LLViewerDisplayName::set("", - boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3)); + LLViewerDisplayName::set("",boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3)); } else { @@ -199,10 +198,9 @@ void LLFloaterDisplayName::onSave() return; } - if (LLAvatarNameCache::useDisplayNames()) + if (LLAvatarNameCache::hasNameLookupURL()) { - LLViewerDisplayName::set(display_name_utf8, - boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3)); + LLViewerDisplayName::set(display_name_utf8,boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3)); } else { diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index a20fce876c..24b0355fca 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -545,7 +545,7 @@ void LLFloaterIMNearbyChat::addMessage(const LLChat& chat,bool archive,const LLS LLAvatarName av_name; LLAvatarNameCache::get(chat.mFromID, &av_name); - if (!av_name.mIsDisplayNameDefault) + if (!av_name.isDisplayNameDefault()) { from_name = av_name.getCompleteName(); } diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index a50907601c..8d8bba7b17 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -602,15 +602,7 @@ void LLPanelScriptLimitsRegionMemory::onNameCache( return; } - std::string name; - if (LLAvatarNameCache::useDisplayNames()) - { - name = LLCacheName::buildUsername(full_name); - } - else - { - name = full_name; - } + std::string name = LLCacheName::buildUsername(full_name); std::vector<LLSD>::iterator id_itor; for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor) @@ -713,10 +705,7 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) else { name_is_cached = gCacheName->getFullName(owner_id, owner_buf); // username - if (LLAvatarNameCache::useDisplayNames()) - { - owner_buf = LLCacheName::buildUsername(owner_buf); - } + owner_buf = LLCacheName::buildUsername(owner_buf); } if(!name_is_cached) { diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 484ecbcd04..c97a6792f3 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -238,7 +238,7 @@ void LLFloaterSellLandUI::updateParcelInfo() void LLFloaterSellLandUI::onBuyerNameCache(const LLAvatarName& av_name) { getChild<LLUICtrl>("sell_to_agent")->setValue(av_name.getCompleteName()); - getChild<LLUICtrl>("sell_to_agent")->setToolTip(av_name.mUsername); + getChild<LLUICtrl>("sell_to_agent")->setToolTip(av_name.getUserName()); } void LLFloaterSellLandUI::setBadge(const char* id, Badge badge) diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp index 2d91a61b54..7530c72dd2 100644 --- a/indra/newview/llfloatertopobjects.cpp +++ b/indra/newview/llfloatertopobjects.cpp @@ -199,17 +199,9 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data) // Owner names can have trailing spaces sent from server LLStringUtil::trim(owner_buf); - if (LLAvatarNameCache::useDisplayNames()) - { - // ...convert hard-coded name from server to a username - // *TODO: Send owner_id from server and look up display name - owner_buf = LLCacheName::buildUsername(owner_buf); - } - else - { - // ...just strip out legacy "Resident" name - owner_buf = LLCacheName::cleanFullName(owner_buf); - } + // *TODO: Send owner_id from server and look up display name + owner_buf = LLCacheName::buildUsername(owner_buf); + columns[column_num]["column"] = "owner"; columns[column_num]["value"] = owner_buf; columns[column_num++]["font"] = "SANSSERIF"; diff --git a/indra/newview/llfloatervoicevolume.cpp b/indra/newview/llfloatervoicevolume.cpp index 87b388b30a..a1df73a065 100644 --- a/indra/newview/llfloatervoicevolume.cpp +++ b/indra/newview/llfloatervoicevolume.cpp @@ -151,7 +151,7 @@ void LLFloaterVoiceVolume::updateVolumeControls() // By convention, we only display and toggle voice mutes, not all mutes bool is_muted = LLAvatarActions::isVoiceMuted(mAvatarID); - bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); + bool is_linden = LLStringUtil::endsWith(mAvatarName.getUserName(), " Linden"); mute_btn->setEnabled(!is_linden); mute_btn->setValue(is_muted); diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index a64ddd185d..0e72fab32c 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -533,7 +533,7 @@ void LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID) bool shouldBeAdded = true; LLAvatarName av_name; LLAvatarNameCache::get(avatarID, &av_name); - const std::string& name = av_name.mUsername; + const std::string& name = av_name.getUserName(); lldebugs << "Processing buddy name: " << name << ", id: " << avatarID diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index e5dda7e8d8..0de8f124ee 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -306,7 +306,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& void LLIMModel::LLIMSession::onAdHocNameCache(const LLAvatarName& av_name) { - if (av_name.mIsTemporaryName) + if (!av_name.isValidName()) { S32 separator_index = mName.rfind(" "); std::string name = mName.substr(0, separator_index); @@ -626,15 +626,7 @@ void LLIMModel::LLIMSession::buildHistoryFileName() // so no need for a callback in LLAvatarNameCache::get() if (LLAvatarNameCache::get(mOtherParticipantID, &av_name)) { - if (av_name.mUsername.empty()) - { - // Display names are off, use mDisplayName which will be the legacy name - mHistoryFileName = LLCacheName::buildUsername(av_name.mDisplayName); - } - else - { - mHistoryFileName = av_name.mUsername; - } + mHistoryFileName = LLCacheName::buildUsername(av_name.getUserName()); } else { @@ -836,7 +828,7 @@ bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, LLAvatarName av_name; if (!from_id.isNull() && LLAvatarNameCache::get(from_id, &av_name) && - !av_name.mIsDisplayNameDefault) + !av_name.isDisplayNameDefault()) { from_name = av_name.getCompleteName(); } @@ -1926,7 +1918,7 @@ void LLOutgoingCallDialog::show(const LLSD& key) LLAvatarName av_name; if (LLAvatarNameCache::get(callee_id, &av_name)) { - final_callee_name = av_name.mDisplayName; + final_callee_name = av_name.getDisplayName(); title = av_name.getCompleteName(); } } @@ -2464,7 +2456,7 @@ void LLIMMgr::addMessage( LLAvatarName av_name; if (LLAvatarNameCache::get(other_participant_id, &av_name) && !name_is_setted) { - fixed_session_name = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); + fixed_session_name = av_name.getDisplayName(); } LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg); @@ -3110,7 +3102,7 @@ void LLIMMgr::noteOfflineUsers( { LLUIString offline = LLTrans::getString("offline_message"); // Use display name only because this user is your friend - offline.setArg("[NAME]", av_name.mDisplayName); + offline.setArg("[NAME]", av_name.getDisplayName()); im_model.proccessOnlineOfflineNotification(session_id, offline); } } diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 8a15cd279f..3507b729be 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -263,9 +263,9 @@ void LLInspectAvatar::onAvatarNameCache( { if (agent_id == mAvatarID) { - getChild<LLUICtrl>("user_name")->setValue(av_name.mDisplayName); - getChild<LLUICtrl>("user_name_small")->setValue(av_name.mDisplayName); - getChild<LLUICtrl>("user_slid")->setValue(av_name.mUsername); + getChild<LLUICtrl>("user_name")->setValue(av_name.getDisplayName()); + getChild<LLUICtrl>("user_name_small")->setValue(av_name.getDisplayName()); + getChild<LLUICtrl>("user_slid")->setValue(av_name.getUserName()); mAvatarName = av_name; // show smaller display name if too long to display in regular size diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 73631f4ba8..bad4e8c231 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4712,10 +4712,9 @@ void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string act gCacheName->getFullName(item->getCreatorUUID(), callingcard_name); // IDEVO LLAvatarName av_name; - if (LLAvatarNameCache::useDisplayNames() - && LLAvatarNameCache::get(item->getCreatorUUID(), &av_name)) + if (LLAvatarNameCache::get(item->getCreatorUUID(), &av_name)) { - callingcard_name = av_name.mDisplayName + " (" + av_name.mUsername + ")"; + callingcard_name = av_name.getCompleteName(); } LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID()); if (session_id != LLUUID::null) diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index b0fbad33b0..855007e403 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -320,7 +320,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( else if (LLAvatarNameCache::get(id, &av_name)) { if (mShortNames) - fullname = av_name.mDisplayName; + fullname = av_name.getDisplayName(); else fullname = av_name.getCompleteName(); } @@ -390,7 +390,7 @@ void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id, { std::string name; if (mShortNames) - name = av_name.mDisplayName; + name = av_name.getDisplayName(); else name = av_name.getCompleteName(); diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index 7612af8f5e..b4deb7a920 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -224,7 +224,7 @@ void LLPanelBlockedList::onFilterEdit(const std::string& search_string) void LLPanelBlockedList::callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names) { if (names.empty() || ids.empty()) return; - LLMute mute(ids[0], names[0].getLegacyName(), LLMute::AGENT); + LLMute mute(ids[0], names[0].getUserName(), LLMute::AGENT); LLMuteList::getInstance()->add(mute); showPanelAndSelect(mute.mID); } diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index 7efeb77e23..a2bbc5400c 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -482,7 +482,7 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids) } else { - names.push_back(av_name.getLegacyName()); + names.push_back(av_name.getUserName()); } } } @@ -495,7 +495,7 @@ void LLPanelGroupInvite::addUserCallback(const LLUUID& id, const LLAvatarName& a std::vector<std::string> names; uuid_vec_t agent_ids; agent_ids.push_back(id); - names.push_back(av_name.getLegacyName()); + names.push_back(av_name.getUserName()); mImplementation->addUsers(names, agent_ids); } diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 31c0e3d01a..93b108efcc 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -543,10 +543,7 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg) msg->getU32("Data","Timestamp",timestamp,i); // we only have the legacy name here, convert it to a username - if (LLAvatarNameCache::useDisplayNames()) - { - name = LLCacheName::buildUsername(name); - } + name = LLCacheName::buildUsername(name); LLSD row; row["id"] = id; diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 5720168f81..7ad7e7149b 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -1616,7 +1616,7 @@ void LLPanelGroupMembersSubTab::onNameCache(const LLUUID& update_id, LLGroupMemb } // trying to avoid unnecessary hash lookups - if (matchesSearchFilter(av_name.getLegacyName())) + if (matchesSearchFilter(av_name.getUserName())) { addMemberToList(id, member); if(!mMembersList->getEnabled()) @@ -1670,7 +1670,7 @@ void LLPanelGroupMembersSubTab::updateMembers() LLAvatarName av_name; if (LLAvatarNameCache::get(mMemberProgress->first, &av_name)) { - if (matchesSearchFilter(av_name.getLegacyName())) + if (matchesSearchFilter(av_name.getUserName())) { addMemberToList(mMemberProgress->first, mMemberProgress->second); } diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 6c838f8a45..c53760bca1 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -381,7 +381,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) // Create a participant view model instance LLAvatarName avatar_name; bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name); - participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.mDisplayName , avatar_id, mRootViewModel); + participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.getDisplayName() , avatar_id, mRootViewModel); participant->fetchAvatarName(); } else diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index ed350ea144..4dc0d424ac 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -69,10 +69,8 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(const LLNotificationPtr& notifi //header title std::string from_name = payload["sender_name"].asString(); - if (LLAvatarNameCache::useDisplayNames()) - { - from_name = LLCacheName::buildUsername(from_name); - } + from_name = LLCacheName::buildUsername(from_name); + std::stringstream from; from << from_name << "/" << groupData.mName; LLTextBox* pTitleText = getChild<LLTextBox>("title"); diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 3cd761b73b..c81f6ace70 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -991,8 +991,7 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l } LLAvatarName av_name; - if (LLAvatarNameCache::useDisplayNames() && - LLAvatarNameCache::get(hover_object->getID(), &av_name)) + if (LLAvatarNameCache::get(hover_object->getID(), &av_name)) { final_name = av_name.getCompleteName(); } diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp index 5741fab29a..4bd38562bc 100644 --- a/indra/newview/llviewerdisplayname.cpp +++ b/indra/newview/llviewerdisplayname.cpp @@ -97,7 +97,7 @@ void LLViewerDisplayName::set(const std::string& display_name, const set_name_sl // People API expects array of [ "old value", "new value" ] LLSD change_array = LLSD::emptyArray(); - change_array.append(av_name.mDisplayName); + change_array.append(av_name.getDisplayName()); change_array.append(display_name); llinfos << "Set name POST to " << cap_url << llendl; @@ -189,8 +189,8 @@ class LLDisplayNameUpdate : public LLHTTPNode LLSD args; args["OLD_NAME"] = old_display_name; - args["SLID"] = av_name.mUsername; - args["NEW_NAME"] = av_name.mDisplayName; + args["SLID"] = av_name.getUserName(); + args["NEW_NAME"] = av_name.getDisplayName(); LLNotificationsUtil::add("DisplayNameUpdate", args); if (agent_id == gAgent.getID()) { diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 511807ec2f..5284d2650e 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -8080,11 +8080,7 @@ class LLWorldPostProcess : public view_listener_t void handle_flush_name_caches() { - // Toggle display names on and off to flush - bool use_display_names = LLAvatarNameCache::useDisplayNames(); - LLAvatarNameCache::setUseDisplayNames(!use_display_names); - LLAvatarNameCache::setUseDisplayNames(use_display_names); - + LLAvatarNameCache::flushCache(); if (gCacheName) gCacheName->clear(); } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index dc8192105f..6397ef7961 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2245,16 +2245,7 @@ static std::string clean_name_from_task_im(const std::string& msg, // Don't try to clean up group names if (!from_group) { - if (LLAvatarNameCache::useDisplayNames()) - { - // ...just convert to username - final += LLCacheName::buildUsername(name); - } - else - { - // ...strip out legacy "Resident" name - final += LLCacheName::cleanFullName(name); - } + final += LLCacheName::buildUsername(name); } final += match[3].str(); return final; @@ -2268,7 +2259,7 @@ void notification_display_name_callback(const LLUUID& id, LLSD& substitutions, const LLSD& payload) { - substitutions["NAME"] = av_name.mDisplayName; + substitutions["NAME"] = av_name.getDisplayName(); LLNotificationsUtil::add(name, substitutions, payload); } @@ -3452,7 +3443,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) LLAvatarName av_name; if (LLAvatarNameCache::get(from_id, &av_name)) { - chat.mFromName = av_name.mDisplayName; + chat.mFromName = av_name.getDisplayName(); } else { diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 220c4ef59a..7cc4e3ed04 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3188,29 +3188,27 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames"); static LLUICachedControl<bool> show_usernames("NameTagShowUsernames"); - if (LLAvatarNameCache::useDisplayNames()) + if (LLAvatarName::useDisplayNames()) { LLAvatarName av_name; if (!LLAvatarNameCache::get(getID(), &av_name)) { - // ...call this function back when the name arrives - // and force a rebuild - LLAvatarNameCache::get(getID(), - boost::bind(&LLVOAvatar::clearNameTag, this)); + // ...call this function back when the name arrives and force a rebuild + LLAvatarNameCache::get(getID(),boost::bind(&LLVOAvatar::clearNameTag, this)); } // Might be blank if name not available yet, that's OK if (show_display_names) { - addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, + addNameTagLine(av_name.getDisplayName(), name_tag_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerif()); } // Suppress SLID display if display name matches exactly (ugh) - if (show_usernames && !av_name.mIsDisplayNameDefault) + if (show_usernames && !av_name.isDisplayNameDefault()) { // *HACK: Desaturate the color LLColor4 username_color = name_tag_color * 0.83f; - addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, + addNameTagLine(av_name.getUserName(), username_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerifSmall()); } } @@ -3421,20 +3419,18 @@ LLColor4 LLVOAvatar::getNameTagColor(bool is_friend) { color_name = "NameTagFriend"; } - else if (LLAvatarNameCache::useDisplayNames()) + else if (LLAvatarName::useDisplayNames()) { - // ...color based on whether username "matches" a computed display - // name + // ...color based on whether username "matches" a computed display name LLAvatarName av_name; - if (LLAvatarNameCache::get(getID(), &av_name) - && av_name.mIsDisplayNameDefault) + if (LLAvatarNameCache::get(getID(), &av_name) && av_name.isDisplayNameDefault()) { color_name = "NameTagMatch"; } else { color_name = "NameTagMismatch"; - } + } } else { diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 37491e5b58..6fdda12a1c 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -2668,7 +2668,7 @@ void LLVivoxVoiceClient::checkFriend(const LLUUID& id) // *NOTE: For now, we feed legacy names to Vivox because I don't know // if their service can support a mix of new and old clients with // different sorts of names. - std::string name = av_name.getLegacyName(); + std::string name = av_name.getUserName(); const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id); bool canSeeMeOnline = false; @@ -6200,7 +6200,7 @@ void LLVivoxVoiceClient::lookupName(const LLUUID &id) void LLVivoxVoiceClient::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) { - std::string display_name = av_name.mDisplayName; + std::string display_name = av_name.getDisplayName(); avatarNameResolved(agent_id, display_name); } -- cgit v1.2.3 From 5f6d55eb1b264780fbb703b115e9b4428cc4ee2b Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Thu, 6 Dec 2012 15:19:10 +0200 Subject: CHUI-444 (Click target off when conversation list is minimized to icons) --- indra/llui/llfolderviewitem.cpp | 4 ++-- indra/llui/llfolderviewitem.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 9b54a7a467..9facf65802 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1863,7 +1863,7 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) } if( !handled ) { - if(mIndentation < x && x < mIndentation + (isMinimized() ? 0 : mArrowSize) + mTextPad) + if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) { toggleOpen(); handled = TRUE; @@ -1887,7 +1887,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) } if( !handled ) { - if(mIndentation < x && x < mIndentation + (isMinimized() ? 0 : mArrowSize) + mTextPad) + if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) { // don't select when user double-clicks plus sign // so as not to contradict single-click behavior diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 2e633a39e5..a35193f948 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -292,7 +292,7 @@ protected: friend class LLUICtrlFactory; void updateLabelRotation(); - virtual bool isMinimized() { return FALSE; } + virtual bool isCollapsed() { return FALSE; } public: typedef std::list<LLFolderViewItem*> items_t; -- cgit v1.2.3 From 272d438ce299fab146e9a30046b7591de7467511 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Thu, 6 Dec 2012 18:23:30 +0200 Subject: CHUI-576 (Group moderation menus do not work in torn off dialogs) --- indra/newview/llfloaterimcontainer.cpp | 20 +++++++++++++------- indra/newview/llfloaterimsessiontab.cpp | 12 ++++++++++++ indra/newview/llfloaterimsessiontab.h | 1 + 3 files changed, 26 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c1daea0aeb..257c17a058 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -850,8 +850,16 @@ const LLConversationItem * LLFloaterIMContainer::getCurSelectedViewModelItem() mConversationsRoot->getCurSelectedItem() && mConversationsRoot->getCurSelectedItem()->getViewModelItem()) { - conversationItem = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem()); - } + LLFloaterIMSessionTab *selectedSession = LLFloaterIMSessionTab::getConversation(mSelectedSession); + if (selectedSession && selectedSession->isTornOff()) + { + conversationItem = selectedSession->getCurSelectedViewModelItem(); + } + else + { + conversationItem = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem()); + } + } return conversationItem; } @@ -1532,21 +1540,19 @@ void LLFloaterIMContainer::moderateVoiceParticipant(const LLUUID& avatar_id, boo LLSpeakerMgr * LLFloaterIMContainer::getSpeakerMgrForSelectedParticipant() { - LLFolderViewItem * selected_folder_itemp = mConversationsRoot->getCurSelectedItem(); - if (NULL == selected_folder_itemp) + LLFolderViewItem *selectedItem = mConversationsRoot->getCurSelectedItem(); + if (NULL == selectedItem) { llwarns << "Current selected item is null" << llendl; return NULL; } - LLFolderViewFolder * conversation_itemp = selected_folder_itemp->getParentFolder(); - conversations_widgets_map::const_iterator iter = mConversationsWidgets.begin(); conversations_widgets_map::const_iterator end = mConversationsWidgets.end(); const LLUUID * conversation_uuidp = NULL; while(iter != end) { - if (iter->second == conversation_itemp) + if (iter->second == selectedItem || iter->second == selectedItem->getParentFolder()) { conversation_uuidp = &iter->first; break; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index d04fa2674d..85d1b1fb49 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -831,4 +831,16 @@ void LLFloaterIMSessionTab::getSelectedUUIDs(uuid_vec_t& selected_uuids) } } +LLConversationItem* LLFloaterIMSessionTab::getCurSelectedViewModelItem() +{ + LLConversationItem *conversationItem = NULL; + if(mConversationsRoot && + mConversationsRoot->getCurSelectedItem() && + mConversationsRoot->getCurSelectedItem()->getViewModelItem()) + { + conversationItem = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem()) ; + } + + return conversationItem; +} diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 8efa0955fc..4851904074 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -94,6 +94,7 @@ public: virtual void onTearOffClicked(); virtual void updateMessages() {} + LLConversationItem* getCurSelectedViewModelItem(); protected: -- cgit v1.2.3 From e2c080b5582d08302d1deaf1fb64cab1a67c138a Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 6 Dec 2012 19:26:52 +0200 Subject: CHUI-505 FIXED Open Call Log if user has new events while out: force open Conversation Log Floater when received a saved offline message --- indra/newview/llimview.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 821e62c4e6..ea123d3f15 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -30,6 +30,7 @@ #include "llavatarnamecache.h" // IDEVO #include "llavataractions.h" +#include "llfloaterconversationlog.h" #include "llfloaterreg.h" #include "llfontgl.h" #include "llgl.h" @@ -2467,6 +2468,18 @@ void LLIMMgr::addMessage( new_session_id = computeSessionID(dialog, other_participant_id); } + // Open conversation log if offline messages are present + if (is_offline_msg) + { + LLFloaterConversationLog* floater_log = + LLFloaterReg::getTypedInstance<LLFloaterConversationLog>("conversation"); + if (floater_log && !(floater_log->isFrontmost())) + { + floater_log->openFloater(); + floater_log->setFrontmost(TRUE); + } + } + //*NOTE session_name is empty in case of incoming P2P sessions std::string fixed_session_name = from; bool name_is_setted = false; -- cgit v1.2.3 From 218cbebbd8bdbfadc954731ee54f6472ed847139 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 6 Dec 2012 15:52:55 -0800 Subject: CHUI-579: When the 'Pop up message' preference is set the conversation line item and/or FUI button flash depending on what is focused. Also when the 'Flash the toolbar button' preference is set the FUI button will flash or the line item will flash depending upon what is focused. --- indra/newview/llimview.cpp | 65 ++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 25 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 821e62c4e6..1a2632f921 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -155,57 +155,72 @@ void on_new_message(const LLSD& msg) // execution of the action + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); + + bool sessionFloaterInActive = session_floater + && (!session_floater->isInVisibleChain()) //conversation floater not displayed + || + (session_floater->isInVisibleChain() && session_floater->hasFocus() == false); //conversation floater is displayed but doesn't have focus + if ("toast" == action) { // Skip toasting if we have open window of IM with this session id - LLFloaterIMSession* open_im_floater = LLFloaterIMSession::findInstance(session_id); if ( - open_im_floater - && open_im_floater->isInVisibleChain() - && open_im_floater->hasFocus() - && !open_im_floater->isMinimized() - && !(open_im_floater->getHost() - && open_im_floater->getHost()->isMinimized()) + session_floater + && session_floater->isInVisibleChain() + && session_floater->hasFocus() + && !session_floater->isMinimized() + && !(session_floater->getHost() + && session_floater->getHost()->isMinimized()) ) { return; } // Skip toasting for system messages and for nearby chat - if (participant_id.isNull() || session_id.isNull()) + if (participant_id.isNull()) { return; } - //Show toast - LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); + //Show IM toasts (upper right toasts) + if(session_id.notNull()) + { + LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); + } + + //Session floater has focus, so don't need to show notification flashes + if(sessionFloaterInActive) + { + //Flash converstation line item anytime that conversation doesn't have focus + im_box->flashConversationItemWidget(session_id, true); + + //Only flash the 'Chat' FUI button when the conversation floater isn't focused (implies not front most floater) + if(!im_box->hasFocus()) + { + gToolBarView->flashCommand(LLCommandId("chat"), true); + } + } } else if ("flash" == action) { - LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); - if (im_box) + if(sessionFloaterInActive && !im_box->hasFocus()) + { + gToolBarView->flashCommand(LLCommandId("chat"), true); // flashing of the FUI button "Chat" + } + else if(sessionFloaterInActive) { im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item } - gToolBarView->flashCommand(LLCommandId("chat"), true); // flashing of the FUI button "Chat" } else if("openconversations" == action) { - LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); - LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); - //Don't flash and show conversation floater when conversation already active (has focus) - if(session_floater - && (!session_floater->isInVisibleChain()) //conversation floater not displayed - || - (session_floater->isInVisibleChain() && session_floater->hasFocus() == false)) //conversation floater is displayed but doesn't have focus - + if(sessionFloaterInActive) { //Flash line item - if (im_box) - { - im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item - } + im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item //Surface conversations floater LLFloaterReg::showInstance("im_container"); -- cgit v1.2.3 From 9da625d439a9a911733564177e32facc3669dc58 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Thu, 6 Dec 2012 20:28:25 -0800 Subject: CHUI-494: WIP First pass at getting the suppression of events in DND working. --- indra/newview/llbrowsernotification.cpp | 5 + indra/newview/llfloateroutbox.cpp | 17 +-- indra/newview/llimhandler.cpp | 2 +- indra/newview/llnotificationalerthandler.cpp | 28 ++++- indra/newview/llnotificationgrouphandler.cpp | 2 +- indra/newview/llnotificationhandler.h | 145 ++++++++++++++++---------- indra/newview/llnotificationhandlerutil.cpp | 12 ++- indra/newview/llnotificationhinthandler.cpp | 27 ++++- indra/newview/llnotificationofferhandler.cpp | 2 +- indra/newview/llnotificationscripthandler.cpp | 2 +- indra/newview/llnotificationtiphandler.cpp | 2 +- indra/newview/llviewerwindow.cpp | 31 ++---- indra/newview/llviewerwindow.h | 9 +- 13 files changed, 184 insertions(+), 100 deletions(-) (limited to 'indra') diff --git a/indra/newview/llbrowsernotification.cpp b/indra/newview/llbrowsernotification.cpp index 9e608d2c8b..19747757db 100644 --- a/indra/newview/llbrowsernotification.cpp +++ b/indra/newview/llbrowsernotification.cpp @@ -35,6 +35,11 @@ using namespace LLNotificationsUI; +LLBrowserNotification::LLBrowserNotification() + : LLSystemNotificationHandler("Browser", "browser") +{ +} + bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification) { LLUUID media_id = notification->getPayload()["media_id"].asUUID(); diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index 18ed36d0f3..29a3e6ac3a 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -49,6 +49,11 @@ /// LLOutboxNotification class ///---------------------------------------------------------------------------- +LLNotificationsUI::LLOutboxNotification::LLOutboxNotification() + : LLSystemNotificationHandler("Outbox", "outbox") +{ +} + bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotificationPtr& notify) { LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance<LLFloaterOutbox>("outbox"); @@ -60,10 +65,10 @@ bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotifi void LLNotificationsUI::LLOutboxNotification::onDelete(LLNotificationPtr p) { - LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler*>(LLNotifications::instance().getChannel("AlertModal").get()); - if (sys_handler) + LLNotificationsUI::LLNotificationHandler * notification_handler = dynamic_cast<LLNotificationsUI::LLNotificationHandler*>(LLNotifications::instance().getChannel("AlertModal").get()); + if (notification_handler) { - sys_handler->onDelete(p); + notification_handler->onDelete(p); } } @@ -524,9 +529,9 @@ void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content) void LLFloaterOutbox::showNotification(const LLNotificationPtr& notification) { - LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler*>(LLNotifications::instance().getChannel("AlertModal").get()); - llassert(sys_handler); + LLNotificationsUI::LLNotificationHandler * notification_handler = dynamic_cast<LLNotificationsUI::LLNotificationHandler*>(LLNotifications::instance().getChannel("AlertModal").get()); + llassert(notification_handler); - sys_handler->processNotification(notification); + notification_handler->processNotification(notification); } diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index 047472a282..72967eb6c7 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -38,7 +38,7 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLIMHandler::LLIMHandler() -: LLSysHandler("IM Notifications", "notifytoast") +: LLCommunicationNotificationHandler("IM Notifications", "notifytoast") { // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel()->getHandle(); diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index 2bc9cdd3c1..58a9b01a45 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -29,6 +29,7 @@ #include "llnotificationhandler.h" +#include "llagentcamera.h" #include "llnotifications.h" #include "llprogressview.h" #include "lltoastnotifypanel.h" @@ -41,7 +42,7 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLAlertHandler::LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal) -: LLSysHandler(name, notification_type), +: LLSystemNotificationHandler(name, notification_type), mIsModal(is_modal) { LLScreenChannelBase::Params p; @@ -123,3 +124,28 @@ void LLAlertHandler::onChange( LLNotificationPtr notification ) if(channel) channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); } + +//-------------------------------------------------------------------------- +LLViewerAlertHandler::LLViewerAlertHandler(const std::string& name, const std::string& notification_type) + : LLSystemNotificationHandler(name, notification_type) +{ +} + +bool LLViewerAlertHandler::processNotification(const LLNotificationPtr& p) +{ + if (gHeadlessClient) + { + LL_INFOS("LLViewerAlertHandler") << "Alert: " << p->getName() << LL_ENDL; + } + + // If we're in mouselook, the mouse is hidden and so the user can't click + // the dialog buttons. In that case, change to First Person instead. + if( gAgentCamera.cameraMouselook() ) + { + gAgentCamera.changeCameraToDefault(); + } + + return false; +} + + diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 18cd94e685..8fef102cf8 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -38,7 +38,7 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLGroupHandler::LLGroupHandler() -: LLSysHandler("Group Notifications", "groupnotify") +: LLCommunicationNotificationHandler("Group Notifications", "groupnotify") { // Getting a Channel for our notifications LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 4bded6ab30..98b0eecd0d 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -27,6 +27,7 @@ #ifndef LL_LLNOTIFICATIONHANDLER_H #define LL_LLNOTIFICATIONHANDLER_H +#include <boost/intrusive_ptr.hpp> #include "llwindow.h" @@ -86,23 +87,39 @@ protected: /** * Handler for system notifications. */ -class LLSysHandler : public LLEventHandler, public LLNotificationChannel +class LLNotificationHandler : public LLEventHandler, public LLNotificationChannel { public: - LLSysHandler(const std::string& name, const std::string& notification_type); - virtual ~LLSysHandler() {}; + LLNotificationHandler(const std::string& name, const std::string& notification_type, const std::string& parentName); + virtual ~LLNotificationHandler() {}; // base interface functions - /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());} + virtual void onAdd(LLNotificationPtr p) { processNotification(p); } + virtual void onChange(LLNotificationPtr p) { processNotification(p); } + virtual void onLoad(LLNotificationPtr p) { processNotification(p); } + virtual void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());} - virtual bool processNotification(const LLNotificationPtr& notify)=0; + virtual bool processNotification(const LLNotificationPtr& notify) = 0; +}; + +class LLSystemNotificationHandler : public LLNotificationHandler +{ +public: + LLSystemNotificationHandler(const std::string& name, const std::string& notification_type); + virtual ~LLSystemNotificationHandler() {}; +}; + +class LLCommunicationNotificationHandler : public LLNotificationHandler +{ +public: + LLCommunicationNotificationHandler(const std::string& name, const std::string& notification_type); + virtual ~LLCommunicationNotificationHandler() {}; }; /** - * Handler for chat message notifications. + * Handler for chat message notifications. */ +// XXX stinson 12/06/2012 : can I just remove the LLChatHandler class? class LLChatHandler : public LLEventHandler { public: @@ -115,67 +132,62 @@ public: * Handler for IM notifications. * It manages life time of IMs, group messages. */ -class LLIMHandler : public LLSysHandler +class LLIMHandler : public LLCommunicationNotificationHandler { public: LLIMHandler(); virtual ~LLIMHandler(); + bool processNotification(const LLNotificationPtr& p); protected: - bool processNotification(const LLNotificationPtr& p); - /*virtual*/ void initChannel(); + virtual void initChannel(); }; /** * Handler for system informational notices. * It manages life time of tip notices. */ -class LLTipHandler : public LLSysHandler +class LLTipHandler : public LLSystemNotificationHandler { public: LLTipHandler(); virtual ~LLTipHandler(); - // base interface functions - /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ bool processNotification(const LLNotificationPtr& p); + virtual bool processNotification(const LLNotificationPtr& p); protected: - /*virtual*/ void initChannel(); + virtual void initChannel(); }; /** * Handler for system informational notices. * It manages life time of script notices. */ -class LLScriptHandler : public LLSysHandler +class LLScriptHandler : public LLSystemNotificationHandler { public: LLScriptHandler(); virtual ~LLScriptHandler(); - /*virtual*/ void onDelete(LLNotificationPtr p); - // base interface functions - /*virtual*/ bool processNotification(const LLNotificationPtr& p); + virtual void onDelete(LLNotificationPtr p); + virtual bool processNotification(const LLNotificationPtr& p); protected: - /*virtual*/ void onDeleteToast(LLToast* toast); - /*virtual*/ void initChannel(); + virtual void onDeleteToast(LLToast* toast); + virtual void initChannel(); }; /** * Handler for group system notices. */ -class LLGroupHandler : public LLSysHandler +class LLGroupHandler : public LLCommunicationNotificationHandler { public: LLGroupHandler(); virtual ~LLGroupHandler(); - // base interface functions - /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ bool processNotification(const LLNotificationPtr& p); + virtual bool processNotification(const LLNotificationPtr& p); protected: virtual void initChannel(); @@ -184,15 +196,14 @@ protected: /** * Handler for alert system notices. */ -class LLAlertHandler : public LLSysHandler +class LLAlertHandler : public LLSystemNotificationHandler { public: LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal); virtual ~LLAlertHandler(); - /*virtual*/ void onChange(LLNotificationPtr p); - /*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ bool processNotification(const LLNotificationPtr& p); + virtual void onChange(LLNotificationPtr p); + virtual bool processNotification(const LLNotificationPtr& p); protected: virtual void initChannel(); @@ -200,67 +211,87 @@ protected: bool mIsModal; }; +class LLViewerAlertHandler : public LLSystemNotificationHandler +{ + LOG_CLASS(LLViewerAlertHandler); +public: + LLViewerAlertHandler(const std::string& name, const std::string& notification_type); + virtual ~LLViewerAlertHandler() {}; + + virtual void onDelete(LLNotificationPtr p) {}; + virtual bool processNotification(const LLNotificationPtr& p); + +protected: + virtual void initChannel() {}; +}; + +typedef boost::intrusive_ptr<LLViewerAlertHandler> LLViewerAlertHandlerPtr; + /** * Handler for offers notices. * It manages life time of offer notices. */ -class LLOfferHandler : public LLSysHandler +class LLOfferHandler : public LLCommunicationNotificationHandler { public: LLOfferHandler(); virtual ~LLOfferHandler(); - // base interface functions - /*virtual*/ void onChange(LLNotificationPtr p); - /*virtual*/ void onDelete(LLNotificationPtr notification); - /*virtual*/ bool processNotification(const LLNotificationPtr& p); + virtual void onChange(LLNotificationPtr p); + virtual void onDelete(LLNotificationPtr notification); + virtual bool processNotification(const LLNotificationPtr& p); protected: - /*virtual*/ void initChannel(); + virtual void initChannel(); }; /** * Handler for UI hints. */ -class LLHintHandler : public LLNotificationChannel +class LLHintHandler : public LLSystemNotificationHandler { public: - LLHintHandler() : LLNotificationChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint")) - {} + LLHintHandler(); virtual ~LLHintHandler() {} - /*virtual*/ void onAdd(LLNotificationPtr p); - /*virtual*/ void onLoad(LLNotificationPtr p); - /*virtual*/ void onDelete(LLNotificationPtr p); + virtual void onAdd(LLNotificationPtr p); + virtual void onLoad(LLNotificationPtr p); + virtual void onDelete(LLNotificationPtr p); + virtual bool processNotification(const LLNotificationPtr& p); + +protected: + virtual void initChannel() {}; }; /** * Handler for browser notifications */ -class LLBrowserNotification : public LLNotificationChannel +class LLBrowserNotification : public LLSystemNotificationHandler { public: - LLBrowserNotification() - : LLNotificationChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser")) - {} - /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } - bool processNotification(const LLNotificationPtr& p); + LLBrowserNotification(); + virtual ~LLBrowserNotification() {} + + virtual bool processNotification(const LLNotificationPtr& p); + +protected: + virtual void initChannel() {}; }; /** * Handler for outbox notifications */ -class LLOutboxNotification : public LLNotificationChannel +class LLOutboxNotification : public LLSystemNotificationHandler { public: - LLOutboxNotification() - : LLNotificationChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")) - {} - /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onChange(LLNotificationPtr p) { } - /*virtual*/ void onDelete(LLNotificationPtr p); - bool processNotification(const LLNotificationPtr& p); + LLOutboxNotification(); + virtual ~LLOutboxNotification() {}; + virtual void onChange(LLNotificationPtr p) { } + virtual void onDelete(LLNotificationPtr p); + virtual bool processNotification(const LLNotificationPtr& p); + +protected: + virtual void initChannel() {}; }; class LLHandlerUtil diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 7f1216ff40..f0175d677c 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -41,8 +41,16 @@ using namespace LLNotificationsUI; -LLSysHandler::LLSysHandler(const std::string& name, const std::string& notification_type) -: LLNotificationChannel(name, "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, notification_type)) +LLNotificationHandler::LLNotificationHandler(const std::string& name, const std::string& notification_type, const std::string& parentName) +: LLNotificationChannel(name, parentName, LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, notification_type)) +{} + +LLSystemNotificationHandler::LLSystemNotificationHandler(const std::string& name, const std::string& notification_type) + : LLNotificationHandler(name, notification_type, "System") +{} + +LLCommunicationNotificationHandler::LLCommunicationNotificationHandler(const std::string& name, const std::string& notification_type) + : LLNotificationHandler(name, notification_type, "Communication") {} // static diff --git a/indra/newview/llnotificationhinthandler.cpp b/indra/newview/llnotificationhinthandler.cpp index 271f418507..f40369a2e0 100644 --- a/indra/newview/llnotificationhinthandler.cpp +++ b/indra/newview/llnotificationhinthandler.cpp @@ -33,6 +33,27 @@ using namespace LLNotificationsUI; -void LLHintHandler::onAdd(LLNotificationPtr p) { LLHints::show(p); } -void LLHintHandler::onLoad(LLNotificationPtr p) { LLHints::show(p); } -void LLHintHandler::onDelete(LLNotificationPtr p) { LLHints::hide(p); } +LLHintHandler::LLHintHandler() + : LLSystemNotificationHandler("Hints", "hint") +{ +} + +void LLHintHandler::onAdd(LLNotificationPtr p) +{ + LLHints::show(p); +} + +void LLHintHandler::onLoad(LLNotificationPtr p) +{ + LLHints::show(p); +} + +void LLHintHandler::onDelete(LLNotificationPtr p) +{ + LLHints::hide(p); +} + +bool LLHintHandler::processNotification(const LLNotificationPtr& p) +{ + return false; +} diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index ff5b5e21f7..da38c9063b 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -41,7 +41,7 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLOfferHandler::LLOfferHandler() -: LLSysHandler("Offer", "offer") +: LLCommunicationNotificationHandler("Offer", "offer") { // Getting a Channel for our notifications LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 290a81f91c..e2d4e9f8ce 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -39,7 +39,7 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLScriptHandler::LLScriptHandler() -: LLSysHandler("Notifications", "notify") +: LLSystemNotificationHandler("Notifications", "notify") { // Getting a Channel for our notifications LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index faa67b5ea4..a85335f1ba 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -42,7 +42,7 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLTipHandler::LLTipHandler() -: LLSysHandler("NotificationTips", "notifytip") +: LLSystemNotificationHandler("NotificationTips", "notifytip") { // Getting a Channel for our notifications LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 1b45e6f85d..7b1cf6e180 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -39,6 +39,7 @@ #include "llagentcamera.h" #include "llfloaterreg.h" #include "llmeshrepository.h" +#include "llnotificationhandler.h" #include "llpanellogin.h" #include "llviewerkeyboard.h" #include "llviewermenu.h" @@ -127,6 +128,7 @@ #include "llmorphview.h" #include "llmoveview.h" #include "llnavigationbar.h" +#include "llnotificationhandler.h" #include "llpanelpathfindingrebakenavmesh.h" #include "llpaneltopinfobar.h" #include "llpopupview.h" @@ -1554,11 +1556,13 @@ LLViewerWindow::LLViewerWindow(const Params& p) mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard))); mViewerWindowListener.reset(new LLViewerWindowListener(this)); - mAlertsChannel.reset(new LLNotificationChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"))); - mModalAlertsChannel.reset(new LLNotificationChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"))); + mSystemChannel.reset(new LLNotificationChannel("System", "Visible", LLNotificationFilters::includeEverything)); + mCommunicationChannel.reset(new LLNotificationChannel("Communication", "Visible", boost::bind(&LLAgent::isDoNotDisturb, &gAgent))); + mAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alerts", "alert")); + mModalAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alertmodal", "alertmodal")); - mAlertsChannel->connectChanged(&LLViewerWindow::onAlert); - mModalAlertsChannel->connectChanged(&LLViewerWindow::onAlert); + //mAlertsChannel->connectChanged(&LLViewerWindow::onAlert); + //mModalAlertsChannel->connectChanged(&LLViewerWindow::onAlert); bool ignore = gSavedSettings.getBOOL("IgnoreAllNotifications"); LLNotifications::instance().setIgnoreAllNotifications(ignore); if (ignore) @@ -5001,25 +5005,6 @@ LLRect LLViewerWindow::getChatConsoleRect() //---------------------------------------------------------------------------- -//static -bool LLViewerWindow::onAlert(const LLSD& notify) -{ - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if (gHeadlessClient) - { - llinfos << "Alert: " << notification->getName() << llendl; - } - - // If we're in mouselook, the mouse is hidden and so the user can't click - // the dialog buttons. In that case, change to First Person instead. - if( gAgentCamera.cameraMouselook() ) - { - gAgentCamera.changeCameraToDefault(); - } - return false; -} - void LLViewerWindow::setUIVisibility(bool visible) { mUIVisible = visible; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index ee6a7793f8..b828a05384 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -43,6 +43,8 @@ #include "lltimer.h" #include "llstat.h" #include "llmousehandler.h" +#include "llnotifications.h" +#include "llnotificationhandler.h" #include "llhandle.h" #include "llinitparam.h" @@ -401,7 +403,6 @@ public: private: bool shouldShowToolTipFor(LLMouseHandler *mh); - static bool onAlert(const LLSD& notify); void switchToolByMask(MASK mask); void destroyWindow(); @@ -418,8 +419,10 @@ private: bool mActive; bool mUIVisible; - boost::shared_ptr<class LLNotificationChannel> mAlertsChannel, - mModalAlertsChannel; + LLNotificationChannelPtr mSystemChannel; + LLNotificationChannelPtr mCommunicationChannel; + LLNotificationsUI::LLViewerAlertHandlerPtr mAlertsChannel; + LLNotificationsUI::LLViewerAlertHandlerPtr mModalAlertsChannel; LLRect mWindowRectRaw; // whole window, including UI LLRect mWindowRectScaled; // whole window, scaled by UI size -- cgit v1.2.3 From bb322a1cccd3fab28951ad4e11b5edcfc4e48140 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 7 Dec 2012 00:10:50 -0800 Subject: CHUI-580 : Fixed : Clean up the use of display name. Allow the use of the legacy protocol in settings.xml --- indra/llcommon/llavatarname.cpp | 75 ++++++++++---- indra/llcommon/llavatarname.h | 13 ++- indra/llmessage/llavatarnamecache.cpp | 170 +++++++++++--------------------- indra/llmessage/llavatarnamecache.h | 32 +++--- indra/llmessage/llcachename.h | 2 +- indra/llui/tests/llurlentry_stub.cpp | 5 - indra/newview/app_settings/settings.xml | 11 +++ indra/newview/llstartup.cpp | 2 +- indra/newview/llviewermenu.cpp | 2 +- 9 files changed, 154 insertions(+), 158 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp index b49e6a7aac..95ecce509b 100644 --- a/indra/llcommon/llavatarname.cpp +++ b/indra/llcommon/llavatarname.cpp @@ -45,6 +45,12 @@ static const std::string DISPLAY_NAME_NEXT_UPDATE("display_name_next_update"); bool LLAvatarName::sUseDisplayNames = true; +// Minimum time-to-live (in seconds) for a name entry. +// Avatar name should always guarantee to expire reasonably soon by default +// so if the failure to get a valid expiration time was due to something temporary +// we will eventually request and get the right data. +const F64 MIN_ENTRY_LIFETIME = 60.0; + LLAvatarName::LLAvatarName() : mUsername(), mDisplayName(), @@ -107,40 +113,67 @@ void LLAvatarName::fromLLSD(const LLSD& sd) } } -void LLAvatarName::fromString(const std::string& full_name, F64 expires) +// Transform a string (typically provided by the legacy service) into a decent +// avatar name instance. +void LLAvatarName::fromString(const std::string& full_name) { mDisplayName = full_name; std::string::size_type index = full_name.find(' '); if (index != std::string::npos) { + // The name is in 2 parts (first last) mLegacyFirstName = full_name.substr(0, index); mLegacyLastName = full_name.substr(index+1); - mUsername = mLegacyFirstName + " " + mLegacyLastName; + if (mLegacyLastName != "Resident") + { + mUsername = mLegacyFirstName + "." + mLegacyLastName; + mDisplayName = full_name; + LLStringUtil::toLower(mUsername); + } + else + { + // Very old names do have a dummy "Resident" last name + // that we choose to hide from users. + mUsername = mLegacyFirstName; + mDisplayName = mLegacyFirstName; + } } else { mLegacyFirstName = full_name; mLegacyLastName = ""; mUsername = full_name; + mDisplayName = full_name; } mIsDisplayNameDefault = true; mIsTemporaryName = true; + setExpires(MIN_ENTRY_LIFETIME); +} + +void LLAvatarName::setExpires(F64 expires) +{ mExpires = LLFrameTimer::getTotalSeconds() + expires; } std::string LLAvatarName::getCompleteName() const { std::string name; - if (mUsername.empty() || mIsDisplayNameDefault) - // If the display name feature is off - // OR this particular display name is defaulted (i.e. based on user name), - // then display only the easier to read instance of the person's name. + if (sUseDisplayNames) { - name = mDisplayName; + if (mUsername.empty() || mIsDisplayNameDefault) + { + // If this particular display name is defaulted (i.e. based on user name), + // then display only the easier to read instance of the person's name. + name = mDisplayName; + } + else + { + name = mDisplayName + " (" + mUsername + ")"; + } } else { - name = mDisplayName + " (" + mUsername + ")"; + name = getUserName(); } return name; } @@ -159,23 +192,29 @@ std::string LLAvatarName::getDisplayName() const std::string LLAvatarName::getUserName() const { - // If we cannot create a user name from the legacy strings, use the display name - if (mLegacyFirstName.empty() && mLegacyLastName.empty()) + std::string name; + if (mLegacyLastName.empty() || (mLegacyLastName == "Resident")) { - return mDisplayName; + if (mLegacyFirstName.empty()) + { + // If we cannot create a user name from the legacy strings, use the display name + name = mDisplayName; + } + else + { + // The last name might be empty if it defaulted to "Resident" + name = mLegacyFirstName; + } + } + else + { + name = mLegacyFirstName + " " + mLegacyLastName; } - - std::string name; - name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() ); - name = mLegacyFirstName; - name += " "; - name += mLegacyLastName; return name; } void LLAvatarName::dump() const { - llinfos << "Merov debug : display = " << mDisplayName << ", user = " << mUsername << ", complete = " << getCompleteName() << ", legacy = " << getUserName() << " first = " << mLegacyFirstName << " last = " << mLegacyLastName << llendl; LL_DEBUGS("AvNameCache") << "LLAvatarName: " << "user '" << mUsername << "' " << "display '" << mDisplayName << "' " diff --git a/indra/llcommon/llavatarname.h b/indra/llcommon/llavatarname.h index cf9eb27b03..2f8c534974 100644 --- a/indra/llcommon/llavatarname.h +++ b/indra/llcommon/llavatarname.h @@ -39,20 +39,25 @@ public: bool operator<(const LLAvatarName& rhs) const; + // Conversion to and from LLSD (cache file or server response) LLSD asLLSD() const; - void fromLLSD(const LLSD& sd); // Used only in legacy mode when the display name capability is not provided server side - void fromString(const std::string& full_name, F64 expires = 0.0f); + // or to otherwise create a temporary valid item. + void fromString(const std::string& full_name); + // Set the name object to become invalid in "expires" seconds from now + void setExpires(F64 expires); + + // Set and get the display name flag set by the user in preferences. static void setUseDisplayNames(bool use); static bool useDisplayNames(); - // Name is valid if not temporary and not yet expired + // A name object is valid if not temporary and not yet expired (default is expiration not checked) bool isValidName(F64 max_unrefreshed = 0.0f) const { return !mIsTemporaryName && (mExpires >= max_unrefreshed); } - // + // Return true if the name is made up from legacy or temporary data bool isDisplayNameDefault() const { return mIsDisplayNameDefault; } // For normal names, returns "James Linden (james.linden)" diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 329871d8eb..15c4f2a207 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -47,18 +47,22 @@ namespace LLAvatarNameCache // current region supports display names. bool sRunning = false; + // Use the People API (modern) for fetching name if true. Use the old legacy protocol if false. + // For testing, there's a UsePeopleAPI setting that can be flipped (must restart viewer). + bool sUsePeopleAPI = true; + // Base lookup URL for name service. // On simulator, loaded from indra.xml // On viewer, usually a simulator capability (at People API team's request) // Includes the trailing slash, like "http://pdp60.lindenlab.com:8000/agents/" std::string sNameLookupURL; - // accumulated agent IDs for next query against service + // Accumulated agent IDs for next query against service typedef std::set<LLUUID> ask_queue_t; ask_queue_t sAskQueue; - // agent IDs that have been requested, but with no reply - // maps agent ID to frame time request was made + // Agent IDs that have been requested, but with no reply. + // Maps agent ID to frame time request was made. typedef std::map<LLUUID, F64> pending_queue_t; pending_queue_t sPendingQueue; @@ -69,21 +73,21 @@ namespace LLAvatarNameCache typedef std::map<LLUUID, callback_signal_t*> signal_map_t; signal_map_t sSignalMap; - // names we know about + // The cache at last, i.e. avatar names we know about. typedef std::map<LLUUID, LLAvatarName> cache_t; cache_t sCache; - // Send bulk lookup requests a few times a second at most - // only need per-frame timing resolution + // Send bulk lookup requests a few times a second at most. + // Only need per-frame timing resolution. LLFrameTimer sRequestTimer; - /// Maximum time an unrefreshed cache entry is allowed + // Maximum time an unrefreshed cache entry is allowed. const F64 MAX_UNREFRESHED_TIME = 20.0 * 60.0; - /// Time when unrefreshed cached names were checked last + // Time when unrefreshed cached names were checked last. static F64 sLastExpireCheck; - /// Time-to-live for a temp cache entry. + // Time-to-live for a temp cache entry. const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0; //----------------------------------------------------------------------- @@ -91,26 +95,18 @@ namespace LLAvatarNameCache //----------------------------------------------------------------------- // Handle name response off network. - // Optionally skip adding to cache, used when this is a fallback to the - // legacy name system. void processName(const LLUUID& agent_id, - const LLAvatarName& av_name, - bool add_to_cache); + const LLAvatarName& av_name); void requestNamesViaCapability(); // Legacy name system callback void legacyNameCallback(const LLUUID& agent_id, const std::string& full_name, - bool is_group - ); + bool is_group); void requestNamesViaLegacy(); - // Fill in an LLAvatarName with the legacy name data - void buildLegacyName(const std::string& full_name, - LLAvatarName* av_name); - // Do a single callback to a given slot void fireSignal(const LLUUID& agent_id, const callback_slot_t& slot, @@ -209,7 +205,7 @@ public: av_name.dump(); // cache it and fire signals - LLAvatarNameCache::processName(agent_id, av_name, true); + LLAvatarNameCache::processName(agent_id, av_name); } // Same logic as error response case @@ -271,7 +267,7 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id) } else { - // we have a chached (but probably expired) entry - since that would have + // we have a cached (but probably expired) entry - since that would have // been returned by the get method, there is no need to signal anyone // Clear this agent from the pending list @@ -281,22 +277,20 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id) LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent " << agent_id << LL_ENDL; av_name.dump(); - av_name.mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME; // reset expiry time so we don't constantly rerequest. + // Reset expiry time so we don't constantly rerequest. + av_name.setExpires(TEMP_CACHE_ENTRY_LIFETIME); } } -void LLAvatarNameCache::processName(const LLUUID& agent_id, - const LLAvatarName& av_name, - bool add_to_cache) +void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName& av_name) { - if (add_to_cache) - { - sCache[agent_id] = av_name; - } + // Add to the cache + sCache[agent_id] = av_name; + // Suppress request from the queue sPendingQueue.erase(agent_id); - // signal everyone waiting on this name + // Signal everyone waiting on this name signal_map_t::iterator sig_it = sSignalMap.find(agent_id); if (sig_it != sSignalMap.end()) { @@ -373,22 +367,20 @@ void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id, const std::string& full_name, bool is_group) { - // Construct a dummy record for this name. By convention, SLID is blank - // Never expires, but not written to disk, so lasts until end of session. - LLAvatarName av_name; LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::legacyNameCallback " << "agent " << agent_id << " " << "full name '" << full_name << "'" << ( is_group ? " [group]" : "" ) << LL_ENDL; - buildLegacyName(full_name, &av_name); + + // Construct an av_name record from this name. + LLAvatarName av_name; + av_name.fromString(full_name); + av_name.dump(); // Add to cache, because if we don't we'll keep rerequesting the - // same record forever. buildLegacyName should always guarantee - // that these records expire reasonably soon - // (in TEMP_CACHE_ENTRY_LIFETIME seconds), so if the failure was due - // to something temporary we will eventually request and get the right data. - processName(agent_id, av_name, true); + // same record forever. + processName(agent_id, av_name); } void LLAvatarNameCache::requestNamesViaLegacy() @@ -410,18 +402,19 @@ void LLAvatarNameCache::requestNamesViaLegacy() LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaLegacy agent " << agent_id << LL_ENDL; gCacheName->get(agent_id, false, // legacy compatibility - boost::bind(&LLAvatarNameCache::legacyNameCallback, - _1, _2, _3)); + boost::bind(&LLAvatarNameCache::legacyNameCallback, _1, _2, _3)); } } -void LLAvatarNameCache::initClass(bool running) +void LLAvatarNameCache::initClass(bool running, bool usePeopleAPI) { sRunning = running; + sUsePeopleAPI = usePeopleAPI; } void LLAvatarNameCache::cleanupClass() { + sCache.clear(); } void LLAvatarNameCache::importFile(std::istream& istr) @@ -481,6 +474,11 @@ bool LLAvatarNameCache::hasNameLookupURL() return !sNameLookupURL.empty(); } +bool LLAvatarNameCache::usePeopleAPI() +{ + return hasNameLookupURL() && sUsePeopleAPI; +} + void LLAvatarNameCache::idle() { // By convention, start running at first idle() call @@ -497,13 +495,12 @@ void LLAvatarNameCache::idle() if (!sAskQueue.empty()) { - if (hasNameLookupURL()) + if (usePeopleAPI()) { requestNamesViaCapability(); } else { - // ...fall back to legacy name cache system requestNamesViaLegacy(); } } @@ -563,18 +560,6 @@ void LLAvatarNameCache::eraseUnrefreshed() } } -void LLAvatarNameCache::buildLegacyName(const std::string& full_name, - LLAvatarName* av_name) -{ - llassert(av_name); - av_name->fromString(full_name,TEMP_CACHE_ENTRY_LIFETIME); - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::buildLegacyName " - << full_name - << LL_ENDL; - // DEBUG ONLY!!! DO NOT COMMIT!!! - av_name->dump(); -} - // fills in av_name if it has it in the cache, even if expired (can check expiry time) // returns bool specifying if av_name was filled, false otherwise bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) @@ -582,38 +567,24 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) if (sRunning) { // ...only do immediate lookups when cache is running - if (hasNameLookupURL()) + std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id); + if (it != sCache.end()) { - // ...use display names cache - std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id); - if (it != sCache.end()) - { - *av_name = it->second; + *av_name = it->second; - // re-request name if entry is expired - if (av_name->mExpires < LLFrameTimer::getTotalSeconds()) + // re-request name if entry is expired + if (av_name->mExpires < LLFrameTimer::getTotalSeconds()) + { + if (!isRequestPending(agent_id)) { - if (!isRequestPending(agent_id)) - { - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::get " - << "refresh agent " << agent_id - << LL_ENDL; - sAskQueue.insert(agent_id); - } + LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::get " + << "refresh agent " << agent_id + << LL_ENDL; + sAskQueue.insert(agent_id); } - - return true; - } - } - else - { - // ...use legacy names cache - std::string full_name; - if (gCacheName->getFullName(agent_id, full_name)) - { - buildLegacyName(full_name, av_name); - return true; } + + return true; } } @@ -644,30 +615,14 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& ag if (sRunning) { // ...only do immediate lookups when cache is running - if (hasNameLookupURL()) - { - // ...use new cache - std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id); - if (it != sCache.end()) - { - const LLAvatarName& av_name = it->second; - - if (av_name.mExpires > LLFrameTimer::getTotalSeconds()) - { - // ...name already exists in cache, fire callback now - fireSignal(agent_id, slot, av_name); - return connection; - } - } - } - else + std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id); + if (it != sCache.end()) { - // ...use old name system - std::string full_name; - if (gCacheName->getFullName(agent_id, full_name)) + const LLAvatarName& av_name = it->second; + + if (av_name.mExpires > LLFrameTimer::getTotalSeconds()) { - LLAvatarName av_name; - buildLegacyName(full_name, &av_name); + // ...name already exists in cache, fire callback now fireSignal(agent_id, slot, av_name); return connection; } @@ -709,11 +664,6 @@ void LLAvatarNameCache::setUseDisplayNames(bool use) } } -void LLAvatarNameCache::flushCache() -{ - sCache.clear(); -} - void LLAvatarNameCache::erase(const LLUUID& agent_id) { sCache.erase(agent_id); diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index e172601432..2a8eb46187 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -37,33 +37,33 @@ class LLUUID; namespace LLAvatarNameCache { - typedef boost::signals2::signal<void (void)> use_display_name_signal_t; // Until the cache is set running, immediate lookups will fail and // async lookups will be queued. This allows us to block requests // until we know if the first region supports display names. - void initClass(bool running); + void initClass(bool running, bool usePeopleAPI); void cleanupClass(); + // Import/export the name cache to file. void importFile(std::istream& istr); void exportFile(std::ostream& ostr); - // On the viewer, usually a simulator capabilitity - // If empty, name cache will fall back to using legacy name - // lookup system + // On the viewer, usually a simulator capabilitity. + // If empty, name cache will fall back to using legacy name lookup system. void setNameLookupURL(const std::string& name_lookup_url); - // Do we have a valid lookup URL, hence are we trying to use the - // new display name lookup system? + // Do we have a valid lookup URL, i.e. are we trying to use the + // more recent display name lookup system? bool hasNameLookupURL(); + bool usePeopleAPI(); // Periodically makes a batch request for display names not already in - // cache. Call once per frame. + // cache. Called once per frame. void idle(); // If name is in cache, returns true and fills in provided LLAvatarName - // otherwise returns false + // otherwise returns false. bool get(const LLUUID& agent_id, LLAvatarName *av_name); // Callback types for get() below @@ -73,23 +73,19 @@ namespace LLAvatarNameCache typedef callback_signal_t::slot_type callback_slot_t; typedef boost::signals2::connection callback_connection_t; - // Fetches name information and calls callback. - // If name information is in cache, callback will be called immediately. + // Fetches name information and calls callbacks. + // If name information is in cache, callbacks will be called immediately. callback_connection_t get(const LLUUID& agent_id, callback_slot_t slot); - // Allow display names to be explicitly disabled for testing. + // Set display name: flips the switch and triggers the callbacks. void setUseDisplayNames(bool use); - bool useDisplayNames(); - - void flushCache(); + void insert(const LLUUID& agent_id, const LLAvatarName& av_name); void erase(const LLUUID& agent_id); - /// Provide some fallback for agents that return errors + /// Provide some fallback for agents that return errors. void handleAgentError(const LLUUID& agent_id); - void insert(const LLUUID& agent_id, const LLAvatarName& av_name); - // Compute name expiration time from HTTP Cache-Control header, // or return default value, in seconds from epoch. F64 nameExpirationFromHeaders(LLSD headers); diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h index b108e37157..d238c3a247 100644 --- a/indra/llmessage/llcachename.h +++ b/indra/llmessage/llcachename.h @@ -40,7 +40,7 @@ typedef boost::signals2::signal<void (const LLUUID& id, bool is_group)> LLCacheNameSignal; typedef LLCacheNameSignal::slot_type LLCacheNameCallback; -// Old callback with user data for compatability +// Old callback with user data for compatibility typedef void (*old_callback_t)(const LLUUID&, const std::string&, bool, void*); // Here's the theory: diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index f8797fd257..5d3f9ac327 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -46,11 +46,6 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& ag return connection; } -bool LLAvatarNameCache::useDisplayNames() -{ - return false; -} - // // Stub implementation for LLCacheName // diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ece711a128..423e5a00df 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12648,6 +12648,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>UsePeopleAPI</key> + <map> + <key>Comment</key> + <string>Use the people API cap for avatar name fetching, use old legacy protocol if false. Requires restart.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>UseStartScreen</key> <map> <key>Comment</key> diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 34259658ea..66a2e6dbda 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2806,7 +2806,7 @@ void LLStartUp::initNameCache() // Start cache in not-running state until we figure out if we have // capabilities for display name lookup - LLAvatarNameCache::initClass(false); + LLAvatarNameCache::initClass(false,gSavedSettings.getBOOL("UsePeopleAPI")); LLAvatarNameCache::setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames")); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 5284d2650e..7ae717cb42 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -8080,7 +8080,7 @@ class LLWorldPostProcess : public view_listener_t void handle_flush_name_caches() { - LLAvatarNameCache::flushCache(); + LLAvatarNameCache::cleanupClass(); if (gCacheName) gCacheName->clear(); } -- cgit v1.2.3 From 935b3326254f75af876b6c9aeb1648ac3a9802cf Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Fri, 7 Dec 2012 15:03:32 +0200 Subject: CHUI-427 FIXED Voice button is added to Conversations floater. --- indra/newview/llfloaterimcontainer.cpp | 13 +++++++++++++ indra/newview/llfloaterimcontainer.h | 2 ++ indra/newview/llfloaterimsessiontab.cpp | 3 ++- .../newview/skins/default/xui/en/floater_im_container.xml | 15 ++++++++++++++- 4 files changed, 31 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index b8a37da3fa..bd99e88a9d 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -206,6 +206,7 @@ BOOL LLFloaterIMContainer::postBuild() mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onExpandCollapseButtonClicked, this)); mStubCollapseBtn = getChild<LLButton>("stub_collapse_btn"); mStubCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onStubCollapseButtonClicked, this)); + getChild<LLButton>("speak_btn")->setClickedCallback(boost::bind(&LLFloaterIMContainer::onSpeakButtonClicked, this)); childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this)); @@ -341,6 +342,11 @@ void LLFloaterIMContainer::onStubCollapseButtonClicked() collapseMessagesPane(true); } +void LLFloaterIMContainer::onSpeakButtonClicked() +{ + LLAgent::toggleMicrophone("speak"); + updateSpeakBtnState(); +} void LLFloaterIMContainer::onExpandCollapseButtonClicked() { if (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed() @@ -1672,6 +1678,13 @@ void LLFloaterIMContainer::reSelectConversation() } } +void LLFloaterIMContainer::updateSpeakBtnState() +{ + LLButton* mSpeakBtn = getChild<LLButton>("speak_btn"); + mSpeakBtn->setToggleState(LLVoiceClient::getInstance()->getUserPTTState()); + mSpeakBtn->setEnabled(LLAgent::isActionAllowed("speak")); +} + void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes) { //Finds the conversation line item to flash using the session_id diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index c9987bffe8..92985c036a 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -117,6 +117,7 @@ private: void onExpandCollapseButtonClicked(); void onStubCollapseButtonClicked(); void processParticipantsStyleUpdate(); + void onSpeakButtonClicked(); void collapseConversationsPane(bool collapse); @@ -172,6 +173,7 @@ public: void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); void setNearbyDistances(); void reSelectConversation(); + void updateSpeakBtnState(); void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes); private: diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index b50b8c2d32..0567ea3d8a 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -698,7 +698,8 @@ void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive) voiceButton->setToolTip( callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip")); - enableDisableCallBtn(); + LLFloaterIMContainer::getInstance()->updateSpeakBtnState(); + enableDisableCallBtn(); } diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 152c897120..a3648f3c9d 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -73,13 +73,26 @@ image_hover_unselected="Toolbar_Middle_Over" image_overlay="Conv_toolbar_plus" image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" + image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" left_pad="4" name="add_btn" tool_tip="Start a new conversation" width="31"/> + <button + follows="top|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Command_Speak_Icon" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_pad="4" + name="speak_btn" + tool_tip="Speak with people using your microphone" + width="31"/> </layout_panel> <layout_panel auto_resize="false" -- cgit v1.2.3 From b3e667cc0e3c0c08fc8caed1408ceaa2798875b1 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 7 Dec 2012 15:13:26 +0200 Subject: CHUI-582 : fixed : Resizing conversation floater initially only resizes conversation list width. --- indra/newview/skins/default/xui/en/floater_im_container.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index a3648f3c9d..9f6503d799 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -32,7 +32,7 @@ top="0" width="450"> <layout_panel - auto_resize="true" + auto_resize="false" user_resize="true" height="430" name="conversations_layout_panel" -- cgit v1.2.3 From 979360340fe05e83948fb1680b2e87292a333094 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Fri, 7 Dec 2012 15:42:33 +0200 Subject: CHUI-530 FIXED Changed selectConversation() to reSelectConversation() --- indra/newview/llfloaterimcontainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index bd99e88a9d..c36128b0bd 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1656,7 +1656,7 @@ void LLFloaterIMContainer::openNearbyChat() LLConversationViewSession* nearby_chat = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,LLUUID())); if (nearby_chat) { - selectConversation(LLUUID()); + reSelectConversation(); nearby_chat->setOpen(TRUE); } } -- cgit v1.2.3 From fb5417b7166742b081d61d33871d13ef76719fa4 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 7 Dec 2012 17:53:17 +0200 Subject: CHUI-564 : Fixed : (Conversation floater always opens when new IM is received) : Remove obsolete code: control of an visibility of container was delegated to on_new_message() [see llimview.cpp] --- indra/newview/llfloaterimsessiontab.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 0567ea3d8a..7d6ba093eb 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -168,11 +168,6 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id) || gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) { floater_container->addFloater(conversp, FALSE, LLTabContainer::END); - - if (!floater_container->getVisible()) - { - LLFloaterReg::toggleInstanceOrBringToFront("im_container"); - } } else { -- cgit v1.2.3 From 6122f000cb249dd2f8cbc0d16e664bb1b00d5864 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 7 Dec 2012 17:43:05 +0200 Subject: CHUI-547 : Fixed : (Clicking IM toast does not select message panel in conversation floater) : select new session floater when a container is hidden --- indra/newview/llfloaterimsessiontab.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 7d6ba093eb..8e4e4e809a 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -167,7 +167,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id) if (!conversp->isNearbyChat() || gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) { - floater_container->addFloater(conversp, FALSE, LLTabContainer::END); + floater_container->addFloater(conversp, !floater_container->getVisible(), LLTabContainer::END); } else { -- cgit v1.2.3 From cd20d3dc2b02754ca14b314a9cab505535ff8e8d Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Fri, 7 Dec 2012 19:56:16 +0200 Subject: CHUI-512 FIXED New incoming conversations take focus in message panel only and do not show toasts --- indra/newview/llfloaterimsessiontab.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 8e4e4e809a..4c6d8fa5a0 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -167,7 +167,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id) if (!conversp->isNearbyChat() || gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) { - floater_container->addFloater(conversp, !floater_container->getVisible(), LLTabContainer::END); + floater_container->addFloater(conversp, !floater_container->getVisible(), LLTabContainer::RIGHT_OF_CURRENT); } else { -- cgit v1.2.3 From 0037b1e2c75d49481aee6fffd24395a79fbf6699 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 7 Dec 2012 14:44:15 -0800 Subject: CHUI-579: Post code review. Renamed variables to make easier to read. --- indra/newview/llfloaterimnearbychathandler.cpp | 5 ++- indra/newview/llimview.cpp | 43 +++++++++++++------------- 2 files changed, 25 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 903c903381..f64cfd0245 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -557,7 +557,10 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, // Send event on to LLEventStream sChatWatcher->post(chat); - if( nearby_chat->isInVisibleChain() + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + + if( nearby_chat->hasFocus() + || im_box->hasFocus() || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT && gSavedSettings.getBOOL("UseChatBubbles") ) || mChannel.isDead() diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 6ffc3b610b..ab2f275711 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -159,10 +159,11 @@ void on_new_message(const LLSD& msg) LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); - bool sessionFloaterInActive = session_floater - && (!session_floater->isInVisibleChain()) //conversation floater not displayed - || - (session_floater->isInVisibleChain() && session_floater->hasFocus() == false); //conversation floater is displayed but doesn't have focus + //session floater not focused (visible or not) + bool sessionFloaterNotFocused = session_floater && !session_floater->hasFocus(); + + //conversation floater not focused (visible or not) + bool conversationFloaterNotFocused = im_box && !im_box->hasFocus(); if ("toast" == action) { @@ -185,43 +186,41 @@ void on_new_message(const LLSD& msg) return; } - //Show IM toasts (upper right toasts) - if(session_id.notNull()) - { - LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); - } - - //Session floater has focus, so don't need to show notification flashes - if(sessionFloaterInActive) + //User is not focused on conversation containing the message + if(sessionFloaterNotFocused) { - //Flash converstation line item anytime that conversation doesn't have focus im_box->flashConversationItemWidget(session_id, true); - //Only flash the 'Chat' FUI button when the conversation floater isn't focused (implies not front most floater) - if(!im_box->hasFocus()) + //The conversation floater isn't focused/open + if(conversationFloaterNotFocused) { gToolBarView->flashCommand(LLCommandId("chat"), true); + + //Show IM toasts (upper right toasts) + LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); } } } else if ("flash" == action) { - if(sessionFloaterInActive && !im_box->hasFocus()) + //User is not focused on conversation containing the message + if(sessionFloaterNotFocused && conversationFloaterNotFocused) { - gToolBarView->flashCommand(LLCommandId("chat"), true); // flashing of the FUI button "Chat" + gToolBarView->flashCommand(LLCommandId("chat"), true); } - else if(sessionFloaterInActive) + //conversation floater is open but a different conversation is focused + else if(sessionFloaterNotFocused) { - im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item + im_box->flashConversationItemWidget(session_id, true); } } else if("openconversations" == action) { - //Don't flash and show conversation floater when conversation already active (has focus) - if(sessionFloaterInActive) + //User is not focused on conversation containing the message + if(sessionFloaterNotFocused) { //Flash line item - im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item + im_box->flashConversationItemWidget(session_id, true); //Surface conversations floater LLFloaterReg::showInstance("im_container"); -- cgit v1.2.3 From 2965cdf5dbca4810e216315644f0981417415e9c Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 7 Dec 2012 15:03:12 -0800 Subject: CHUI-579: Found a small bug in my last commit causing nearby chat im's to show two toast messages. Now the upper right toast (im toasts) will only show when the session id is non NULL (Nearby chat has a session value that is NULL). --- indra/newview/llimview.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index ab2f275711..278384cd08 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -197,7 +197,10 @@ void on_new_message(const LLSD& msg) gToolBarView->flashCommand(LLCommandId("chat"), true); //Show IM toasts (upper right toasts) - LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); + if(session_id.notNull()) + { + LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); + } } } } -- cgit v1.2.3 From b1b4b78d5c97659d82ff67b38db4d4188967efbb Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 7 Dec 2012 17:38:36 -0800 Subject: CHUI-417: Problem: Speaking indicator icons were out of position because they were not taking into account the reduced width when a vertical scrollbar appeared. Resolution: Now when the ::arrange() function is called, this implies that the width of a conversation line item has changed...so within this function call updateChildren(). updateChildren() will reposition the speaker icon and info button based upon the adjusted width. --- indra/newview/llconversationview.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index b964cee09f..f088a8c084 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -472,6 +472,9 @@ S32 LLConversationViewParticipant::arrange(S32* width, S32* height) mAvatarIcon->getRect().mBottom); mAvatarIcon->setShape(avatarRect); + //Since dimensions changed, adjust the children (info button, speaker indicator) + updateChildren(); + return arranged; } -- cgit v1.2.3 From a6f1690128b510977cfe86071f80f81967b9d0c7 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 7 Dec 2012 18:58:52 -0800 Subject: CHUI-580, CHUI-406 : Fixed : Finished avatar name caching, also fixed the display of (waiting) when names don't come (mostly in legacy mode). --- indra/llmessage/llavatarnamecache.cpp | 39 ++++++++++++++++++++++++----------- indra/newview/llconversationmodel.cpp | 1 + 2 files changed, 28 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 15c4f2a207..9d6aa15ed1 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -100,11 +100,14 @@ namespace LLAvatarNameCache void requestNamesViaCapability(); - // Legacy name system callback + // Legacy name system callbacks void legacyNameCallback(const LLUUID& agent_id, const std::string& full_name, bool is_group); - + void legacyNameFetch(const LLUUID& agent_id, + const std::string& full_name, + bool is_group); + void requestNamesViaLegacy(); // Do a single callback to a given slot @@ -262,8 +265,7 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id) LL_WARNS("AvNameCache") << "LLAvatarNameCache get legacy for agent " << agent_id << LL_ENDL; gCacheName->get(agent_id, false, // legacy compatibility - boost::bind(&LLAvatarNameCache::legacyNameCallback, - _1, _2, _3)); + boost::bind(&LLAvatarNameCache::legacyNameFetch, _1, _2, _3)); } else { @@ -367,19 +369,32 @@ void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id, const std::string& full_name, bool is_group) { - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::legacyNameCallback " - << "agent " << agent_id << " " + // Put the received data in the cache + legacyNameFetch(agent_id, full_name, is_group); + + // Retrieve the name and set it to never (or almost never...) expire: when we are using the legacy + // protocol, we do not get an expiration date for each name and there's no reason to ask the + // data again and again so we set the expiration time to the largest value admissible. + std::map<LLUUID,LLAvatarName>::iterator av_record = sCache.find(agent_id); + LLAvatarName& av_name = av_record->second; + av_name.setExpires(MAX_UNREFRESHED_TIME); +} + +void LLAvatarNameCache::legacyNameFetch(const LLUUID& agent_id, + const std::string& full_name, + bool is_group) +{ + LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::legacyNameFetch " + << "agent " << agent_id << " " << "full name '" << full_name << "'" - << ( is_group ? " [group]" : "" ) - << LL_ENDL; + << ( is_group ? " [group]" : "" ) + << LL_ENDL; // Construct an av_name record from this name. LLAvatarName av_name; av_name.fromString(full_name); - av_name.dump(); - - // Add to cache, because if we don't we'll keep rerequesting the - // same record forever. + + // Add to cache: we're still using the new cache even if we're using the old (legacy) protocol. processName(agent_id, av_name); } diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 1f6022decb..99dd35a9e8 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -393,6 +393,7 @@ LLConversationItemParticipant::LLConversationItemParticipant(std::string display mDistToAgent(-1.0), mAvatarNameCacheConnection() { + mDisplayName = display_name; mConvType = CONV_PARTICIPANT; } -- cgit v1.2.3 From 53471178fed23f32fbb967b6d001c58d8612e450 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 7 Dec 2012 20:06:30 -0800 Subject: CHUI-509, CHUI-585 : Fixed : Add font color parameters to received items and other inventory elements created --- indra/newview/llpanelmarketplaceinboxinventory.cpp | 10 ++++++++++ indra/newview/llpanelobjectinventory.cpp | 11 +++++++++++ 2 files changed, 21 insertions(+) (limited to 'indra') diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index 68aefa7fb7..adfb2dee86 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -40,6 +40,8 @@ #define DEBUGGING_FRESHNESS 0 +const LLColor4U DEFAULT_WHITE(255, 255, 255); + // // statics // @@ -62,18 +64,24 @@ LLInboxInventoryPanel::~LLInboxInventoryPanel() LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge) { + LLUIColor item_color = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + LLInboxFolderViewFolder::Params params; params.name = bridge->getDisplayName(); params.root = mFolderRoot; params.listener = bridge; params.tool_tip = params.name; + params.font_color = item_color; + params.font_highlight_color = item_color; return LLUICtrlFactory::create<LLInboxFolderViewFolder>(params); } LLFolderViewItem * LLInboxInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge) { + LLUIColor item_color = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + LLInboxFolderViewItem::Params params; params.name = bridge->getDisplayName(); @@ -82,6 +90,8 @@ LLFolderViewItem * LLInboxInventoryPanel::createFolderViewItem(LLInvFVBridge * b params.listener = bridge; params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; + params.font_color = item_color; + params.font_highlight_color = item_color; return LLUICtrlFactory::create<LLInboxFolderViewItem>(params); } diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index de12826452..a2aabb50b5 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -66,6 +66,7 @@ #include "llviewerobjectlist.h" #include "llviewermessage.h" +const LLColor4U DEFAULT_WHITE(255, 255, 255); ///---------------------------------------------------------------------------- /// Class LLTaskInvFVBridge @@ -1719,11 +1720,15 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root bridge = LLTaskInvFVBridge::createObjectBridge(this, inventory_root); if(bridge) { + LLUIColor item_color = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + LLFolderViewFolder::Params p; p.name = inventory_root->getName(); p.tool_tip = p.name; p.root = mFolders; p.listener = bridge; + p.font_color = item_color; + p.font_highlight_color = item_color; LLFolderViewFolder* new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); new_folder->addToFolder(mFolders); @@ -1742,6 +1747,8 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li LLInventoryObject* parent, LLFolderViewFolder* folder) { + LLUIColor item_color = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + // Find all in the first pass LLDynamicArray<obj_folder_pair*> child_categories; LLTaskInvFVBridge* bridge; @@ -1767,6 +1774,8 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li p.root = mFolders; p.listener = bridge; p.tool_tip = p.name; + p.font_color = item_color; + p.font_highlight_color = item_color; view = LLUICtrlFactory::create<LLFolderViewFolder>(p); child_categories.put(new obj_folder_pair(obj, (LLFolderViewFolder*)view)); @@ -1780,6 +1789,8 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li params.listener(bridge); params.rect(LLRect()); params.tool_tip = params.name; + params.font_color = item_color; + params.font_highlight_color = item_color; view = LLUICtrlFactory::create<LLFolderViewItem> (params); } view->addToFolder(folder); -- cgit v1.2.3 From 08a7f4193b18ca5c0bbaf144232eeb2678205eae Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Mon, 10 Dec 2012 15:30:46 +0200 Subject: CHUI-457 FIXED Brought back the checking --- indra/newview/llfloaterimcontainer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c36128b0bd..9e13875d20 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -919,7 +919,10 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec } else if ("im" == command) { - LLAvatarActions::startIM(userID); + if (gAgent.getID() != userID) + { + LLAvatarActions::startIM(userID); + } } else if ("offer_teleport" == command) { -- cgit v1.2.3 From f49d47b3041c6b36b36a23b67eec609e95494acc Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Mon, 10 Dec 2012 17:22:56 +0200 Subject: CHUI-394 (Group moderation tools missing in right click menus) --- indra/newview/llconversationmodel.cpp | 14 ++++---- indra/newview/llconversationmodel.h | 2 ++ indra/newview/llfloaterimcontainer.cpp | 38 +++++++++++++--------- .../skins/default/xui/en/menu_conversation.xml | 13 ++------ 4 files changed, 36 insertions(+), 31 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 99dd35a9e8..d03ad92fbc 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -46,7 +46,8 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& u mUUID(uuid), mNeedsRefresh(true), mConvType(CONV_UNKNOWN), - mLastActiveTime(0.0) + mLastActiveTime(0.0), + mDisplayModeratorOptions(false) { } @@ -56,7 +57,8 @@ LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInte mUUID(uuid), mNeedsRefresh(true), mConvType(CONV_UNKNOWN), - mLastActiveTime(0.0) + mLastActiveTime(0.0), + mDisplayModeratorOptions(false) { } @@ -66,7 +68,8 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod mUUID(), mNeedsRefresh(true), mConvType(CONV_UNKNOWN), - mLastActiveTime(0.0) + mLastActiveTime(0.0), + mDisplayModeratorOptions(false) { } @@ -117,14 +120,13 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items) items.push_back(std::string("block_unblock")); items.push_back(std::string("MuteText")); - if(this->getType() != CONV_SESSION_1_ON_1) + if(this->getType() != CONV_SESSION_1_ON_1 && mDisplayModeratorOptions) { items.push_back(std::string("Moderator Options Separator")); items.push_back(std::string("Moderator Options")); items.push_back(std::string("AllowTextChat")); items.push_back(std::string("moderate_voice_separator")); - items.push_back(std::string("ModerateVoiceMuteSelected")); - items.push_back(std::string("ModerateVoiceUnMuteSelected")); + items.push_back(std::string("ModerateVoiceToggleMuteSelected")); items.push_back(std::string("ModerateVoiceMute")); items.push_back(std::string("ModerateVoiceUnmute")); } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index dd849210a8..7177d3a414 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -138,6 +138,7 @@ protected: EConversationType mConvType; // Type of conversation item bool mNeedsRefresh; // Flag signaling to the view that something changed for this item F64 mLastActiveTime; + bool mDisplayModeratorOptions; }; class LLConversationItemSession : public LLConversationItem @@ -198,6 +199,7 @@ public: LLConversationItemSession* getParentSession(); void dumpDebugData(); + void setModeratorOptionsVisible(bool visible) { mDisplayModeratorOptions = visible; } private: void onAvatarNameCache(const LLAvatarName& av_name); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c36128b0bd..e900f583b3 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -509,6 +509,22 @@ void LLFloaterIMContainer::draw() // still needs the conversation list. Simply collapse the message pane in that case. collapseMessagesPane(true); } + + //Update moderator options visibility + const LLConversationItem *current_session = getCurSelectedViewModelItem(); + if (current_session) + { + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = current_session->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = current_session->getChildrenEnd(); + while (current_participant_model != end_participant_model) + { + LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); + participant_model->setModeratorOptionsVisible(isGroupModerator() && participant_model->getUUID() != gAgentID); + + current_participant_model++; + } + } + LLFloater::draw(); } @@ -1156,7 +1172,7 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v { return LLAvatarActions::canOfferTeleport(uuids); } - else if (("can_moderate_voice" == item) || ("can_allow_text_chat" == item) || ("can_mute" == item) || ("can_unmute" == item)) + else if (("can_moderate_voice" == item) || ("can_allow_text_chat" == item) || ("can_mute_unmute" == item)) { // *TODO : get that out of here... return enableModerateContextMenuItem(item); @@ -1246,11 +1262,11 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool } } - // Set the focus on the selected floater - if (!session_floater->hasFocus()) - { - session_floater->setFocus(TRUE); - } + // Set the focus on the selected floater + if (!session_floater->hasFocus()) + { + session_floater->setFocus(TRUE); + } return handled; } @@ -1463,18 +1479,10 @@ bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& user bool voice_channel = speakerp->isInVoiceChannel(); - if ("can_moderate_voice" == userdata) + if ("can_moderate_voice" == userdata || "can_mute_unmute" == userdata) { return voice_channel; } - else if ("can_mute" == userdata) - { - return voice_channel && !isMuted(getCurSelectedViewModelItem()->getUUID()); - } - else if ("can_unmute" == userdata) - { - return voice_channel && isMuted(getCurSelectedViewModelItem()->getUUID()); - } // The last invoke is used to check whether the "can_allow_text_chat" will enabled return LLVoiceClient::getInstance()->isParticipantAvatar(getCurSelectedViewModelItem()->getUUID()); diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index 01ef8ebdb5..e0edf384d6 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -156,18 +156,11 @@ </menu_item_check> <menu_item_separator layout="topleft" name="moderate_voice_separator" /> <menu_item_call - label="Mute this participant" + label="Toggle mute this participant" layout="topleft" - name="ModerateVoiceMuteSelected"> + name="ModerateVoiceToggleMuteSelected"> <on_click function="Avatar.DoToSelected" parameter="selected" /> - <on_enable function="Avatar.EnableItem" parameter="can_mute" /> - </menu_item_call> - <menu_item_call - label="Unmute this participant" - layout="topleft" - name="ModerateVoiceUnMuteSelected"> - <on_click function="Avatar.DoToSelected" parameter="selected" /> - <on_enable function="Avatar.EnableItem" parameter="can_unmute" /> + <on_enable function="Avatar.EnableItem" parameter="can_mute_unmute" /> </menu_item_call> <menu_item_call label="Mute everyone" -- cgit v1.2.3 From 4d3590ae9c0040d010badc026b755634e7b3ac77 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Mon, 10 Dec 2012 19:14:37 -0800 Subject: Correcting a mac build error. --- indra/newview/llnotificationhandler.h | 2 -- indra/newview/llviewerwindow.cpp | 2 -- indra/newview/llviewerwindow.h | 9 ++++----- 3 files changed, 4 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 98b0eecd0d..a78f0c067b 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -225,8 +225,6 @@ protected: virtual void initChannel() {}; }; -typedef boost::intrusive_ptr<LLViewerAlertHandler> LLViewerAlertHandlerPtr; - /** * Handler for offers notices. * It manages life time of offer notices. diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 7b1cf6e180..eae5112b03 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1561,8 +1561,6 @@ LLViewerWindow::LLViewerWindow(const Params& p) mAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alerts", "alert")); mModalAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alertmodal", "alertmodal")); - //mAlertsChannel->connectChanged(&LLViewerWindow::onAlert); - //mModalAlertsChannel->connectChanged(&LLViewerWindow::onAlert); bool ignore = gSavedSettings.getBOOL("IgnoreAllNotifications"); LLNotifications::instance().setIgnoreAllNotifications(ignore); if (ignore) diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index b828a05384..5a0d9652b8 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -44,7 +44,6 @@ #include "llstat.h" #include "llmousehandler.h" #include "llnotifications.h" -#include "llnotificationhandler.h" #include "llhandle.h" #include "llinitparam.h" @@ -419,10 +418,10 @@ private: bool mActive; bool mUIVisible; - LLNotificationChannelPtr mSystemChannel; - LLNotificationChannelPtr mCommunicationChannel; - LLNotificationsUI::LLViewerAlertHandlerPtr mAlertsChannel; - LLNotificationsUI::LLViewerAlertHandlerPtr mModalAlertsChannel; + LLNotificationChannelPtr mSystemChannel; + LLNotificationChannelPtr mCommunicationChannel; + LLNotificationChannelPtr mAlertsChannel; + LLNotificationChannelPtr mModalAlertsChannel; LLRect mWindowRectRaw; // whole window, including UI LLRect mWindowRectScaled; // whole window, scaled by UI size -- cgit v1.2.3 From 6b1ab1b81c6b23a1947d0038686e294b6344eddb Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Tue, 11 Dec 2012 15:20:46 +0200 Subject: CHUI-587 FIXED Disable menu item if "KeepConversationLogTranscripts" is false. --- indra/newview/llfloaterimcontainer.cpp | 5 +++++ indra/newview/llfloaterimcontainer.h | 1 + indra/newview/llviewermenu.cpp | 2 ++ indra/newview/skins/default/xui/en/menu_viewer.xml | 2 ++ 4 files changed, 10 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a76714950d..cc053ca658 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1696,6 +1696,11 @@ void LLFloaterIMContainer::updateSpeakBtnState() mSpeakBtn->setEnabled(LLAgent::isActionAllowed("speak")); } +bool LLFloaterIMContainer::isConversationLoggingAllowed() +{ + return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); +} + void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes) { //Finds the conversation line item to flash using the session_id diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 92985c036a..3818645037 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -174,6 +174,7 @@ public: void setNearbyDistances(); void reSelectConversation(); void updateSpeakBtnState(); + static bool isConversationLoggingAllowed(); void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes); private: diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 7ae717cb42..fe9c00cc27 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -59,6 +59,7 @@ #include "llbuycurrencyhtml.h" #include "llfloatergodtools.h" #include "llfloaterinventory.h" +#include "llfloaterimcontainer.h" #include "llfloaterland.h" #include "llfloaterpathfindingcharacters.h" #include "llfloaterpathfindinglinksets.h" @@ -8238,6 +8239,7 @@ void initialize_menus() commit.add("Inventory.NewWindow", boost::bind(&LLFloaterInventory::showAgentInventory)); + enable.add("Conversation.IsConversationLoggingAllowed", boost::bind(&LLFloaterIMContainer::isConversationLoggingAllowed)); // Agent commit.add("Agent.toggleFlying", boost::bind(&LLAgent::toggleFlying)); diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b1e3a2d41f..3e7329c0b5 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -261,6 +261,8 @@ <menu_item_check.on_check function="Floater.Visible" parameter="conversation" /> + <menu_item_check.on_enable + function="Conversation.IsConversationLoggingAllowed" /> <menu_item_check.on_click function="Floater.Toggle" parameter="conversation" /> -- cgit v1.2.3 From 13956ab25d76ef3373d2a06795b92b24364f63cf Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Tue, 11 Dec 2012 17:16:32 +0200 Subject: CHUI-572 FIXED Changed initial position for floaters according to screenshot. --- indra/newview/skins/default/xui/en/floater_camera.xml | 4 ++-- indra/newview/skins/default/xui/en/floater_destinations.xml | 3 +-- indra/newview/skins/default/xui/en/floater_im_container.xml | 3 ++- indra/newview/skins/default/xui/en/floater_moveview.xml | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index 4b4821a383..521389d7b3 100644 --- a/indra/newview/skins/default/xui/en/floater_camera.xml +++ b/indra/newview/skins/default/xui/en/floater_camera.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater positioning="specified" - left="643" - bottom="-80" + right="-460" + bottom="-50" follows="left|bottom" legacy_header_height="18" can_minimize="true" diff --git a/indra/newview/skins/default/xui/en/floater_destinations.xml b/indra/newview/skins/default/xui/en/floater_destinations.xml index 41b57530fc..94ebaa9cb2 100644 --- a/indra/newview/skins/default/xui/en/floater_destinations.xml +++ b/indra/newview/skins/default/xui/en/floater_destinations.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + positioning="cascading" ignore_ui_scale="false" legacy_header_height="225" can_minimize="true" @@ -11,8 +12,6 @@ height="230" layout="topleft" name="Destinations" - right="-10" - bottom="-80" single_instance="true" help_topic="destinations" save_rect="true" diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 9f6503d799..1128b8fef6 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -13,7 +13,8 @@ single_instance="true" reuse_instance="true" title="CONVERSATIONS" - bottom="-80" + bottom="-50" + right="-5" width="450"> <string name="collapse_icon" diff --git a/indra/newview/skins/default/xui/en/floater_moveview.xml b/indra/newview/skins/default/xui/en/floater_moveview.xml index 02d9805ddf..5e84283ab0 100644 --- a/indra/newview/skins/default/xui/en/floater_moveview.xml +++ b/indra/newview/skins/default/xui/en/floater_moveview.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater positioning="specified" - left="505" - bottom="-80" + right="-693" + bottom="-50" legacy_header_height="18" can_dock="false" can_minimize="true" -- cgit v1.2.3 From 80bc7e13e128c4b94028fe74755a5999f08e24ce Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Wed, 12 Dec 2012 03:05:32 +0200 Subject: CHUI-557 (Cannot expand conversation from minimized state by clicking on selected conversation) --- indra/newview/llconversationview.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index f088a8c084..527c0ad233 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -223,10 +223,11 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) //This node (conversation) was selected and a child (participant) was not if(result && getRoot()->getCurSelectedItem() == this) - { - (LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"))-> - selectConversationPair(session_id, false); - } + { + LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + im_container->selectConversationPair(session_id, false); + im_container->collapseMessagesPane(false); + } return result; } -- cgit v1.2.3 From 34558181c7fad95c235bca1e29c282ca09d136ba Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 11 Dec 2012 17:49:43 -0800 Subject: CHUI-545: Problem: Sometimes the speaker indicator icons were not visible in the conversations panel. Resolution: The problem was that the visibility was set incorrectly. When the speaking indicator was not in the visible chain the state of the visiblity would be stored in a pending variable. If the visiblity changed before the pending variable was used, then this meant the pending variable overrode the most recent visibiltiy changes. So as a solution, if the visiblity changes then prevent the pending visiblity from being used. --- indra/newview/lloutputmonitorctrl.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index e4621a7fc3..27c552b626 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -333,7 +333,9 @@ void LLOutputMonitorCtrl::switchIndicator(bool switch_on) LL_DEBUGS("SpeakingIndicator") << "Indicator is in visible chain, notifying parent: " << mSpeakerId << LL_ENDL; setVisible((BOOL)switch_on); notifyParentVisibilityChanged(); - } + //Visibility has just been updated so make sure not to use the pending visibility when ::draw executes (if one is pending) + mIsSwitchDirty = false; + } // otherwise remember necessary state and mark itself as dirty. // State will be applied in next draw when parents chain becomes visible. -- cgit v1.2.3 From b5db4952590321acef60a4ff8726eb4162305c9f Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Tue, 11 Dec 2012 18:48:29 -0800 Subject: CHUI-494: Toggling the behavior of the communication notification channel filter as it should be true when not in DND mode and false when in DND mode. --- indra/newview/llviewerwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index eae5112b03..fcd65f7df2 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1557,7 +1557,7 @@ LLViewerWindow::LLViewerWindow(const Params& p) mViewerWindowListener.reset(new LLViewerWindowListener(this)); mSystemChannel.reset(new LLNotificationChannel("System", "Visible", LLNotificationFilters::includeEverything)); - mCommunicationChannel.reset(new LLNotificationChannel("Communication", "Visible", boost::bind(&LLAgent::isDoNotDisturb, &gAgent))); + mCommunicationChannel.reset(new LLNotificationChannel("Communication", "Visible", !boost::bind(&LLAgent::isDoNotDisturb, &gAgent))); mAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alerts", "alert")); mModalAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alertmodal", "alertmodal")); -- cgit v1.2.3 From 9c145d88a667c20a550884d75b6616b11ebc8104 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Wed, 12 Dec 2012 05:46:56 +0200 Subject: CHUI-589 (Conversation floater displays wrong IM floater when receiving a new message) --- indra/newview/llfloaterimcontainer.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index cc053ca658..054379c064 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -101,6 +101,16 @@ void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::str { addConversationListItem(session_id); LLFloaterIMSessionTab::addToHost(session_id); + + // If session was added while floater is not visible, conversation should not change + if (!isVisible(this)) + { + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(mSelectedSession); + if (session_floater->getHost()) + { + selectFloater(session_floater); + } + } } void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) @@ -1229,7 +1239,7 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id) void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) { selectConversationPair(session_id, true); - } +} // Synchronous select the conversation item and the conversation floater BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget) -- cgit v1.2.3 From 79cb158e118d14bfaf7050f79e5ece1fa2052471 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Tue, 11 Dec 2012 20:03:05 -0800 Subject: Removing cruft code. --- indra/newview/llchatbar.cpp | 44 -------------------------------------------- 1 file changed, 44 deletions(-) (limited to 'indra') diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 27138e6c06..7d0331757b 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -669,47 +669,3 @@ void LLChatBar::onCommitGesture(LLUICtrl* ctrl) mGestureCombo->setFocus(FALSE); } } - - -/* Cruft - global gChatHandler declared below has been commented out, - so this class is never used. See similar code in llfloaterimnearbychatbar.cpp -class LLChatHandler : public LLCommandHandler -{ -public: - // not allowed from outside the app - LLChatHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } - - // Your code here - bool handle(const LLSD& tokens, const LLSD& query_map, - LLMediaCtrl* web) - { - bool retval = false; - // Need at least 2 tokens to have a valid message. - if (tokens.size() < 2) - { - retval = false; - } - else - { - S32 channel = tokens[0].asInteger(); - // VWR-19499 Restrict function to chat channels greater than 0. - if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG)) - { - retval = true; - // Say mesg on channel - std::string mesg = tokens[1].asString(); - send_chat_from_viewer(mesg, CHAT_TYPE_NORMAL, channel); - } - else - { - retval = false; - // Tell us this is an unsupported SLurl. - } - } - return retval; - } -}; - -// Creating the object registers with the dispatcher. -//LLChatHandler gChatHandler; -cruft */ -- cgit v1.2.3 From 3636b10d479043c6e7386bc60af3228bd856f737 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Tue, 11 Dec 2012 20:46:10 -0800 Subject: CHUI-494: Removing the creation of a new session while receiving an IM in DND mode. --- indra/newview/llimview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 4e2ac09dd8..5bbe14a8b9 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2499,7 +2499,7 @@ void LLIMMgr::addMessage( } bool new_session = !hasSession(new_session_id); - if (new_session) + if (new_session && !gAgent.isDoNotDisturb()) { LLAvatarName av_name; if (LLAvatarNameCache::get(other_participant_id, &av_name) && !name_is_setted) -- cgit v1.2.3 From 3d7aaaada853d950888a2fd0fe3e2f375bd5bbb0 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Wed, 12 Dec 2012 13:14:52 +0200 Subject: CHUI-427 FIXED Added callback to track changing in mUserPTTState. It's needed to synchronize both buttons --- indra/newview/llfloaterimcontainer.cpp | 7 ++++++- indra/newview/llfloaterimcontainer.h | 1 + indra/newview/llfloaterimsessiontab.cpp | 1 - indra/newview/llvoiceclient.cpp | 1 + indra/newview/llvoiceclient.h | 6 ++++++ 5 files changed, 14 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index cc053ca658..75b311eecf 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -88,6 +88,11 @@ LLFloaterIMContainer::~LLFloaterIMContainer() mNewMessageConnection.disconnect(); LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); + if (mMicroChangedSignal.connected()) + { + mMicroChangedSignal.disconnect(); + } + gSavedPerAccountSettings.setBOOL("ConversationsListPaneCollapsed", mConversationsPane->isCollapsed()); gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed()); @@ -213,7 +218,7 @@ BOOL LLFloaterIMContainer::postBuild() collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate)); - + mMicroChangedSignal = LLVoiceClient::getInstance()->MicroChangedCallback(boost::bind(&LLFloaterIMContainer::updateSpeakBtnState, this)); if (! mMessagesPane->isCollapsed()) { S32 list_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"); diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 3818645037..4f1bb96d9b 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -176,6 +176,7 @@ public: void updateSpeakBtnState(); static bool isConversationLoggingAllowed(); void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes); + boost::signals2::connection mMicroChangedSignal; private: LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 4c6d8fa5a0..0eb0289f49 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -693,7 +693,6 @@ void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive) voiceButton->setToolTip( callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip")); - LLFloaterIMContainer::getInstance()->updateSpeakBtnState(); enableDisableCallBtn(); } diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 730f022c50..dd529d74e9 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -551,6 +551,7 @@ void LLVoiceClient::setUserPTTState(bool ptt) { mUserPTTState = ptt; updateMicMuteLogic(); + mMicroChangedSignal(); } bool LLVoiceClient::getUserPTTState() diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index c9aeea35a9..714dd6a9f2 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -303,6 +303,9 @@ public: LLVoiceClient(); ~LLVoiceClient(); + typedef boost::signals2::signal<void(void)> micro_changed_signal_t; + micro_changed_signal_t mMicroChangedSignal; + void init(LLPumpIO *pump); // Call this once at application startup (creates connector) void terminate(); // Call this to clean up during shutdown @@ -401,6 +404,8 @@ public: void keyUp(KEY key, MASK mask); void middleMouseState(bool down); + boost::signals2::connection MicroChangedCallback(const micro_changed_signal_t::slot_type& cb ) { return mMicroChangedSignal.connect(cb); } + ///////////////////////////// // Accessors for data related to nearby speakers @@ -456,6 +461,7 @@ protected: LLVoiceModuleInterface* mVoiceModule; LLPumpIO *m_servicePump; + LLCachedControl<bool> mVoiceEffectEnabled; LLCachedControl<std::string> mVoiceEffectDefault; -- cgit v1.2.3 From 9275379e3ce20f6a27341e595481ce57c3a6b954 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 12 Dec 2012 18:59:24 +0200 Subject: CHUI-584 : WIP : Viewer crash when clicking on view/sort options drop down in conversation floater: Renaming of local vfriables in accordance with the code convention --- indra/newview/llfloaterimcontainer.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 75b311eecf..5d41f46b3f 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -891,37 +891,37 @@ void LLFloaterIMContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids) const LLConversationItem * LLFloaterIMContainer::getCurSelectedViewModelItem() { - LLConversationItem * conversationItem = NULL; + LLConversationItem * conversation_item = NULL; if(mConversationsRoot && mConversationsRoot->getCurSelectedItem() && mConversationsRoot->getCurSelectedItem()->getViewModelItem()) { - LLFloaterIMSessionTab *selectedSession = LLFloaterIMSessionTab::getConversation(mSelectedSession); - if (selectedSession && selectedSession->isTornOff()) + LLFloaterIMSessionTab *selected_session_floater = LLFloaterIMSessionTab::getConversation(mSelectedSession); + if (selected_session_floater && !selected_session_floater->getHost()) { - conversationItem = selectedSession->getCurSelectedViewModelItem(); + conversation_item = selected_session_floater->getCurSelectedViewModelItem(); } else { - conversationItem = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem()); + conversation_item = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem()); } } - return conversationItem; + return conversation_item; } void LLFloaterIMContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) { //Find the conversation floater associated with the selected id - const LLConversationItem * conversationItem = getCurSelectedViewModelItem(); + const LLConversationItem * conversation_item = getCurSelectedViewModelItem(); if(conversationItem->getType() == LLConversationItem::CONV_PARTICIPANT) { getSelectedUUIDs(selected_uuids); } //When a one-on-one conversation exists, retrieve the participant id from the conversation floater - else if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + else if(conversation_item->getType() == LLConversationItem::CONV_SESSION_1_ON_1) { LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(conversationItem->getUUID()); LLUUID participantID = conversationFloater->getOtherParticipantUUID(); -- cgit v1.2.3 From 322fb006306524481ee09e88a079457b86fcd95a Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 12 Dec 2012 19:05:40 +0200 Subject: CHUI-584 : Fixed : Viewer crash when clicking on view/sort options drop down in conversation floater: Protection from a lack of the current selection. It need for the newly created floater, which still is not finished adding the first conversation item. --- indra/newview/llfloaterimcontainer.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 5d41f46b3f..82bcd8efa4 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -916,7 +916,12 @@ void LLFloaterIMContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) //Find the conversation floater associated with the selected id const LLConversationItem * conversation_item = getCurSelectedViewModelItem(); - if(conversationItem->getType() == LLConversationItem::CONV_PARTICIPANT) + if (NULL == conversation_item) + { + return; + } + + if (conversation_item->getType() == LLConversationItem::CONV_PARTICIPANT) { getSelectedUUIDs(selected_uuids); } -- cgit v1.2.3 From 4c20cc3e46d0392c63ecec304858493c8f59059b Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 12 Dec 2012 18:53:06 +0200 Subject: CHUI-584 : Addit. fix : Viewer crash when clicking on view/sort options drop down in conversation floater: Cancelled unconditional receiving a instance of the floater (LLFloaterReg::getInstance()) from LLFloaterIMContainer::selectConversationPair(), because in some situations this method is called from LLFloaterIMNearbyChat::postBuild() - In other words, while the unfinished process of creation of this floater --- indra/newview/llfloaterimcontainer.cpp | 57 ++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 26 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 82bcd8efa4..3a5f2ae854 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -928,9 +928,9 @@ void LLFloaterIMContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) //When a one-on-one conversation exists, retrieve the participant id from the conversation floater else if(conversation_item->getType() == LLConversationItem::CONV_SESSION_1_ON_1) { - LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(conversationItem->getUUID()); - LLUUID participantID = conversationFloater->getOtherParticipantUUID(); - selected_uuids.push_back(participantID); + LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(conversation_item->getUUID()); + LLUUID participant_id = conversation_floaterp->getOtherParticipantUUID(); + selected_uuids.push_back(participant_id); } } @@ -1239,13 +1239,13 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id) void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) { selectConversationPair(session_id, true); - } +} // Synchronous select the conversation item and the conversation floater BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget) { BOOL handled = TRUE; - LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); /* widget processing */ if (select_widget) @@ -1259,26 +1259,29 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool /* floater processing */ - if (session_id != getSelectedSession()) - { - // Store the active session - setSelectedSession(session_id); + if (NULL != session_floater) + { + if (session_id != getSelectedSession()) + { + // Store the active session + setSelectedSession(session_id); - if (session_floater->getHost()) - { - // Always expand the message pane if the panel is hosted by the container - collapseMessagesPane(false); - // Switch to the conversation floater that is being selected - selectFloater(session_floater); + if (session_floater->getHost()) + { + // Always expand the message pane if the panel is hosted by the container + collapseMessagesPane(false); + // Switch to the conversation floater that is being selected + selectFloater(session_floater); + } } - } - // Set the focus on the selected floater - if (!session_floater->hasFocus()) - { - session_floater->setFocus(TRUE); + // Set the focus on the selected floater + if (!session_floater->hasFocus()) + { + session_floater->setFocus(TRUE); + } } return handled; @@ -1388,12 +1391,14 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& // set the widget to minimized mode if conversations pane is collapsed widget->toggleCollapsedMode(mConversationsPane->isCollapsed()); - if (isWidgetSelected) - { - selectConversation(uuid); - // scroll to newly added item - mConversationsRoot->scrollToShowSelection(); - } + if (isWidgetSelected || 0 == mConversationsRoot->getSelectedCount()) + { + selectConversationPair(uuid, true); + widget->requestArrange(); + + // scroll to newly added item + mConversationsRoot->scrollToShowSelection(); + } return item; } -- cgit v1.2.3 From e90bd165c8f41ac4a670d6c52a7ee2d7b3728991 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Wed, 12 Dec 2012 23:35:52 +0200 Subject: CHUI-589 (Conversation floater displays wrong IM floater when receiving a new message) additional fix --- indra/newview/llfloaterimcontainer.cpp | 10 ---------- indra/newview/llfloaterimsessiontab.cpp | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 054379c064..3b98c6d98c 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -101,16 +101,6 @@ void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::str { addConversationListItem(session_id); LLFloaterIMSessionTab::addToHost(session_id); - - // If session was added while floater is not visible, conversation should not change - if (!isVisible(this)) - { - LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(mSelectedSession); - if (session_floater->getHost()) - { - selectFloater(session_floater); - } - } } void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 4c6d8fa5a0..4d923913fb 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -167,7 +167,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id) if (!conversp->isNearbyChat() || gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) { - floater_container->addFloater(conversp, !floater_container->getVisible(), LLTabContainer::RIGHT_OF_CURRENT); + floater_container->addFloater(conversp, false, LLTabContainer::RIGHT_OF_CURRENT); } else { -- cgit v1.2.3 From 89671fa1ad4ef13acb264d0e047fb24b9ee5d8a4 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 12 Dec 2012 16:59:57 -0800 Subject: CHUI-545: Adjusted fix because the old implementation of ::switchIndicator was not very clean and relied on the visiblity of the OutputMonitorCtrl to have a visibility of true even when it wasn't. The fix implemented makes it so that the visibility of OutputMonitorCtrl is always correct and the parent of this ctrl can use this information to adjust children adjacent to OutputMonitorCtrl. --- indra/newview/llavatarlistitem.cpp | 11 +++++++ indra/newview/llavatarlistitem.h | 1 + indra/newview/lloutputmonitorctrl.cpp | 61 +++++++++++------------------------ indra/newview/lloutputmonitorctrl.h | 6 ++-- 4 files changed, 34 insertions(+), 45 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 84e177d4a4..e52677925e 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -141,6 +141,17 @@ BOOL LLAvatarListItem::postBuild() return TRUE; } +void LLAvatarListItem::handleVisibilityChange ( BOOL new_visibility ) +{ + //Adjust positions of icons (info button etc) when + //speaking indicator visibility was changed/toggled while panel was closed (not visible) + if(new_visibility && mSpeakingIndicator->getIndicatorToggled()) + { + updateChildren(); + mSpeakingIndicator->setIndicatorToggled(false); + } +} + void LLAvatarListItem::fetchAvatarName() { if (mAvatarNameCacheConnection.connected()) diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 41853b6b51..96aed20016 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -84,6 +84,7 @@ public: /** * Processes notification from speaker indicator to update children when indicator's visibility is changed. */ + virtual void handleVisibilityChange ( BOOL new_visibility ); virtual S32 notifyParent(const LLSD& info); virtual void onMouseLeave(S32 x, S32 y, MASK mask); virtual void onMouseEnter(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 27c552b626..88a52caf27 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -73,8 +73,7 @@ LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p) mAutoUpdate(p.auto_update), mSpeakerId(p.speaker_id), mIsAgentControl(false), - mIsSwitchDirty(false), - mShouldSwitchOn(false), + mIndicatorToggled(false), mShowParticipantsSpeaking(false) { //static LLUIColor output_monitor_muted_color = LLUIColorTable::instance().getColor("OutputMonitorMutedColor", LLColor4::orange); @@ -116,26 +115,6 @@ void LLOutputMonitorCtrl::setPower(F32 val) void LLOutputMonitorCtrl::draw() { - // see also switchIndicator() - if (mIsSwitchDirty) - { - mIsSwitchDirty = false; - if (mShouldSwitchOn) - { - // just notify parent visibility may have changed - notifyParentVisibilityChanged(); - } - else - { - // make itself invisible and notify parent about this - setVisible(FALSE); - notifyParentVisibilityChanged(); - - // no needs to render for invisible element - return; - } - } - // Copied from llmediaremotectrl.cpp // *TODO: Give the LLOutputMonitorCtrl an agent-id to monitor, then // call directly into LLVoiceClient::getInstance() to ask if that agent-id is muted, is @@ -323,28 +302,26 @@ void LLOutputMonitorCtrl::onChange() // virtual void LLOutputMonitorCtrl::switchIndicator(bool switch_on) { - // ensure indicator is visible in case it is not in visible chain - // to be called when parent became visible next time to notify parent that visibility is changed. - setVisible(TRUE); - // if parent is in visible chain apply switch_on state and notify it immediately - if (getParent() && getParent()->isInVisibleChain()) - { - LL_DEBUGS("SpeakingIndicator") << "Indicator is in visible chain, notifying parent: " << mSpeakerId << LL_ENDL; - setVisible((BOOL)switch_on); - notifyParentVisibilityChanged(); - //Visibility has just been updated so make sure not to use the pending visibility when ::draw executes (if one is pending) - mIsSwitchDirty = false; - } + if(getVisible() != (BOOL)switch_on) + { + setVisible(switch_on); + + //Let parent adjust positioning of icons adjacent to speaker indicator + //(when speaker indicator hidden, adjacent icons move to right and when speaker + //indicator visible, adjacent icons move to the left) + if (getParent() && getParent()->isInVisibleChain()) + { + notifyParentVisibilityChanged(); + } + else + { + //Makes sure to only adjust adjacent icons when parent becomes visible + //(!mIndicatorToggled ensures that changes of TFT and FTF are discarded, real state changes are TF or FT) + mIndicatorToggled = !mIndicatorToggled; + } - // otherwise remember necessary state and mark itself as dirty. - // State will be applied in next draw when parents chain becomes visible. - else - { - LL_DEBUGS("SpeakingIndicator") << "Indicator is not in visible chain, parent won't be notified: " << mSpeakerId << LL_ENDL; - mIsSwitchDirty = true; - mShouldSwitchOn = switch_on; - } + } } ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 1fa6ef41f8..7671a736d6 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -108,6 +108,8 @@ public: * It will be applied in next draw and parent will be notified. */ virtual void switchIndicator(bool switch_on); + bool getIndicatorToggled() { return mIndicatorToggled;} + void setIndicatorToggled(bool value) { mIndicatorToggled = value;} private: @@ -148,9 +150,7 @@ private: /** uuid of a speaker being monitored */ LLUUID mSpeakerId; - /** indicates if the instance is dirty and should notify parent */ - bool mIsSwitchDirty; - bool mShouldSwitchOn; + bool mIndicatorToggled; }; #endif -- cgit v1.2.3 From 37e95e837968935fba1744ec59b3fdd32b7034bf Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 12 Dec 2012 17:43:15 -0800 Subject: CHUI-545: Minor logic fix, inside ::switchIndicator(), make sure that in the case that the parent is visible and the parent makes the visibility changes...that mIndicatorToggled becomes false because the parent has already made the visiblity changes. --- indra/newview/lloutputmonitorctrl.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 88a52caf27..02841e9831 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -313,6 +313,8 @@ void LLOutputMonitorCtrl::switchIndicator(bool switch_on) if (getParent() && getParent()->isInVisibleChain()) { notifyParentVisibilityChanged(); + //Ignore toggled state in case it was set when parent visibility was hidden + mIndicatorToggled = false; } else { -- cgit v1.2.3 From b6f3c4d07e96f3529f048a93863aa9b0f28cbad4 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 12 Dec 2012 18:02:13 -0800 Subject: CHUI-526: Slight bug fix. Problem was that the 'Teleport Offer' sound was turn on by default when the user cleared their settings. Resolution: Inside settings.xml changed the PlaySoundTeleportOffer to no longer have an intial value of 1 (true). Now it is 0 (false). --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 3e0de834b4..24fa0a0cd4 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6909,7 +6909,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> + <integer>0</integer> </map> <key>PluginAttachDebuggerToPlugins</key> <map> -- cgit v1.2.3 From 5df9d52d48b56a5d8f36a45ced0393c99473f536 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Wed, 12 Dec 2012 18:49:07 -0800 Subject: CHUI-499: Refactoring the persistent notification storage so that I can reuse the functionality for do-not-disturb mode. --- indra/llui/llnotifications.h | 2 +- indra/newview/CMakeLists.txt | 2 + indra/newview/llchannelmanager.cpp | 2 +- indra/newview/llnotificationstorage.cpp | 203 ++++----------------- indra/newview/llnotificationstorage.h | 34 ++-- indra/newview/llpersistentnotificationstorage.cpp | 210 ++++++++++++++++++++++ indra/newview/llpersistentnotificationstorage.h | 63 +++++++ 7 files changed, 322 insertions(+), 194 deletions(-) create mode 100644 indra/newview/llpersistentnotificationstorage.cpp create mode 100644 indra/newview/llpersistentnotificationstorage.h (limited to 'indra') diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 056a316d40..8bb79b57e3 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -1026,7 +1026,7 @@ protected: // Stores only persistent notifications. // Class users can use connectChanged() to process persistent notifications -// (see LLNotificationStorage for example). +// (see LLPersistentNotificationStorage for example). class LLPersistentNotificationChannel : public LLNotificationChannel { LOG_CLASS(LLPersistentNotificationChannel); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c9176d71fb..da1d96414b 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -448,6 +448,7 @@ set(viewer_SOURCE_FILES llpathfindingobject.cpp llpathfindingobjectlist.cpp llpathfindingpathtool.cpp + llpersistentnotificationstorage.cpp llphysicsmotion.cpp llphysicsshapebuilderutil.cpp llplacesinventorybridge.cpp @@ -1021,6 +1022,7 @@ set(viewer_HEADER_FILES llpathfindingobject.h llpathfindingobjectlist.h llpathfindingpathtool.h + llpersistentnotificationstorage.h llphysicsmotion.h llphysicsshapebuilderutil.h llplacesinventorybridge.h diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 987651fc80..79e2d376ea 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -29,7 +29,7 @@ #include "llchannelmanager.h" #include "llappviewer.h" -#include "llnotificationstorage.h" +#include "llpersistentnotificationstorage.h" #include "llviewercontrol.h" #include "llviewerwindow.h" #include "llrootview.h" diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index a31b95811e..d25a212059 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -25,207 +25,68 @@ */ #include "llviewerprecompiledheaders.h" // must be first include + #include "llnotificationstorage.h" -#include "llxmlnode.h" // for linux compilers +#include <string> -#include "llchannelmanager.h" -#include "llscreenchannel.h" -#include "llscriptfloater.h" +#include "llerror.h" +#include "llfile.h" +#include "llpointer.h" +#include "llsd.h" #include "llsdserialize.h" -#include "llviewermessage.h" - -////////////////////////////////////////////////////////////////////////// - -class LLResponderRegistry -{ -public: - - static void registerResponders(); - - static LLNotificationResponderInterface* createResponder(const std::string& notification_name, const LLSD& params); - -private: - - template<typename RESPONDER_TYPE> - static LLNotificationResponderInterface* create(const LLSD& params) - { - RESPONDER_TYPE* responder = new RESPONDER_TYPE(); - responder->fromLLSD(params); - return responder; - } - - typedef boost::function<LLNotificationResponderInterface* (const LLSD& params)> responder_constructor_t; - - static void add(const std::string& notification_name, const responder_constructor_t& ctr); - -private: - - typedef std::map<std::string, responder_constructor_t> build_map_t; - - static build_map_t sBuildMap; -}; -////////////////////////////////////////////////////////////////////////// -LLPersistentNotificationStorage::LLPersistentNotificationStorage() +LLNotificationStorage::LLNotificationStorage(std::string pFileName) + : mFileName(pFileName) { - mFileName = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml" ); } -bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload) +LLNotificationStorage::~LLNotificationStorage() { - // we ignore "load" messages, but rewrite the persistence file on any other - const std::string sigtype = payload["sigtype"].asString(); - if ("load" != sigtype) - { - saveNotifications(); - } - return false; } -static LLFastTimer::DeclareTimer FTM_SAVE_NOTIFICATIONS("Save Notifications"); - -void LLPersistentNotificationStorage::saveNotifications() +bool LLNotificationStorage::writeNotifications(const LLSD& pNotificationData) const { - LLFastTimer _(FTM_SAVE_NOTIFICATIONS); - - llofstream notify_file(mFileName.c_str()); - if (!notify_file.is_open()) - { - llwarns << "Failed to open " << mFileName << llendl; - return; - } - LLSD output; - LLSD& data = output["data"]; + llofstream notifyFile(mFileName.c_str()); + bool didFileOpen = notifyFile.is_open(); - boost::intrusive_ptr<LLPersistentNotificationChannel> history_channel = boost::dynamic_pointer_cast<LLPersistentNotificationChannel>(LLNotifications::instance().getChannel("Persistent")); - if (!history_channel) + if (!didFileOpen) { - return; + LL_WARNS("LLNotificationStorage") << "Failed to open file '" << mFileName << "'" << LL_ENDL; } - - for ( std::vector<LLNotificationPtr>::iterator it = history_channel->beginHistory(), end_it = history_channel->endHistory(); - it != end_it; - ++it) + else { - LLNotificationPtr notification = *it; - - // After a notification was placed in Persist channel, it can become - // responded, expired or canceled - in this case we are should not save it - if(notification->isRespondedTo() || notification->isCancelled() - || notification->isExpired()) - { - continue; - } - - data.append(notification->asLLSD()); + LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter(); + formatter->format(pNotificationData, notifyFile, LLSDFormatter::OPTIONS_PRETTY); } - LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter(); - formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY); + return didFileOpen; } -static LLFastTimer::DeclareTimer FTM_LOAD_NOTIFICATIONS("Load Notifications"); - -void LLPersistentNotificationStorage::loadNotifications() +bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const { - LLFastTimer _(FTM_LOAD_NOTIFICATIONS); - LLResponderRegistry::registerResponders(); + bool didFileRead; - LLNotifications::instance().getChannel("Persistent")-> - connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1)); + pNotificationData.clear(); - llifstream notify_file(mFileName.c_str()); - if (!notify_file.is_open()) + llifstream notifyFile(mFileName.c_str()); + didFileRead = notifyFile.is_open(); + if (!didFileRead) { - llwarns << "Failed to open " << mFileName << llendl; - return; + LL_WARNS("LLNotificationStorage") << "Failed to open file '" << mFileName << "'" << LL_ENDL; } - - LLSD input; - LLPointer<LLSDParser> parser = new LLSDXMLParser(); - if (parser->parse(notify_file, input, LLSDSerialize::SIZE_UNLIMITED) < 0) + else { - llwarns << "Failed to parse open notifications" << llendl; - return; - } - - if (input.isUndefined()) - { - return; - } - - LLSD& data = input["data"]; - if (data.isUndefined()) - { - return; - } - - using namespace LLNotificationsUI; - LLScreenChannel* notification_channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); - - LLNotifications& instance = LLNotifications::instance(); - - for (LLSD::array_const_iterator notification_it = data.beginArray(); - notification_it != data.endArray(); - ++notification_it) - { - LLSD notification_params = *notification_it; - LLNotificationPtr notification(new LLNotification(notification_params)); - - LLNotificationResponderPtr responder(LLResponderRegistry:: - createResponder(notification_params["name"], notification_params["responder"])); - notification->setResponseFunctor(responder); - - instance.add(notification); - - // hide script floaters so they don't confuse the user and don't overlap startup toast - LLScriptFloaterManager::getInstance()->setFloaterVisible(notification->getID(), false); - - if(notification_channel) + LLPointer<LLSDParser> parser = new LLSDXMLParser(); + didFileRead = (parser->parse(notifyFile, pNotificationData, LLSDSerialize::SIZE_UNLIMITED) >= 0); + if (!didFileRead) { - // hide saved toasts so they don't confuse the user - notification_channel->hideToast(notification->getID()); + LL_WARNS("LLNotificationStorage") << "Failed to parse open notifications from file '" << mFileName + << "'" << LL_ENDL; } } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -LLResponderRegistry::build_map_t LLResponderRegistry::sBuildMap; - -void LLResponderRegistry::registerResponders() -{ - sBuildMap.clear(); - - add("ObjectGiveItem", &create<LLOfferInfo>); - add("UserGiveItem", &create<LLOfferInfo>); -} - -LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& notification_name, const LLSD& params) -{ - build_map_t::const_iterator it = sBuildMap.find(notification_name); - if(sBuildMap.end() == it) - { - return NULL; - } - responder_constructor_t ctr = it->second; - return ctr(params); + return didFileRead; } - -void LLResponderRegistry::add(const std::string& notification_name, const responder_constructor_t& ctr) -{ - if(sBuildMap.find(notification_name) != sBuildMap.end()) - { - llwarns << "Responder is already registered : " << notification_name << llendl; - llassert(!"Responder already registered"); - } - sBuildMap[notification_name] = ctr; -} - -// EOF diff --git a/indra/newview/llnotificationstorage.h b/indra/newview/llnotificationstorage.h index 8635c797c0..ab4da4e73f 100644 --- a/indra/newview/llnotificationstorage.h +++ b/indra/newview/llnotificationstorage.h @@ -27,32 +27,24 @@ #ifndef LL_NOTIFICATIONSTORAGE_H #define LL_NOTIFICATIONSTORAGE_H -#include "llnotifications.h" - -// Class that saves not responded(unread) notifications. -// Unread notifications are saved in open_notifications.xml in SL account folder -// -// Notifications that should be saved(if unread) are marked with persist="true" in notifications.xml -// Notifications using functor responders are saved automatically (see llviewermessage.cpp -// lure_callback_reg for example). -// Notifications using object responders(LLOfferInfo) need additional tuning. Responder object should -// be a) serializable(implement LLNotificationResponderInterface), -// b) registered with LLResponderRegistry (found in llnotificationstorage.cpp). -class LLPersistentNotificationStorage : public LLSingleton<LLPersistentNotificationStorage> -{ - LOG_CLASS(LLPersistentNotificationStorage); -public: +#include <string> - LLPersistentNotificationStorage(); +#include "llerror.h" - void saveNotifications(); +class LLSD; - void loadNotifications(); - -private: +class LLNotificationStorage +{ + LOG_CLASS(LLNotificationStorage); +public: + LLNotificationStorage(std::string pFileName); + ~LLNotificationStorage(); - bool onPersistentChannelChanged(const LLSD& payload); +protected: + bool writeNotifications(const LLSD& pNotificationData) const; + bool readNotifications(LLSD& pNotificationData) const; +private: std::string mFileName; }; diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp new file mode 100644 index 0000000000..7aaad64fd7 --- /dev/null +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -0,0 +1,210 @@ +/** +* @file llpersistentnotificationstorage.cpp +* @brief Implementation of llpersistentnotificationstorage +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + + +#include "llviewerprecompiledheaders.h" + +#include "llpersistentnotificationstorage.h" + +#include "llchannelmanager.h" +#include "llnotificationstorage.h" +#include "llscreenchannel.h" +#include "llscriptfloater.h" +#include "llviewermessage.h" + +class LLResponderRegistry +{ +public: + + static void registerResponders(); + + static LLNotificationResponderInterface* createResponder(const std::string& notification_name, const LLSD& params); + +protected: + +private: + template<typename RESPONDER_TYPE> + static LLNotificationResponderInterface* create(const LLSD& params) + { + RESPONDER_TYPE* responder = new RESPONDER_TYPE(); + responder->fromLLSD(params); + return responder; + } + + typedef boost::function<LLNotificationResponderInterface* (const LLSD& params)> responder_constructor_t; + + static void add(const std::string& notification_name, const responder_constructor_t& ctr); + + typedef std::map<std::string, responder_constructor_t> build_map_t; + + static build_map_t sBuildMap; +}; + +LLPersistentNotificationStorage::LLPersistentNotificationStorage() + : LLSingleton<LLPersistentNotificationStorage>() + , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml")) +{ +} + +LLPersistentNotificationStorage::~LLPersistentNotificationStorage() +{ +} + +static LLFastTimer::DeclareTimer FTM_SAVE_NOTIFICATIONS("Save Notifications"); + +void LLPersistentNotificationStorage::saveNotifications() +{ + LLFastTimer _(FTM_SAVE_NOTIFICATIONS); + + boost::intrusive_ptr<LLPersistentNotificationChannel> history_channel = boost::dynamic_pointer_cast<LLPersistentNotificationChannel>(LLNotifications::instance().getChannel("Persistent")); + if (!history_channel) + { + return; + } + + LLSD output = LLSD::emptyMap(); + LLSD& data = output["data"]; + + for ( std::vector<LLNotificationPtr>::iterator it = history_channel->beginHistory(), end_it = history_channel->endHistory(); + it != end_it; + ++it) + { + LLNotificationPtr notification = *it; + + // After a notification was placed in Persist channel, it can become + // responded, expired or canceled - in this case we are should not save it + if(notification->isRespondedTo() || notification->isCancelled() + || notification->isExpired()) + { + continue; + } + + data.append(notification->asLLSD()); + } + + writeNotifications(output); +} + +static LLFastTimer::DeclareTimer FTM_LOAD_NOTIFICATIONS("Load Notifications"); + +void LLPersistentNotificationStorage::loadNotifications() +{ + LLFastTimer _(FTM_LOAD_NOTIFICATIONS); + LLResponderRegistry::registerResponders(); + + LLNotifications::instance().getChannel("Persistent")-> + connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1)); + + LLSD input; + if (!readNotifications(input) ||input.isUndefined()) + { + return; + } + + LLSD& data = input["data"]; + if (data.isUndefined()) + { + return; + } + + using namespace LLNotificationsUI; + LLScreenChannel* notification_channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + + LLNotifications& instance = LLNotifications::instance(); + + for (LLSD::array_const_iterator notification_it = data.beginArray(); + notification_it != data.endArray(); + ++notification_it) + { + LLSD notification_params = *notification_it; + LLNotificationPtr notification(new LLNotification(notification_params)); + + LLNotificationResponderPtr responder(LLResponderRegistry:: + createResponder(notification_params["name"], notification_params["responder"])); + notification->setResponseFunctor(responder); + + instance.add(notification); + + // hide script floaters so they don't confuse the user and don't overlap startup toast + LLScriptFloaterManager::getInstance()->setFloaterVisible(notification->getID(), false); + + if(notification_channel) + { + // hide saved toasts so they don't confuse the user + notification_channel->hideToast(notification->getID()); + } + } +} + +bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload) +{ + // we ignore "load" messages, but rewrite the persistence file on any other + const std::string sigtype = payload["sigtype"].asString(); + if ("load" != sigtype) + { + saveNotifications(); + } + return false; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLResponderRegistry::build_map_t LLResponderRegistry::sBuildMap; + +void LLResponderRegistry::registerResponders() +{ + sBuildMap.clear(); + + add("ObjectGiveItem", &create<LLOfferInfo>); + add("UserGiveItem", &create<LLOfferInfo>); +} + +LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& notification_name, const LLSD& params) +{ + build_map_t::const_iterator it = sBuildMap.find(notification_name); + if(sBuildMap.end() == it) + { + return NULL; + } + responder_constructor_t ctr = it->second; + return ctr(params); +} + +void LLResponderRegistry::add(const std::string& notification_name, const responder_constructor_t& ctr) +{ + if(sBuildMap.find(notification_name) != sBuildMap.end()) + { + llwarns << "Responder is already registered : " << notification_name << llendl; + llassert(!"Responder already registered"); + } + sBuildMap[notification_name] = ctr; +} + +// EOF diff --git a/indra/newview/llpersistentnotificationstorage.h b/indra/newview/llpersistentnotificationstorage.h new file mode 100644 index 0000000000..98a825d2c1 --- /dev/null +++ b/indra/newview/llpersistentnotificationstorage.h @@ -0,0 +1,63 @@ +/** +* @file llpersistentnotificationstorage.h +* @brief Header file for llpersistentnotificationstorage +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#ifndef LL_LLPERSISTENTNOTIFICATIONSTORAGE_H +#define LL_LLPERSISTENTNOTIFICATIONSTORAGE_H + +#include "llerror.h" +#include "llnotificationstorage.h" +#include "llsingleton.h" + +class LLSD; + +// Class that saves not responded(unread) notifications. +// Unread notifications are saved in open_notifications.xml in SL account folder +// +// Notifications that should be saved(if unread) are marked with persist="true" in notifications.xml +// Notifications using functor responders are saved automatically (see llviewermessage.cpp +// lure_callback_reg for example). +// Notifications using object responders(LLOfferInfo) need additional tuning. Responder object should +// be a) serializable(implement LLNotificationResponderInterface), +// b) registered with LLResponderRegistry (found in llpersistentnotificationstorage.cpp). + +class LLPersistentNotificationStorage : public LLSingleton<LLPersistentNotificationStorage>, public LLNotificationStorage +{ + LOG_CLASS(LLPersistentNotificationStorage); +public: + LLPersistentNotificationStorage(); + ~LLPersistentNotificationStorage(); + + void saveNotifications(); + void loadNotifications(); + +protected: + +private: + bool onPersistentChannelChanged(const LLSD& payload); +}; + +#endif // LL_LLPERSISTENTNOTIFICATIONSTORAGE_H + -- cgit v1.2.3 From be6f3286f4a969a4de73d8f3af7b8262fe70bfb9 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 13 Dec 2012 18:43:52 +0200 Subject: Fixed path for correct assembly of the project --- indra/newview/llavatariconctrl.h | 2 +- indra/newview/llconversationmodel.h | 4 ++-- indra/newview/llconversationview.h | 4 ++-- indra/newview/llfloaterimcontainer.h | 6 +++--- indra/newview/llimview.h | 2 +- indra/newview/lloutputmonitorctrl.h | 4 ++-- indra/newview/llviewermenu.h | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h index f55967926a..4929efb7d0 100644 --- a/indra/newview/llavatariconctrl.h +++ b/indra/newview/llavatariconctrl.h @@ -29,7 +29,7 @@ #include <boost/signals2.hpp> -#include "lliconctrl.h" +#include "../llui/lliconctrl.h" #include "llavatarpropertiesprocessor.h" #include "llviewermenu.h" diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 7177d3a414..743a6ba40b 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -30,8 +30,8 @@ #include <boost/signals2.hpp> #include "llavatarname.h" -#include "llfolderviewitem.h" -#include "llfolderviewmodel.h" +#include "../llui/llfolderviewitem.h" +#include "../llui/llfolderviewmodel.h" #include "llviewerfoldertype.h" // Implementation of conversations list diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index a6f408403b..fb2834f26a 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -27,10 +27,10 @@ #ifndef LL_LLCONVERSATIONVIEW_H #define LL_LLCONVERSATIONVIEW_H -#include "llfolderviewitem.h" +#include "../llui/llfolderviewitem.h" #include "llavatariconctrl.h" -#include "llbutton.h" +#include "../llui/llbutton.h" #include "lloutputmonitorctrl.h" class LLTextBox; diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 4f1bb96d9b..1a3e64f759 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -32,11 +32,11 @@ #include "llimview.h" #include "llevents.h" -#include "llfloater.h" -#include "llmultifloater.h" +#include "../llui/llfloater.h" +#include "../llui/llmultifloater.h" #include "llavatarpropertiesprocessor.h" #include "llgroupmgr.h" -#include "lltrans.h" +#include "../llui/lltrans.h" #include "llconversationmodel.h" #include "llconversationview.h" diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 19b738069c..9dbbd7738a 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -27,7 +27,7 @@ #ifndef LL_LLIMVIEW_H #define LL_LLIMVIEW_H -#include "lldockablefloater.h" +#include "../llui/lldockablefloater.h" #include "lleventtimer.h" #include "llinstantmessage.h" diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 1fa6ef41f8..c3d3c35fd5 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -28,10 +28,10 @@ #define LL_LLOUTPUTMONITORCTRL_H #include "v4color.h" -#include "llview.h" +#include "../llui/llview.h" #include "llmutelist.h" #include "llspeakingindicatormanager.h" -#include "lluiimage.h" +#include "../llui/lluiimage.h" class LLTextBox; class LLUICtrlFactory; diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 139f898b76..c0376ba114 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -27,7 +27,7 @@ #ifndef LL_LLVIEWERMENU_H #define LL_LLVIEWERMENU_H -#include "llmenugl.h" +#include "../llui/llmenugl.h" #include "llsafehandle.h" class LLMessageSystem; -- cgit v1.2.3 From 179ab5c7353150ebaeac6e32fa55f96670c3c256 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Thu, 13 Dec 2012 15:54:49 -0800 Subject: CHUI-595, CHU-554: Updating the people panel to new specs. --- indra/newview/skins/default/xui/en/floater_people.xml | 2 +- indra/newview/skins/default/xui/en/panel_people.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_people.xml b/indra/newview/skins/default/xui/en/floater_people.xml index 8e143623ab..5f475baa93 100644 --- a/indra/newview/skins/default/xui/en/floater_people.xml +++ b/indra/newview/skins/default/xui/en/floater_people.xml @@ -7,7 +7,7 @@ height="570" help_topic="sidebar_people" min_height="440" - min_width="390" + min_width="260" layout="topleft" name="floater_people" save_rect="true" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 7433ad828d..7ce2627be9 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -229,7 +229,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M bg_opaque_color="DkGray" bottom="-1" follows="all" - label="MY FRIENDS" + label="FRIENDS" layout="topleft" left="0" help_topic="people_friends_tab" @@ -385,7 +385,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M bg_opaque_color="DkGray" bottom="-1" follows="all" - label="MY GROUPS" + label="GROUPS" layout="topleft" left="0" help_topic="people_groups_tab" -- cgit v1.2.3 From 569701cfc898091a414dad0650f89471b1962d49 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 13 Dec 2012 17:15:18 -0800 Subject: CHUI-574, CHUI-575 : Fixed inventory regressions : select the first filtered item when searching the inventory, simply made the folder selection secondary to item selection. --- indra/llui/llfolderview.h | 16 ++++++++++++++-- indra/newview/llinventoryfunctions.cpp | 10 ++++------ 2 files changed, 18 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 525efe425a..d4a1434c73 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -341,16 +341,28 @@ public: virtual void doItem(LLFolderViewItem* item) = 0; }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLSelectFirstFilteredItem +// +// This will select the first *item* found in the hierarchy. If no item can be +// selected, the first matching folder will. +// Since doFolder() is done first but we prioritize item selection, we let the +// first filtered folder set the selection and raise a folder flag. +// The selection might be overridden by the first filtered item in doItem() +// which checks an item flag. Since doFolder() checks the item flag too, the first +// item will still be selected if items were to be done first and folders second. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLSelectFirstFilteredItem : public LLFolderViewFunctor { public: - LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} + LLSelectFirstFilteredItem() : mItemSelected(FALSE), mFolderSelected(FALSE) {} virtual ~LLSelectFirstFilteredItem() {} virtual void doFolder(LLFolderViewFolder* folder); virtual void doItem(LLFolderViewItem* item); - BOOL wasItemSelected() { return mItemSelected; } + BOOL wasItemSelected() { return mItemSelected || mFolderSelected; } protected: BOOL mItemSelected; + BOOL mFolderSelected; }; class LLOpenFilteredFolders : public LLFolderViewFunctor diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 1426567196..6474d56414 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1031,14 +1031,12 @@ void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item) void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder) { - if (folder->LLFolderViewItem::passedFilter() && !mItemSelected) + // Skip if folder or item already found, if not filtered or if no parent (root folder is not selectable) + if (!mFolderSelected && !mItemSelected && folder->LLFolderViewItem::passedFilter() && folder->getParentFolder()) { folder->getRoot()->setSelection(folder, FALSE, FALSE); - if (folder->getParentFolder()) - { - folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); - } - mItemSelected = TRUE; + folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); + mFolderSelected = TRUE; } } -- cgit v1.2.3 From 08cc82ec483fab8299d52ba979f04df95e525acb Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 13 Dec 2012 22:45:47 -0800 Subject: CHUI-599 : Fixed : Avatar name provides now a method to get the regular account name. --- indra/llcommon/llavatarname.h | 3 +++ indra/newview/llavataractions.cpp | 8 ++------ 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llavatarname.h b/indra/llcommon/llavatarname.h index 2f8c534974..4827353018 100644 --- a/indra/llcommon/llavatarname.h +++ b/indra/llcommon/llavatarname.h @@ -74,6 +74,9 @@ public: // Also used for backwards compatibility with systems like voice and muting std::string getUserName() const; + // Returns "james.linden" or the legacy name for very old names + std::string getAccountName() const { return mUsername; } + // Debug print of the object void dump() const; diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 59b862503c..23d528901a 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -315,15 +315,11 @@ static const char* get_profile_floater_name(const LLUUID& avatar_id) static void on_avatar_name_show_profile(const LLUUID& agent_id, const LLAvatarName& av_name) { - std::string username = av_name.getUserName(); - - llinfos << "opening web profile for " << username << llendl; - std::string url = getProfileURL(username); + std::string url = getProfileURL(av_name.getAccountName()); // PROFILES: open in webkit window LLFloaterWebContent::Params p; - p.url(url). - id(agent_id.asString()); + p.url(url).id(agent_id.asString()); LLFloaterReg::showInstance(get_profile_floater_name(agent_id), p); } -- cgit v1.2.3 From 22c2fff4ba4198b8dca8367ae3f03d189e815770 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 14 Dec 2012 19:56:05 +0200 Subject: CHUI-566 Flashing and color on Conversations FUI button and conversation line item --- indra/llui/llbutton.cpp | 36 +++++++------------ indra/newview/llimview.cpp | 42 ++++++++++++++-------- indra/newview/skins/default/colors.xml | 3 ++ .../skins/default/xui/en/widgets/toolbar.xml | 12 +++---- 4 files changed, 48 insertions(+), 45 deletions(-) (limited to 'indra') diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index f82cdc64a9..99384439d2 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -613,29 +613,11 @@ void LLButton::draw() static LLCachedControl<bool> sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true); F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); - bool flash = false; if (mFlashingTimer) { mFlashing = mFlashingTimer->isFlashingInProgress(); - flash = mFlashing && (!sEnableButtonFlashing || mFlashingTimer->isCurrentlyHighlighted()); - } - else - { - if(mFlashing) - { - if ( sEnableButtonFlashing) - { - F32 elapsed = mFrameTimer.getElapsedTimeF32(); - S32 flash_count = S32(elapsed * mButtonFlashRate * 2.f); - // flash on or off? - flash = (flash_count % 2 == 0) || flash_count > S32((F32)mButtonFlashCount * 2.f); - } - else - { // otherwise just highlight button in flash color - flash = true; - } - } } + bool flash = mFlashing && sEnableButtonFlashing; bool pressed_by_keyboard = FALSE; if (hasFocus()) @@ -660,7 +642,8 @@ void LLButton::draw() bool selected = getToggleState(); bool use_glow_effect = FALSE; - LLColor4 glow_color = LLColor4::white; + LLColor4 highlighting_color = LLColor4::white; + LLColor4 glow_color; LLRender::eBlendType glow_type = LLRender::BT_ADD_WITH_ALPHA; LLUIImage* imagep = NULL; if (pressed && mDisplayPressedState) @@ -733,10 +716,15 @@ void LLButton::draw() LLColor4 flash_color = mFlashBgColor.get(); use_glow_effect = TRUE; glow_type = LLRender::BT_ALPHA; // blend the glow - if (mNeedsHighlight) // highlighted AND flashing - glow_color = (glow_color*0.5f + flash_color*0.5f) % 2.0f; // average between flash and highlight colour, with sum of the opacity - else + + if (mFlashingTimer->isCurrentlyHighlighted()) + { glow_color = flash_color; + } + else if (mNeedsHighlight) + { + glow_color = highlighting_color; + } } } @@ -785,7 +773,7 @@ void LLButton::draw() if (use_glow_effect) { mCurGlowStrength = lerp(mCurGlowStrength, - mFlashing ? (flash? 1.0 : 0.0) + mFlashing ? (mFlashingTimer->isCurrentlyHighlighted() || mNeedsHighlight? 1.0 : 0.0) : mHoverGlowStrength, LLCriticalDamp::getInterpolant(0.05f)); } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 7e02915b43..5b4d5466a1 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -160,10 +160,16 @@ void on_new_message(const LLSD& msg) LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); //session floater not focused (visible or not) - bool sessionFloaterNotFocused = session_floater && !session_floater->hasFocus(); + bool session_floater_not_focused = session_floater && !session_floater->hasFocus(); + //conv. floater is closed + bool conversation_floater_is_closed = + !( im_box + && im_box->isInVisibleChain() + && !im_box->isMinimized()); //conversation floater not focused (visible or not) - bool conversationFloaterNotFocused = im_box && !im_box->hasFocus(); + bool conversation_floater_not_focused = + conversation_floater_is_closed || !im_box->hasFocus(); if ("toast" == action) { @@ -187,12 +193,12 @@ void on_new_message(const LLSD& msg) } //User is not focused on conversation containing the message - if(sessionFloaterNotFocused) + if(session_floater_not_focused) { im_box->flashConversationItemWidget(session_id, true); //The conversation floater isn't focused/open - if(conversationFloaterNotFocused) + if(conversation_floater_not_focused) { gToolBarView->flashCommand(LLCommandId("chat"), true); @@ -204,23 +210,29 @@ void on_new_message(const LLSD& msg) } } } + else if ("flash" == action) { - //User is not focused on conversation containing the message - if(sessionFloaterNotFocused && conversationFloaterNotFocused) - { - gToolBarView->flashCommand(LLCommandId("chat"), true); - } - //conversation floater is open but a different conversation is focused - else if(sessionFloaterNotFocused) - { - im_box->flashConversationItemWidget(session_id, true); - } + if (session_floater_not_focused) + { + //User is not focused on conversation containing the message + + if(conversation_floater_not_focused) + { + gToolBarView->flashCommand(LLCommandId("chat"), true); + } + //conversation floater is open but a different conversation is focused + else + { + im_box->flashConversationItemWidget(session_id, true); + } + } } + else if("openconversations" == action) { //User is not focused on conversation containing the message - if(sessionFloaterNotFocused) + if(session_floater_not_focused) { //Flash line item im_box->flashConversationItemWidget(session_id, true); diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 05230b8bd5..afd8ee4ba1 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -11,6 +11,9 @@ <color name="EmphasisColor_35" value="0.38 0.694 0.573 0.35" /> + <color + name="BeaconColor" + value="1 .67 .2 1" /> <color name="White" value="1 1 1 1" /> diff --git a/indra/newview/skins/default/xui/en/widgets/toolbar.xml b/indra/newview/skins/default/xui/en/widgets/toolbar.xml index 053b213ef4..0ace37a5dc 100644 --- a/indra/newview/skins/default/xui/en/widgets/toolbar.xml +++ b/indra/newview/skins/default/xui/en/widgets/toolbar.xml @@ -30,9 +30,9 @@ image_overlay_alignment="left" use_ellipses="true" auto_resize="true" - button_flash_count="3" - button_flash_rate="0.25" - flash_color="EmphasisColor"/> + button_flash_count="4" + button_flash_rate="0.5" + flash_color="BeaconColor"/> <button_icon pad_left="10" pad_right="10" image_bottom_pad="10" @@ -51,7 +51,7 @@ chrome="true" use_ellipses="true" auto_resize="true" - button_flash_count="3" - button_flash_rate="0.25" - flash_color="EmphasisColor"/> + button_flash_count="4" + button_flash_rate="0.5" + flash_color="BeaconColor"/> </toolbar> -- cgit v1.2.3 From bede028c51a30d2c0d3b3077e2b6d0ffdaf769da Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Fri, 14 Dec 2012 14:17:53 -0800 Subject: CHUI-595: Updating the people panel according to specs. --- indra/newview/skins/default/xui/en/floater_people.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_people.xml b/indra/newview/skins/default/xui/en/floater_people.xml index 5f475baa93..fe3aeeb038 100644 --- a/indra/newview/skins/default/xui/en/floater_people.xml +++ b/indra/newview/skins/default/xui/en/floater_people.xml @@ -14,13 +14,13 @@ single_instance="true" reuse_instance="true" title="PEOPLE" - width="390"> + width="370"> <panel_container default_panel_name="panel_people" follows="all" height="570" name="main_panel" - width="390"> + width="370"> <panel class="panel_people" name="panel_people" -- cgit v1.2.3 From 9b556fb3fea0a97f5773d8fd435a428b0fafacbf Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 14 Dec 2012 14:19:17 -0800 Subject: CHUI-599 : Use the account name in all places that are not UI related but use avatar names to index, search and other code only uses. --- indra/llmessage/llavatarnamecache.cpp | 2 +- indra/llui/llscrolllistctrl.cpp | 2 +- indra/llui/llurlentry.cpp | 2 +- indra/newview/llfavoritesbar.cpp | 10 +++++----- indra/newview/llfriendcard.cpp | 2 +- indra/newview/llpanelblockedlist.cpp | 2 +- indra/newview/llpanelgroupinvite.cpp | 4 ++-- indra/newview/llpanelgrouproles.cpp | 4 ++-- indra/newview/llvoicevivox.cpp | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 9d6aa15ed1..9163262cc0 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -561,7 +561,7 @@ void LLAvatarNameCache::eraseUnrefreshed() { const LLUUID& agent_id = it->first; LL_DEBUGS("AvNameCache") << agent_id - << " user '" << av_name.getUserName() << "' " + << " user '" << av_name.getAccountName() << "' " << "expired " << now - av_name.mExpires << " secs ago" << LL_ENDL; sCache.erase(it++); diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 2bd2294ea2..8b9fb47d5c 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1841,7 +1841,7 @@ void LLScrollListCtrl::copyNameToClipboard(std::string id, bool is_group) { LLAvatarName av_name; LLAvatarNameCache::get(LLUUID(id), &av_name); - name = av_name.getUserName(); + name = av_name.getAccountName(); } LLUrlAction::copyURLToClipboard(name); } diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index fd2635c73a..47a780b7dc 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -613,7 +613,7 @@ LLUrlEntryAgentUserName::LLUrlEntryAgentUserName() std::string LLUrlEntryAgentUserName::getName(const LLAvatarName& avatar_name) { - return avatar_name.getUserName(); + return avatar_name.getAccountName(); } // diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index ff0e01a200..ba3d4036c9 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -1520,8 +1520,8 @@ void LLFavoritesOrderStorage::saveFavoritesSLURLs() LLAvatarName av_name; LLAvatarNameCache::get( gAgentID, &av_name ); - lldebugs << "Saved favorites for " << av_name.getUserName() << llendl; - fav_llsd[av_name.getUserName()] = user_llsd; + lldebugs << "Saved favorites for " << av_name.getAccountName() << llendl; + fav_llsd[av_name.getAccountName()] = user_llsd; llofstream file; file.open(filename); @@ -1539,10 +1539,10 @@ void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() LLAvatarName av_name; LLAvatarNameCache::get( gAgentID, &av_name ); - lldebugs << "Removed favorites for " << av_name.getUserName() << llendl; - if (fav_llsd.has(av_name.getUserName())) + lldebugs << "Removed favorites for " << av_name.getAccountName() << llendl; + if (fav_llsd.has(av_name.getAccountName())) { - fav_llsd.erase(av_name.getUserName()); + fav_llsd.erase(av_name.getAccountName()); } llofstream out_file; diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index 0e72fab32c..a4dfd94496 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -533,7 +533,7 @@ void LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID) bool shouldBeAdded = true; LLAvatarName av_name; LLAvatarNameCache::get(avatarID, &av_name); - const std::string& name = av_name.getUserName(); + const std::string& name = av_name.getAccountName(); lldebugs << "Processing buddy name: " << name << ", id: " << avatarID diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index b4deb7a920..ecab7d2167 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -224,7 +224,7 @@ void LLPanelBlockedList::onFilterEdit(const std::string& search_string) void LLPanelBlockedList::callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names) { if (names.empty() || ids.empty()) return; - LLMute mute(ids[0], names[0].getUserName(), LLMute::AGENT); + LLMute mute(ids[0], names[0].getAccountName(), LLMute::AGENT); LLMuteList::getInstance()->add(mute); showPanelAndSelect(mute.mID); } diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index a2bbc5400c..3f0c6c4613 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -482,7 +482,7 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids) } else { - names.push_back(av_name.getUserName()); + names.push_back(av_name.getAccountName()); } } } @@ -495,7 +495,7 @@ void LLPanelGroupInvite::addUserCallback(const LLUUID& id, const LLAvatarName& a std::vector<std::string> names; uuid_vec_t agent_ids; agent_ids.push_back(id); - names.push_back(av_name.getUserName()); + names.push_back(av_name.getAccountName()); mImplementation->addUsers(names, agent_ids); } diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 7368477905..98e4cded6c 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -1613,7 +1613,7 @@ void LLPanelGroupMembersSubTab::onNameCache(const LLUUID& update_id, LLGroupMemb } // trying to avoid unnecessary hash lookups - if (matchesSearchFilter(av_name.getUserName())) + if (matchesSearchFilter(av_name.getAccountName())) { addMemberToList(member); if(!mMembersList->getEnabled()) @@ -1667,7 +1667,7 @@ void LLPanelGroupMembersSubTab::updateMembers() LLAvatarName av_name; if (LLAvatarNameCache::get(mMemberProgress->first, &av_name)) { - if (matchesSearchFilter(av_name.getUserName())) + if (matchesSearchFilter(av_name.getAccountName())) { addMemberToList(mMemberProgress->second); } diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 6fdda12a1c..cd93b3da28 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -2668,7 +2668,7 @@ void LLVivoxVoiceClient::checkFriend(const LLUUID& id) // *NOTE: For now, we feed legacy names to Vivox because I don't know // if their service can support a mix of new and old clients with // different sorts of names. - std::string name = av_name.getUserName(); + std::string name = av_name.getAccountName(); const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id); bool canSeeMeOnline = false; -- cgit v1.2.3 From 56b23a8727af34d950e217affa784d322b737cc3 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Fri, 14 Dec 2012 14:25:49 -0800 Subject: CHUI-554: Updating the people panel according to specs. --- indra/newview/skins/default/xui/en/floater_people.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_people.xml b/indra/newview/skins/default/xui/en/floater_people.xml index fe3aeeb038..701233ba4a 100644 --- a/indra/newview/skins/default/xui/en/floater_people.xml +++ b/indra/newview/skins/default/xui/en/floater_people.xml @@ -6,7 +6,7 @@ can_resize="true" height="570" help_topic="sidebar_people" - min_height="440" + min_height="220" min_width="260" layout="topleft" name="floater_people" -- cgit v1.2.3 From 68b61bdec620014f30d6e9c63726d96fa7f4382a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 14 Dec 2012 16:01:14 -0800 Subject: CHUI-520: Now when have a P2P conversation torn off a voice indicator icon will be displayed allowing the user to adjust the voice volume when clicked. Also did a code cleanup on conversationview.h/cpp which was showing the speaking indicator icon too soon when joining another voice session. This was due to calling switchIndicator(..) directly inside ::onCurrentVoiceSessionChanged. The proper solution is to wait for SpeeakingIndicatorManager::switchSpeakerIndicators() call switchIndicators(). --- indra/newview/llconversationview.cpp | 24 ---------------------- indra/newview/llconversationview.h | 1 - indra/newview/llfloaterimsession.cpp | 18 ++++++++++++++++ indra/newview/llfloaterimsession.h | 1 + indra/newview/llfloaterimsessiontab.cpp | 3 +++ indra/newview/llfloaterimsessiontab.h | 1 + indra/newview/lloutputmonitorctrl.cpp | 2 ++ .../skins/default/xui/en/floater_im_session.xml | 12 +++++++++++ 8 files changed, 37 insertions(+), 25 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 527c0ad233..71d668d047 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -341,14 +341,6 @@ void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& sessi if (vmi) { bool is_active = vmi->getUUID() == session_id; - bool is_nearby = vmi->getType() == LLConversationItem::CONV_SESSION_NEARBY; - - if (is_nearby) - { - mSpeakingIndicator->setSpeakerId(is_active ? gAgentID : LLUUID::null); - } - - mSpeakingIndicator->switchIndicator(is_active); mCallIconLayoutPanel->setVisible(is_active); } } @@ -409,7 +401,6 @@ BOOL LLConversationViewParticipant::postBuild() mInfoBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onInfoBtnClick, this)); mInfoBtn->setVisible(false); - mActiveVoiceChannelConnection = LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLConversationViewParticipant::onCurrentVoiceSessionChanged, this, _1)); mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator"); if (!sStaticInitialized) @@ -479,21 +470,6 @@ S32 LLConversationViewParticipant::arrange(S32* width, S32* height) return arranged; } -void LLConversationViewParticipant::onCurrentVoiceSessionChanged(const LLUUID& session_id) -{ - LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem()); - - if (participant_model) - { - LLConversationItemSession* parent_session = participant_model->getParentSession(); - if (parent_session) - { - bool is_active = (parent_session->getUUID() == session_id); - mSpeakingIndicator->switchIndicator(is_active); - } - } -} - void LLConversationViewParticipant::refresh() { // Refresh the participant view from its model data diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index fb2834f26a..a9333020e9 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -146,7 +146,6 @@ protected: void onInfoBtnClick(); private: - void onCurrentVoiceSessionChanged(const LLUUID& session_id); LLAvatarIconCtrl* mAvatarIcon; LLButton * mInfoBtn; diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 3001029968..a0ca7286f1 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -101,6 +101,24 @@ void LLFloaterIMSession::refresh() } } +// virtual +void LLFloaterIMSession::onTearOffClicked() +{ + LLFloaterIMSessionTab::onTearOffClicked(); + + if(mIsP2PChat) + { + if(isTornOff()) + { + mSpeakingIndicator->setSpeakerId(mOtherParticipantUUID, mSessionID); + } + else + { + mSpeakingIndicator->setSpeakerId(LLUUID::null); + } + } +} + // virtual void LLFloaterIMSession::onClickCloseBtn() { diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index 72a320041f..1d8957b1d9 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -135,6 +135,7 @@ private: /*virtual*/ void refresh(); + /*virtual*/ void onTearOffClicked(); /*virtual*/ void onClickCloseBtn(); // Update the window title and input field help text diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 0eb0289f49..ab588e489f 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -54,6 +54,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) , mSessionID(session_id.asUUID()) , mConversationsRoot(NULL) , mScroller(NULL) + , mSpeakingIndicator(NULL) , mChatHistory(NULL) , mInputEditor(NULL) , mInputEditorTopPad(0) @@ -206,6 +207,8 @@ BOOL LLFloaterIMSessionTab::postBuild() mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); mScroller->setFollowsAll(); + mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator"); + // Insert that scroller into the panel widgets hierarchy mParticipantListPanel->addChild(mScroller); diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 4851904074..cd0bcd481c 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -149,6 +149,7 @@ protected: LLFolderView* mConversationsRoot; LLScrollContainer* mScroller; + LLOutputMonitorCtrl* mSpeakingIndicator; LLChatHistory* mChatHistory; LLChatEntry* mInputEditor; int mInputEditorTopPad; // padding between input field and chat history diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 02841e9831..f6e3c0cac0 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -260,6 +260,8 @@ void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& s if (speaker_id.isNull() && mSpeakerId.notNull()) { LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); + switchIndicator(false); + mSpeakerId = speaker_id; } if (speaker_id.isNull() || (speaker_id == mSpeakerId)) diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index faf54774f6..e4b127b7b9 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -106,6 +106,18 @@ name="voice_call_btn" tool_tip="Open voice connection" width="31"/> + <output_monitor + auto_update="true" + follows="top|left" + draw_border="false" + height="16" + layout="topleft" + top="10" + left_pad="10" + mouse_opaque="true" + name="speaking_indicator" + visible="false" + width="20" /> <button follows="right|top" height="25" -- cgit v1.2.3 From d0dbdac41dffa8afbebaecb25d0e57e044bf61e6 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Fri, 14 Dec 2012 17:00:00 -0800 Subject: CHUI-549: Updating the conversations floater according to specs. --- indra/newview/llfloaterimcontainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 3a5f2ae854..54cfe88140 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1476,7 +1476,7 @@ LLConversationViewParticipant* LLFloaterIMContainer::createConversationViewParti params.rect = LLRect (0, 24, panel_rect.getWidth(), 0); params.tool_tip = params.name; params.participant_id = item->getUUID(); - params.folder_indentation = 42; + params.folder_indentation = 27; return LLUICtrlFactory::create<LLConversationViewParticipant>(params); } -- cgit v1.2.3 From d0d8ee87e7648e80b83b125202d6270495e955b6 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 14 Dec 2012 21:20:43 -0800 Subject: CHUI-596 : Added a new flash state so we can keep a conversation highlighted after the flash time ends. Clears the flash state for all conversation on select. --- indra/newview/llconversationview.cpp | 10 ++++++++-- indra/newview/llconversationview.h | 3 ++- indra/newview/llfloaterimcontainer.cpp | 22 ++++++++++++---------- 3 files changed, 22 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 527c0ad233..1943174872 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -98,14 +98,20 @@ LLConversationViewSession::~LLConversationViewSession() mFlashTimer->unset(); } +void LLConversationViewSession::setFlashState(bool flash_state) +{ + mFlashStateOn = flash_state; + (flash_state ? mFlashTimer->startFlashing() : mFlashTimer->stopFlashing()); +} + bool LLConversationViewSession::isHighlightAllowed() { - return mFlashTimer->isFlashingInProgress() || mIsSelected; + return mFlashStateOn || mIsSelected; } bool LLConversationViewSession::isHighlightActive() { - return mFlashTimer->isFlashingInProgress() ? mFlashTimer->isCurrentlyHighlighted() : mIsCurSelection; + return (mFlashStateOn ? (mFlashTimer->isFlashingInProgress() ? mFlashTimer->isCurrentlyHighlighted() : true) : mIsCurSelection); } BOOL LLConversationViewSession::postBuild() diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index fb2834f26a..3e65823a23 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -83,7 +83,7 @@ public: virtual void refresh(); - LLFlashTimer * getFlashTimer() { return mFlashTimer; } + void setFlashState(bool flash_state); private: @@ -94,6 +94,7 @@ private: LLTextBox* mSessionTitle; LLOutputMonitorCtrl* mSpeakingIndicator; LLFlashTimer* mFlashTimer; + bool mFlashStateOn; bool mCollapsedMode; bool mHasArrow; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 3a5f2ae854..aaf43bdda0 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1247,6 +1247,17 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool BOOL handled = TRUE; LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); + // On selection, stop the flash state on all conversation widgets + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + for (;widget_it != mConversationsWidgets.end(); ++widget_it) + { + LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); + if (widget) + { + widget->setFlashState(false); + } + } + /* widget processing */ if (select_widget) { @@ -1723,16 +1734,7 @@ void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, if (widget) { - //Start flash - if (is_flashes) - { - widget->getFlashTimer()->startFlashing(); - } - //Stop flash - else - { - widget->getFlashTimer()->stopFlashing(); - } + widget->setFlashState(is_flashes); } } -- cgit v1.2.3 From 64dffe46118f9c435115edd2b714a0314242e752 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Sat, 15 Dec 2012 20:37:18 +0200 Subject: CHUI-598 : Fixed : Conversation log file created even when keep conversation log preference is off : Checked the status of the another ("KeepConversationLogTranscripts") setting too. --- indra/newview/llconversationlog.cpp | 3 ++- indra/newview/llfloaterconversationlog.cpp | 3 ++- indra/newview/llimview.cpp | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index a0765f5e16..1171b3db41 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -191,7 +191,8 @@ LLConversationLog::LLConversationLog() if (ctrl) { ctrl->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); - if (ctrl->getValue().asBoolean()) + if (ctrl->getValue().asBoolean() + && gSavedSettings.getBOOL("KeepConversationLogTranscripts")) { enableLogging(true); } diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index 089aec1905..a40a000bab 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -67,7 +67,8 @@ BOOL LLFloaterConversationLog::postBuild() if (ctrl) { ctrl->getSignal()->connect(boost::bind(&LLFloaterConversationLog::onCallLoggingEnabledDisabled, this, _2)); - onCallLoggingEnabledDisabled(ctrl->getValue().asBoolean()); + onCallLoggingEnabledDisabled(ctrl->getValue().asBoolean() + && gSavedSettings.getBOOL("KeepConversationLogTranscripts")); } return LLFloater::postBuild(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 4e2ac09dd8..cdd08ededf 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -857,7 +857,8 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) { - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + if (gSavedPerAccountSettings.getBOOL("LogInstantMessages") + && gSavedSettings.getBOOL("KeepConversationLogTranscripts")) { std::string from_name = from; -- cgit v1.2.3 From 56973ed9a4e3bba8529071a5e37e576f17490296 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Sat, 15 Dec 2012 17:35:24 +0200 Subject: CHUI-505 : Fixed : Don't open Call Log on login if the user doesn't want a Call Log: Checked the setting status --- indra/newview/llimview.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cdd08ededf..da3d2e89bf 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2478,8 +2478,8 @@ void LLIMMgr::addMessage( new_session_id = computeSessionID(dialog, other_participant_id); } - // Open conversation log if offline messages are present - if (is_offline_msg) + // Open conversation log if offline messages are present and user allows a Call Log + if (is_offline_msg && gSavedSettings.getBOOL("KeepConversationLogTranscripts")) { LLFloaterConversationLog* floater_log = LLFloaterReg::getTypedInstance<LLFloaterConversationLog>("conversation"); -- cgit v1.2.3 From 01bdfb3ecb88ce71078494274a8d7835d181c50e Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Sat, 15 Dec 2012 21:28:38 +0200 Subject: CHUI-591 FIXED Issues with resizing conversations floater --- indra/llui/lllayoutstack.cpp | 6 +++- indra/llui/lllayoutstack.h | 2 ++ indra/llui/llmultifloater.cpp | 4 +-- indra/llui/llresizebar.cpp | 8 ++++- indra/llui/llresizebar.h | 2 ++ indra/llui/llview.cpp | 21 +++++++++++-- indra/newview/llfloaterimcontainer.cpp | 35 +++++++++------------- indra/newview/llfloaterimcontainer.h | 3 +- indra/newview/llfloaterimnearbychat.cpp | 24 +++++++-------- indra/newview/llfloaterimnearbychat.h | 4 +-- .../skins/default/xui/en/floater_im_container.xml | 31 +++++++++---------- 11 files changed, 79 insertions(+), 61 deletions(-) (limited to 'indra') diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 0674275612..e642883991 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -32,7 +32,6 @@ #include "lllocalcliprect.h" #include "llpanel.h" -#include "llresizebar.h" #include "llcriticaldamp.h" #include "boost/foreach.hpp" @@ -796,6 +795,11 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& } else { + if (new_auto_resize_headroom < 1.f) + { + new_auto_resize_headroom = 1.f; + } + F32 new_fractional_size = llclamp(total_visible_fraction * (F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom) / new_auto_resize_headroom, MIN_FRACTIONAL_SIZE, diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 883331c792..02c664f1a0 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -29,6 +29,7 @@ #define LL_LLLAYOUTSTACK_H #include "llpanel.h" +#include "llresizebar.h" class LLLayoutPanel; @@ -178,6 +179,7 @@ public: F32 getAutoResizeFactor() const; F32 getVisibleAmount() const; S32 getVisibleDim() const; + LLResizeBar* getResizeBar() { return mResizeBar; } bool isCollapsed() const { return mCollapsed;} diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index 02ff64dbc6..179b251cdb 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -41,8 +41,8 @@ LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params) mTabContainer(NULL), mTabPos(LLTabContainer::TOP), mAutoResize(TRUE), - mOrigMinWidth(0), - mOrigMinHeight(0) + mOrigMinWidth(params.min_width), + mOrigMinHeight(params.min_height) { } diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp index 87aeb4d7a7..4b9add820f 100644 --- a/indra/llui/llresizebar.cpp +++ b/indra/llui/llresizebar.cpp @@ -45,7 +45,8 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p) mSide( p.side ), mSnappingEnabled(p.snapping_enabled), mAllowDoubleClickSnapping(p.allow_double_click_snapping), - mResizingView(p.resizing_view) + mResizingView(p.resizing_view), + mResizeListener(NULL) { setFollowsNone(); // set up some generically good follow code. @@ -261,6 +262,11 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask) } } + if (mResizeListener) + { + mResizeListener(NULL); + } + return handled; } // end LLResizeBar::handleHover diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h index 6daf191918..8190a95a71 100644 --- a/indra/llui/llresizebar.h +++ b/indra/llui/llresizebar.h @@ -71,6 +71,7 @@ public: void setEnableSnapping(BOOL enable) { mSnappingEnabled = enable; } void setAllowDoubleClickSnapping(BOOL allow) { mAllowDoubleClickSnapping = allow; } bool canResize() { return getEnabled() && mMaxSize > mMinSize; } + void setResizeListener(boost::function<void(void*)> listener) {mResizeListener = listener;} private: S32 mDragLastScreenX; @@ -84,6 +85,7 @@ private: BOOL mSnappingEnabled; BOOL mAllowDoubleClickSnapping; LLView* mResizingView; + boost::function<void(void*)> mResizeListener; }; #endif // LL_RESIZEBAR_H diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 5bcdae921d..3613a40e2c 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -55,6 +55,8 @@ #include "lltexteditor.h" #include "lltextbox.h" +static const S32 LINE_HEIGHT = 15; + S32 LLView::sDepth = 0; bool LLView::sDebugRects = false; bool LLView::sDebugRectsShowNames = true; @@ -1203,11 +1205,24 @@ void LLView::drawDebugRect() && preview_iter == sPreviewHighlightedElements.end() && sDebugRectsShowNames) { - //char temp[256]; S32 x, y; gGL.color4fv( border_color.mV ); - x = debug_rect.getWidth()/2; - y = debug_rect.getHeight()/2; + + x = debug_rect.getWidth() / 2; + + S32 rect_height = debug_rect.getHeight(); + S32 lines = rect_height / LINE_HEIGHT + 1; + + S32 depth = 0; + LLView * viewp = this; + while (NULL != viewp) + { + viewp = viewp->getParent(); + depth++; + } + + y = rect_height - LINE_HEIGHT * (depth % lines + 1); + std::string debug_text = llformat("%s (%d x %d)", getName().c_str(), debug_rect.getWidth(), debug_rect.getHeight()); LLFontGL::getFontSansSerifSmall()->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color, diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 3c85f21188..ba5ec363d6 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -51,8 +51,8 @@ #include "llconversationview.h" #include "llcallbacklist.h" #include "llworld.h" - #include "llsdserialize.h" + // // LLFloaterIMContainer // @@ -171,6 +171,9 @@ BOOL LLFloaterIMContainer::postBuild() // Open IM session with selected participant on double click event mConversationsListPanel->setDoubleClickCallback(boost::bind(&LLFloaterIMContainer::doToSelected, this, LLSD("im"))); + // The resize limits for LLFloaterIMContainer should be updated, based on current values of width of conversation and message panels + mConversationsPane->getResizeBar()->setResizeListener(boost::bind(&LLFloaterIMContainer::assignResizeLimits, this)); + // Create the root model and view for all conversation sessions LLConversationItem* base_item = new LLConversationItem(getRootViewModel()); @@ -247,6 +250,7 @@ void LLFloaterIMContainer::onOpen(const LLSD& key) { LLMultiFloater::onOpen(key); openNearbyChat(); + assignResizeLimits(); } // virtual @@ -308,26 +312,6 @@ void LLFloaterIMContainer::onCloseFloater(LLUUID& id) setFocus(TRUE); } -// virtual -void LLFloaterIMContainer::computeResizeLimits(S32& new_min_width, S32& new_min_height) -{ - // possibly increase floater's minimum height according to children's minimums - for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) - { - LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getPanelByIndex(tab_idx)); - if (floaterp) - { - new_min_height = llmax(new_min_height, floaterp->getMinHeight()); - } - } - - S32 conversations_pane_min_dim = mConversationsPane->getRelevantMinDim(); - S32 messages_pane_min_dim = mMessagesPane->getRelevantMinDim(); - - // set floater's minimum width according to relevant minimal children's dimensionals - new_min_width = conversations_pane_min_dim + messages_pane_min_dim + LLPANEL_BORDER_WIDTH*2; -} - void LLFloaterIMContainer::onNewMessageReceived(const LLSD& data) { LLUUID session_id = data["session_id"].asUUID(); @@ -728,6 +712,15 @@ void LLFloaterIMContainer::updateState(bool collapse, S32 delta_width) setResizeLimits(expanded_min_size, expanded_min_size); } + assignResizeLimits(); +} + +void LLFloaterIMContainer::assignResizeLimits() +{ + const LLRect& conv_rect = mConversationsPane->isCollapsed() ? LLRect() : mConversationsPane->getRect(); + S32 msg_limits = mMessagesPane->isCollapsed() ? 0 : mMessagesPane->getExpandedMinDim(); + S32 x_limits = conv_rect.getWidth() + msg_limits; + setResizeLimits(x_limits + LLPANEL_BORDER_WIDTH * 3, getMinHeight()); } void LLFloaterIMContainer::onAddButtonClicked() diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 1a3e64f759..5db1565cea 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -110,7 +110,7 @@ private: avatarID_panel_map_t mSessions; boost::signals2::connection mNewMessageConnection; - /*virtual*/ void computeResizeLimits(S32& new_min_width, S32& new_min_height); + /*virtual*/ void computeResizeLimits(S32& new_min_width, S32& new_min_height) {} void onNewMessageReceived(const LLSD& data); @@ -153,6 +153,7 @@ private: void toggleAllowTextChat(const LLUUID& participant_uuid); void toggleMute(const LLUUID& participant_id, U32 flags); void openNearbyChat(); + void assignResizeLimits(); LLButton* mExpandCollapseBtn; LLButton* mStubCollapseBtn; diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index a9a3611970..797d590e1f 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -113,8 +113,8 @@ BOOL LLFloaterIMNearbyChat::postBuild() BOOL result = LLFloaterIMSessionTab::postBuild(); mInputEditor->setCommitCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxCommit, this)); - mInputEditor->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this)); - mInputEditor->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); + mInputEditor->setKeystrokeCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxKeystroke, this)); + mInputEditor->setFocusLostCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxFocusLost, this)); mInputEditor->setFocusReceivedCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxFocusReceived, this)); mInputEditor->setLabel(LLTrans::getString("NearbyChatTitle")); @@ -354,13 +354,11 @@ BOOL LLFloaterIMNearbyChat::matchChatTypeTrigger(const std::string& in_str, std: return string_was_found; } -void LLFloaterIMNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userdata) +void LLFloaterIMNearbyChat::onChatBoxKeystroke() { LLFirstUse::otherAvatarChatFirst(false); - LLFloaterIMNearbyChat* self = (LLFloaterIMNearbyChat *)userdata; - - LLWString raw_text = self->mInputEditor->getWText(); + LLWString raw_text = mInputEditor->getWText(); // Can't trim the end, because that will cause autocompletion // to eat trailing spaces that might be part of a gesture. @@ -386,8 +384,8 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userd // 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(); + mInputEditor->setText( new_text ); + mInputEditor->setCursorToEnd(); length = length - 1; } */ @@ -407,17 +405,17 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userd if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) { std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); - self->mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part + mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part // Select to end of line, starting from the character // after the last one the user typed. - self->mInputEditor->selectNext(rest_of_match, false); + mInputEditor->selectNext(rest_of_match, false); } else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) { std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); - self->mInputEditor->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part - self->mInputEditor->endOfDoc(); + mInputEditor->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part + mInputEditor->endOfDoc(); } //llinfos << "GESTUREDEBUG " << trigger @@ -428,7 +426,7 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userd } // static -void LLFloaterIMNearbyChat::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) +void LLFloaterIMNearbyChat::onChatBoxFocusLost() { // stop typing animation gAgent.stopTyping(); diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index a38824dc78..f4213eda5a 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -83,8 +83,8 @@ public: protected: static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); - static void onChatBoxKeystroke(LLTextEditor* caller, void* userdata); - static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); + void onChatBoxKeystroke(); + void onChatBoxFocusLost(); void onChatBoxFocusReceived(); void sendChat( EChatType type ); diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 1128b8fef6..37a3b9ac59 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -15,7 +15,7 @@ title="CONVERSATIONS" bottom="-50" right="-5" - width="450"> + width="500"> <string name="collapse_icon" value="Conv_toolbar_collapse"/> @@ -24,22 +24,21 @@ value="Conv_toolbar_expand"/> <layout_stack animate="true" + bottom="-1" follows="all" - height="230" layout="topleft" left="0" name="conversations_stack" orientation="horizontal" - top="0" - width="450"> + right="-1" + top="0"> <layout_panel auto_resize="false" user_resize="true" - height="430" name="conversations_layout_panel" min_dim="38" - width="268" - expanded_min_dim="120"> + width="225" + expanded_min_dim="200"> <layout_stack animate="false" follows="left|top|right" @@ -48,8 +47,8 @@ left="0" name="conversations_pane_buttons_stack" orientation="horizontal" - top="0" - width="268"> + right="-1" + top="0"> <layout_panel auto_resize="true" height="35" @@ -123,32 +122,30 @@ top_pad="0" left="5" height="390" - width="263"/> + right="-1"/> </layout_panel> <layout_panel auto_resize="true" user_resize="true" - height="430" name="messages_layout_panel" - width="412" expanded_min_dim="225"> <panel_container + bottom="-1" follows="all" - height="430" layout="topleft" left="0" name="im_box_tab_container" - top="0" - width="412"> + right="-1" + top="0"> <panel + bottom="-1" follows="all" layout="topleft" name="stub_panel" opaque="true" top_pad="0" left="0" - height="430" - width="412"> + right="-1"> <button follows="right|top" height="25" -- cgit v1.2.3 From ed52792396c76ead787207b7a7dc3968f4352a1d Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Mon, 17 Dec 2012 15:38:03 +0200 Subject: CHUI-593 FIXED Using callback signal will update Speak button if voice chat disabled --- indra/newview/llvoiceclient.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index dd529d74e9..b46c55321c 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -541,6 +541,7 @@ void LLVoiceClient::setMuteMic(bool muted) { mMuteMic = muted; updateMicMuteLogic(); + mMicroChangedSignal(); } -- cgit v1.2.3 From b4d4fc902ba4d289326c6839e8a2a3e4fb1630e9 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Mon, 17 Dec 2012 15:06:38 -0800 Subject: CHUI-115: Removing code that is ifdef'ed out. --- indra/newview/llhudobject.cpp | 2 -- indra/newview/llhudobject.h | 4 ---- indra/newview/llvoavatar.cpp | 16 ---------------- indra/newview/llvoicevisualizer.cpp | 32 -------------------------------- indra/newview/llvoicevisualizer.h | 27 --------------------------- 5 files changed, 81 deletions(-) (limited to 'indra') diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp index 0960846510..95d57d08d8 100644 --- a/indra/newview/llhudobject.cpp +++ b/indra/newview/llhudobject.cpp @@ -232,11 +232,9 @@ LLHUDEffect *LLHUDObject::addHUDEffect(const U8 type) case LL_HUD_EFFECT_LOOKAT: hud_objectp = new LLHUDEffectLookAt(type); break; -#ifdef XXX_STINSON_CHUI_REWORK case LL_HUD_EFFECT_VOICE_VISUALIZER: hud_objectp = new LLVoiceVisualizer(type); break; -#endif // XXX_STINSON_CHUI_REWORK case LL_HUD_EFFECT_POINTAT: hud_objectp = new LLHUDEffectPointAt(type); break; diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h index 32cffe6839..2f7a98c86c 100644 --- a/indra/newview/llhudobject.h +++ b/indra/newview/llhudobject.h @@ -39,8 +39,6 @@ #include "lldrawpool.h" // TODO: eliminate, unused below #include <list> -#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot - class LLViewerCamera; class LLFontGL; class LLFace; @@ -96,9 +94,7 @@ public: LL_HUD_EFFECT_EDIT, LL_HUD_EFFECT_LOOKAT, LL_HUD_EFFECT_POINTAT, -#ifdef XXX_STINSON_CHUI_REWORK LL_HUD_EFFECT_VOICE_VISUALIZER, // Ventrella -#endif // XXX_STINSON_CHUI_REWORK LL_HUD_NAME_TAG, LL_HUD_EFFECT_BLOB }; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 7cc4e3ed04..19c7eda717 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -34,8 +34,6 @@ #include "llvoavatar.h" -#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot - #include <stdio.h> #include <ctype.h> @@ -711,13 +709,9 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, LLMemType mt(LLMemType::MTYPE_AVATAR); //VTResume(); // VTune -#ifdef XXX_STINSON_CHUI_REWORK // mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim ); -#else // XXX_STINSON_CHUI_REWORK - mVoiceVisualizer = new LLVoiceVisualizer(); -#endif // XXX_STINSON_CHUI_REWORK lldebugs << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << llendl; @@ -893,11 +887,7 @@ void LLVOAvatar::markDead() mNameText = NULL; sNumVisibleChatBubbles--; } -#ifdef XXX_STINSON_CHUI_REWORK mVoiceVisualizer->markDead(); -#else // XXX_STINSON_CHUI_REWORK - mVoiceVisualizer->setStopSpeaking(); -#endif // XXX_STINSON_CHUI_REWORK LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ; LLViewerObject::markDead(); } @@ -1429,9 +1419,7 @@ void LLVOAvatar::initInstance(void) //VTPause(); // VTune -#ifdef XXX_STINSON_CHUI_REWORK mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) ); -#endif // XXX_STINSON_CHUI_REWORK } @@ -2529,7 +2517,6 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) { -#ifdef XXX_STINSON_CHUI_REWORK bool render_visualizer = voice_enabled; // Don't render the user's own voice visualizer when in mouselook, or when opening the mic is disabled. @@ -2542,7 +2529,6 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) } mVoiceVisualizer->setVoiceEnabled(render_visualizer); -#endif // XXX_STINSON_CHUI_REWORK if ( voice_enabled ) { @@ -2618,7 +2604,6 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) } } -#ifdef XXX_STINSON_CHUI_REWORK //-------------------------------------------------------------------------------------------- // here we get the approximate head position and set as sound source for the voice symbol // (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing) @@ -2636,7 +2621,6 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) tagPos[VZ] += ( mBodySize[VZ] + 0.125f ); mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos ); } -#endif // XXX_STINSON_CHUI_REWORK }//if ( voiceEnabled ) } diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index d380a8672f..b497f80560 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -45,7 +45,6 @@ //29de489d-0491-fb00-7dab-f9e686d31e83 -#ifdef XXX_STINSON_CHUI_REWORK //-------------------------------------------------------------------------------------- // sound symbol constants //-------------------------------------------------------------------------------------- @@ -61,7 +60,6 @@ const F32 BASE_BRIGHTNESS = 0.7f; // gray level of the voice indicator when qu const F32 DOT_SIZE = 0.05f; // size of the dot billboard texture const F32 DOT_OPACITY = 0.7f; // how opaque the dot is const F32 WAVE_MOTION_RATE = 1.5f; // scalar applied to consecutive waves as a function of speaking amplitude -#endif // XXX_STINSON_CHUI_REWORK //-------------------------------------------------------------------------------------- // gesticulation constants @@ -69,13 +67,11 @@ const F32 WAVE_MOTION_RATE = 1.5f; // scalar applied to consecutive waves as a const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE = 0.2f; const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE = 1.0f; -#ifdef XXX_STINSON_CHUI_REWORK //-------------------------------------------------------------------------------------- // other constants //-------------------------------------------------------------------------------------- const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code. const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL -#endif // XXX_STINSON_CHUI_REWORK //------------------------------------------------------------------ // Initialize the statics @@ -98,28 +94,12 @@ F32 LLVoiceVisualizer::sAahPowerTransfersf = 0.0f; //----------------------------------------------- // constructor //----------------------------------------------- -#ifdef XXX_STINSON_CHUI_REWORK LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) : LLHUDEffect(type) -#else // XXX_STINSON_CHUI_REWORK -LLVoiceVisualizer::LLVoiceVisualizer() - : LLRefCount(), - mTimer(), - mStartTime(0.0), - mCurrentlySpeaking(false), - mSpeakingAmplitude(0.0f), - mMaxGesticulationAmplitude(DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE), - mMinGesticulationAmplitude(DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE) -#endif // XXX_STINSON_CHUI_REWORK { -#ifdef XXX_STINSON_CHUI_REWORK mCurrentTime = mTimer.getTotalSeconds(); mPreviousTime = mCurrentTime; mStartTime = mCurrentTime; -#else // XXX_STINSON_CHUI_REWORK - mStartTime = mTimer.getTotalSeconds(); -#endif // XXX_STINSON_CHUI_REWORK -#ifdef XXX_STINSON_CHUI_REWORK mVoiceSourceWorldPosition = LLVector3( 0.0f, 0.0f, 0.0f ); mSpeakingAmplitude = 0.0f; mCurrentlySpeaking = false; @@ -128,11 +108,9 @@ LLVoiceVisualizer::LLVoiceVisualizer() mMaxGesticulationAmplitude = DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE; mSoundSymbol.mActive = true; mSoundSymbol.mPosition = LLVector3( 0.0f, 0.0f, 0.0f ); -#endif // XXX_STINSON_CHUI_REWORK mTimer.reset(); -#ifdef XXX_STINSON_CHUI_REWORK const char* sound_level_img[] = { "voice_meter_dot.j2c", @@ -154,7 +132,6 @@ LLVoiceVisualizer::LLVoiceVisualizer() } mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); -#endif // XXX_STINSON_CHUI_REWORK // The first instance loads the initial state from prefs. if (!sPrefsInitialized) @@ -174,7 +151,6 @@ LLVoiceVisualizer::LLVoiceVisualizer() }//--------------------------------------------------- -#ifdef XXX_STINSON_CHUI_REWORK //--------------------------------------------------- void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m ) { @@ -195,16 +171,13 @@ void LLVoiceVisualizer::setVoiceEnabled( bool v ) mVoiceEnabled = v; }//--------------------------------------------------- -#endif // XXX_STINSON_CHUI_REWORK //--------------------------------------------------- void LLVoiceVisualizer::setStartSpeaking() { mStartTime = mTimer.getTotalSeconds(); mCurrentlySpeaking = true; -#ifdef XXX_STINSON_CHUI_REWORK mSoundSymbol.mActive = true; -#endif // XXX_STINSON_CHUI_REWORK }//--------------------------------------------------- @@ -359,7 +332,6 @@ void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah ) }//--------------------------------------------------- -#ifdef XXX_STINSON_CHUI_REWORK //--------------------------------------------------- // this method is inherited from HUD Effect //--------------------------------------------------- @@ -558,7 +530,6 @@ void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p ) mVoiceSourceWorldPosition = p; }//--------------------------------------------------- -#endif // XXX_STINSON_CHUI_REWORK //--------------------------------------------------- VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel() @@ -589,7 +560,6 @@ LLVoiceVisualizer::~LLVoiceVisualizer() }//---------------------------------------------- -#ifdef XXX_STINSON_CHUI_REWORK //--------------------------------------------------- // "packData" is inherited from HUDEffect //--------------------------------------------------- @@ -639,5 +609,3 @@ void LLVoiceVisualizer::markDead() LLHUDEffect::markDead(); }//------------------------------------------------------------------ - -#endif // XXX_STINSON_CHUI_REWORK diff --git a/indra/newview/llvoicevisualizer.h b/indra/newview/llvoicevisualizer.h index 5da592c48e..36c78252d1 100644 --- a/indra/newview/llvoicevisualizer.h +++ b/indra/newview/llvoicevisualizer.h @@ -42,12 +42,7 @@ #ifndef LL_VOICE_VISUALIZER_H #define LL_VOICE_VISUALIZER_H -#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot -#ifdef XXX_STINSON_CHUI_REWORK #include "llhudeffect.h" -#else // XXX_STINSON_CHUI_REWORK -#include "llpointer.h" -#endif // XXX_STINSON_CHUI_REWORK //----------------------------------------------------------------------------------------------- // The values of voice gesticulation represent energy levels for avatar animation, based on @@ -65,45 +60,30 @@ enum VoiceGesticulationLevel NUM_VOICE_GESTICULATION_LEVELS }; -#ifdef XXX_STINSON_CHUI_REWORK const static int NUM_VOICE_SYMBOL_WAVES = 7; -#endif // XXX_STINSON_CHUI_REWORK //---------------------------------------------------- // LLVoiceVisualizer class //---------------------------------------------------- -#ifdef XXX_STINSON_CHUI_REWORK class LLVoiceVisualizer : public LLHUDEffect -#else // XXX_STINSON_CHUI_REWORK -class LLVoiceVisualizer : public LLRefCount -#endif // XXX_STINSON_CHUI_REWORK { //--------------------------------------------------- // public methods //--------------------------------------------------- public: -#ifdef XXX_STINSON_CHUI_REWORK LLVoiceVisualizer( const U8 type ); //constructor -#else // XXX_STINSON_CHUI_REWORK - LLVoiceVisualizer(); //constructor -#endif // XXX_STINSON_CHUI_REWORK ~LLVoiceVisualizer(); //destructor -#ifdef XXX_STINSON_CHUI_REWORK void setVoiceSourceWorldPosition( const LLVector3 &p ); // this should be the position of the speaking avatar's head void setMinGesticulationAmplitude( F32 ); // the lower range of meaningful amplitude for setting gesticulation level void setMaxGesticulationAmplitude( F32 ); // the upper range of meaningful amplitude for setting gesticulation level -#endif // XXX_STINSON_CHUI_REWORK void setStartSpeaking(); // tell me when the av starts speaking -#ifdef XXX_STINSON_CHUI_REWORK void setVoiceEnabled( bool ); // tell me whether or not the user is voice enabled -#endif // XXX_STINSON_CHUI_REWORK void setSpeakingAmplitude( F32 ); // tell me how loud the av is speaking (ranges from 0 to 1) void setStopSpeaking(); // tell me when the av stops speaking bool getCurrentlySpeaking(); // the get for the above set VoiceGesticulationLevel getCurrentGesticulationLevel(); // based on voice amplitude, I'll give you the current "energy level" of avatar speech void lipSyncOohAah( F32& ooh, F32& aah ); -#ifdef XXX_STINSON_CHUI_REWORK void render(); // inherited from HUD Effect void packData(LLMessageSystem *mesgsys); // inherited from HUD Effect void unpackData(LLMessageSystem *mesgsys, S32 blocknum); // inherited from HUD Effect @@ -119,7 +99,6 @@ class LLVoiceVisualizer : public LLRefCount //---------------------------------------------------------------------------------------------- void setMaxGesticulationAmplitude(); void setMinGesticulationAmplitude(); -#endif // XXX_STINSON_CHUI_REWORK //--------------------------------------------------- // private members @@ -129,7 +108,6 @@ class LLVoiceVisualizer : public LLRefCount static void setPreferences( ); static void lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ); // convert a string of digits to an array of floats -#ifdef XXX_STINSON_CHUI_REWORK struct SoundSymbol { F32 mWaveExpansion [ NUM_VOICE_SYMBOL_WAVES ]; @@ -140,20 +118,15 @@ class LLVoiceVisualizer : public LLRefCount bool mActive; LLVector3 mPosition; }; -#endif // XXX_STINSON_CHUI_REWORK LLFrameTimer mTimer; // so I can ask the current time in seconds F64 mStartTime; // time in seconds when speaking started -#ifdef XXX_STINSON_CHUI_REWORK F64 mCurrentTime; // current time in seconds, captured every step F64 mPreviousTime; // copy of "current time" from last frame SoundSymbol mSoundSymbol; // the sound symbol that appears over the avatar's head bool mVoiceEnabled; // if off, no rendering should happen -#endif // XXX_STINSON_CHUI_REWORK bool mCurrentlySpeaking; // is the user currently speaking? -#ifdef XXX_STINSON_CHUI_REWORK LLVector3 mVoiceSourceWorldPosition; // give this to me every step - I need it to update the sound symbol -#endif // XXX_STINSON_CHUI_REWORK F32 mSpeakingAmplitude; // this should be set as often as possible when the user is speaking F32 mMaxGesticulationAmplitude; // this is the upper-limit of the envelope of detectable gesticulation leves F32 mMinGesticulationAmplitude; // this is the lower-limit of the envelope of detectable gesticulation leves -- cgit v1.2.3 From 1bebff84ba56b2ecfc0d24b4246fa417f12c66b6 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Mon, 17 Dec 2012 16:11:52 -0800 Subject: Removing some old code for parsing the response from changing maturity level as it is now consistent across the grid. --- indra/newview/llagent.cpp | 58 ++++++++++++----------------------------------- 1 file changed, 14 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 22a21ffaeb..49c570c30b 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2541,51 +2541,21 @@ void LLMaturityPreferencesResponder::error(U32 pStatus, const std::string& pReas U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent) { - // stinson 05/24/2012 Pathfinding regions have re-defined the response behavior. In the old server code, - // if you attempted to change the preferred maturity to the same value, the response content would be an - // undefined LLSD block. In the new server code with pathfinding, the response content should always be - // defined. Thus, the check for isUndefined() can be replaced with an assert after pathfinding is merged - // into server trunk and fully deployed. U8 maturity = SIM_ACCESS_MIN; - if (pContent.isUndefined()) - { - maturity = mPreferredMaturity; - } - else - { - llassert(!pContent.isUndefined()); - llassert(pContent.isMap()); - - if (!pContent.isUndefined() && pContent.isMap()) - { - // stinson 05/24/2012 Pathfinding regions have re-defined the response syntax. The if statement catches - // the new syntax, and the else statement catches the old syntax. After pathfinding is merged into - // server trunk and fully deployed, we can remove the else statement. - if (pContent.has("access_prefs")) - { - llassert(pContent.has("access_prefs")); - llassert(pContent.get("access_prefs").isMap()); - llassert(pContent.get("access_prefs").has("max")); - llassert(pContent.get("access_prefs").get("max").isString()); - if (pContent.get("access_prefs").isMap() && pContent.get("access_prefs").has("max") && - pContent.get("access_prefs").get("max").isString()) - { - LLSD::String actualPreference = pContent.get("access_prefs").get("max").asString(); - LLStringUtil::trim(actualPreference); - maturity = LLViewerRegion::shortStringToAccess(actualPreference); - } - } - else if (pContent.has("max")) - { - llassert(pContent.get("max").isString()); - if (pContent.get("max").isString()) - { - LLSD::String actualPreference = pContent.get("max").asString(); - LLStringUtil::trim(actualPreference); - maturity = LLViewerRegion::shortStringToAccess(actualPreference); - } - } - } + + llassert(!pContent.isUndefined()); + llassert(pContent.isMap()); + llassert(pContent.has("access_prefs")); + llassert(pContent.get("access_prefs").isMap()); + llassert(pContent.get("access_prefs").has("max")); + llassert(pContent.get("access_prefs").get("max").isString()); + if (!pContent.isUndefined() && pContent.isMap() && pContent.has("access_prefs") + && pContent.get("access_prefs").isMap() && pContent.get("access_prefs").has("max") + && pContent.get("access_prefs").get("max").isString()) + { + LLSD::String actualPreference = pContent.get("access_prefs").get("max").asString(); + LLStringUtil::trim(actualPreference); + maturity = LLViewerRegion::shortStringToAccess(actualPreference); } return maturity; -- cgit v1.2.3 From 138d4f5fcd4567c5d77230b6eadc21c246ceed59 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Mon, 17 Dec 2012 16:15:28 -0800 Subject: Updating a comment. --- indra/newview/llflexibleobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index aae0990e4b..c2b9c77307 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -444,7 +444,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate() return ; } - // stinson 11/12/2012: Need to check with davep on the following. + // Fix for MAINT-1894 // Skipping the flexible update if render res is negative. If we were to continue with a negative value, // the subsequent S32 num_render_sections = 1<<mRenderRes; code will specify a really large number of // render sections which will then create a length exception in the std::vector::resize() method. -- cgit v1.2.3 From 6fe7144104cd8b5bd9c7d215f76afdeafe13b7ee Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 17 Dec 2012 18:59:01 -0800 Subject: CHUI-580 : WIP : Protect callback connections passed to LLAvatarNameCache::get() where necessary --- indra/llui/llnotifications.cpp | 12 +++++------- indra/llui/llscrolllistctrl.cpp | 1 + indra/llui/llurlentry.cpp | 22 ++++++++++++++-------- indra/llui/llurlentry.h | 16 ++++++++++++++++ indra/newview/llavataractions.cpp | 8 +++----- indra/newview/llavatariconctrl.cpp | 9 ++++----- indra/newview/llavatarlistitem.cpp | 9 ++++----- indra/newview/llcallingcard.cpp | 4 +--- indra/newview/llchathistory.cpp | 9 ++++----- indra/newview/llconversationlog.cpp | 9 +++++++-- indra/newview/llconversationlog.h | 10 +++++++++- indra/newview/llconversationmodel.cpp | 11 +++++------ indra/newview/llfloaterdisplayname.cpp | 10 +++------- indra/newview/llfloaterinspect.cpp | 34 +++++++++++++++++++++------------- indra/newview/llfloaterinspect.h | 7 +++---- indra/newview/llfloaterreporter.cpp | 14 ++++++++++++-- indra/newview/llfloaterreporter.h | 1 + indra/newview/llfloatersellland.cpp | 15 ++++++++++++--- indra/newview/llfloatervoicevolume.cpp | 13 +++++++++++-- indra/newview/llimview.cpp | 23 +++++++++++++++-------- indra/newview/llimview.h | 12 +++++++++++- indra/newview/llinspectavatar.cpp | 16 ++++++++++++---- indra/newview/llinventorybridge.cpp | 4 +--- indra/newview/llnamelistctrl.cpp | 13 +++++++++---- indra/newview/llnamelistctrl.h | 8 ++++++++ indra/newview/llpanelgroupgeneral.cpp | 19 +++++++++++++------ indra/newview/llpanelgroupgeneral.h | 1 + indra/newview/llpanelgroupinvite.cpp | 32 +++++++++++++++++++++++++++----- indra/newview/llpanelgrouproles.cpp | 15 ++++++++++++--- indra/newview/llpanelgrouproles.h | 1 + indra/newview/llpanelplaceprofile.cpp | 23 ++++++++++++++++------- indra/newview/llpanelplaceprofile.h | 4 +++- indra/newview/llpathfindingobject.cpp | 1 + indra/newview/lltoolpie.cpp | 20 ++------------------ indra/newview/llviewerdisplayname.cpp | 7 ++++--- indra/newview/llviewermessage.cpp | 19 ++++++------------- indra/newview/llvoavatar.cpp | 5 +++-- indra/newview/llvoicevivox.cpp | 16 ++++++++++++---- indra/newview/llvoicevivox.h | 1 + 39 files changed, 294 insertions(+), 160 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index fd9bfec203..6b00225605 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1814,15 +1814,13 @@ void LLPostponedNotification::onGroupNameCache(const LLUUID& id, void LLPostponedNotification::fetchAvatarName(const LLUUID& id) { - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } - if (id.notNull()) { - mAvatarNameCacheConnection = LLAvatarNameCache::get(id, - boost::bind(&LLPostponedNotification::onAvatarNameCache, this, _1, _2)); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(id, boost::bind(&LLPostponedNotification::onAvatarNameCache, this, _1, _2)); } } diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 7ed7042aff..26aadd056f 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1832,6 +1832,7 @@ void LLScrollListCtrl::copyNameToClipboard(std::string id, bool is_group) { LLAvatarName av_name; LLAvatarNameCache::get(LLUUID(id), &av_name); + // Note: Will return an empty string if the avatar name was not cached for that id. Fine in that case. name = av_name.getUserName(); } LLUrlAction::copyURLToClipboard(name); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index fd2635c73a..71db238c94 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -340,7 +340,8 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const // secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about // x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about // -LLUrlEntryAgent::LLUrlEntryAgent() +LLUrlEntryAgent::LLUrlEntryAgent() : + mAvatarNameCacheConnection() { mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/\\w+", boost::regex::perl|boost::regex::icase); @@ -456,9 +457,11 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa } else { - LLAvatarNameCache::get(agent_id, - boost::bind(&LLUrlEntryAgent::onAvatarNameCache, - this, _1, _2)); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgent::onAvatarNameCache, this, _1, _2)); addObserver(agent_id_string, url, cb); return LLTrans::getString("LoadingData"); } @@ -515,7 +518,8 @@ std::string LLUrlEntryAgent::getIcon(const std::string &url) // secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username) // x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username) // -LLUrlEntryAgentName::LLUrlEntryAgentName() +LLUrlEntryAgentName::LLUrlEntryAgentName() : + mAvatarNameCacheConnection() {} void LLUrlEntryAgentName::onAvatarNameCache(const LLUUID& id, @@ -554,9 +558,11 @@ std::string LLUrlEntryAgentName::getLabel(const std::string &url, const LLUrlLab } else { - LLAvatarNameCache::get(agent_id, - boost::bind(&LLUrlEntryAgentCompleteName::onAvatarNameCache, - this, _1, _2)); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgentCompleteName::onAvatarNameCache, this, _1, _2)); addObserver(agent_id_string, url, cb); return LLTrans::getString("LoadingData"); } diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 5f82721c0f..8c6c32178a 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -171,6 +171,13 @@ class LLUrlEntryAgent : public LLUrlEntryBase { public: LLUrlEntryAgent(); + ~LLUrlEntryAgent() + { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + } /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); /*virtual*/ std::string getIcon(const std::string &url); /*virtual*/ std::string getTooltip(const std::string &string) const; @@ -181,6 +188,7 @@ protected: /*virtual*/ void callObservers(const std::string &id, const std::string &label, const std::string& icon); private: void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name); + boost::signals2::connection mAvatarNameCacheConnection; }; /// @@ -192,6 +200,13 @@ class LLUrlEntryAgentName : public LLUrlEntryBase, public boost::signals2::track { public: LLUrlEntryAgentName(); + ~LLUrlEntryAgentName() + { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + } /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); /*virtual*/ LLStyle::Params getStyle() const; protected: @@ -199,6 +214,7 @@ protected: virtual std::string getName(const LLAvatarName& avatar_name) = 0; private: void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name); + boost::signals2::connection mAvatarNameCacheConnection; }; diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 59b862503c..5a185c9571 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -94,7 +94,7 @@ void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::strin LLRecentPeople::instance().add(id); } -void on_avatar_name_friendship(const LLUUID& id, const LLAvatarName av_name) +static void on_avatar_name_friendship(const LLUUID& id, const LLAvatarName av_name) { LLAvatarActions::requestFriendshipDialog(id, av_name.getCompleteName()); } @@ -195,8 +195,7 @@ void LLAvatarActions::startIM(const LLUUID& id) if (id.isNull()) return; - LLAvatarNameCache::get(id, - boost::bind(&on_avatar_name_cache_start_im, _1, _2)); + LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_cache_start_im, _1, _2)); } // static @@ -231,8 +230,7 @@ void LLAvatarActions::startCall(const LLUUID& id) { return; } - LLAvatarNameCache::get(id, - boost::bind(&on_avatar_name_cache_start_call, _1, _2)); + LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_cache_start_call, _1, _2)); } // static diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 0db38c947c..60a2c14911 100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -261,13 +261,12 @@ void LLAvatarIconCtrl::setValue(const LLSD& value) void LLAvatarIconCtrl::fetchAvatarName() { - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } - if (mAvatarId.notNull()) { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } mAvatarNameCacheConnection = LLAvatarNameCache::get(mAvatarId, boost::bind(&LLAvatarIconCtrl::onAvatarNameCache, this, _1, _2)); } } diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 84e177d4a4..b4a70008e7 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -143,13 +143,12 @@ BOOL LLAvatarListItem::postBuild() void LLAvatarListItem::fetchAvatarName() { - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } - if (mAvatarId.notNull()) { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLAvatarListItem::onAvatarNameCache, this, _2)); } } diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 9a295faa73..30306b230f 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -704,9 +704,7 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online) if(chat_notify) { // Look up the name of this agent for the notification - LLAvatarNameCache::get(agent_id, - boost::bind(&on_avatar_name_cache_notify, - _1, _2, online, payload)); + LLAvatarNameCache::get(agent_id,boost::bind(&on_avatar_name_cache_notify,_1, _2, online, payload)); } mModifyMask |= LLFriendObserver::ONLINE; diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 3e25d9c457..764ee4a8ea 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -539,13 +539,12 @@ private: void fetchAvatarName() { - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } - if (mAvatarID.notNull()) { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } mAvatarNameCacheConnection = LLAvatarNameCache::get(mAvatarID, boost::bind(&LLChatHistoryHeader::onAvatarNameCache, this, _1, _2)); } diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index a0765f5e16..f8ccb08e66 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -185,7 +185,8 @@ void LLConversationLogFriendObserver::changed(U32 mask) /* LLConversationLog implementation */ /************************************************************************/ -LLConversationLog::LLConversationLog() +LLConversationLog::LLConversationLog() : + mAvatarNameCacheConnection() { LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); if (ctrl) @@ -251,7 +252,11 @@ void LLConversationLog::createConversation(const LLIMModel::LLIMSession* session if (LLIMModel::LLIMSession::P2P_SESSION == session->mSessionType) { - LLAvatarNameCache::get(session->mOtherParticipantID, boost::bind(&LLConversationLog::onAvatarNameCache, this, _1, _2, session)); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(session->mOtherParticipantID, boost::bind(&LLConversationLog::onAvatarNameCache, this, _1, _2, session)); } notifyObservers(); diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 8f6ac3f5d1..35462ec3a4 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -141,7 +141,14 @@ public: private: LLConversationLog(); - + virtual ~LLConversationLog() + { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + } + void enableLogging(bool enable); /** @@ -176,6 +183,7 @@ private: LLFriendObserver* mFriendObserver; // Observer of the LLAvatarTracker instance boost::signals2::connection newMessageSignalConnection; + boost::signals2::connection mAvatarNameCacheConnection; }; class LLConversationLogObserver diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index d03ad92fbc..ef9e0e02e5 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -421,16 +421,15 @@ LLConversationItemParticipant::~LLConversationItemParticipant() void LLConversationItemParticipant::fetchAvatarName() { - // Disconnect any previous avatar name cache connection - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } - // Request the avatar name from the cache llassert(getUUID().notNull()); if (getUUID().notNull()) { + // Disconnect any previous avatar name cache connection + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } mAvatarNameCacheConnection = LLAvatarNameCache::get(getUUID(), boost::bind(&LLConversationItemParticipant::onAvatarNameCache, this, _2)); } } diff --git a/indra/newview/llfloaterdisplayname.cpp b/indra/newview/llfloaterdisplayname.cpp index be1ee77152..e2cef5630b 100644 --- a/indra/newview/llfloaterdisplayname.cpp +++ b/indra/newview/llfloaterdisplayname.cpp @@ -44,7 +44,7 @@ class LLFloaterDisplayName : public LLFloater { public: LLFloaterDisplayName(const LLSD& key); - virtual ~LLFloaterDisplayName() {}; + virtual ~LLFloaterDisplayName() { } /*virtual*/ BOOL postBuild(); void onSave(); void onReset(); @@ -58,8 +58,8 @@ private: const LLSD& content); }; -LLFloaterDisplayName::LLFloaterDisplayName(const LLSD& key) - : LLFloater(key) +LLFloaterDisplayName::LLFloaterDisplayName(const LLSD& key) : + LLFloater(key) { } @@ -122,10 +122,6 @@ void LLFloaterDisplayName::onCacheSetName(bool success, LLSD args; args["DISPLAY_NAME"] = content["display_name"]; LLNotificationsUtil::add("SetDisplayNameSuccess", args); - - // Re-fetch my name, as it may have been sanitized by the service - //LLAvatarNameCache::get(getAvatarId(), - // boost::bind(&LLPanelMyProfileEdit::onNameCache, this, _1, _2)); return; } diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp index cece8d299c..3636bba355 100644 --- a/indra/newview/llfloaterinspect.cpp +++ b/indra/newview/llfloaterinspect.cpp @@ -46,7 +46,9 @@ LLFloaterInspect::LLFloaterInspect(const LLSD& key) : LLFloater(key), - mDirty(FALSE) + mDirty(FALSE), + mOwnerNameCacheConnection(), + mCreatorNameCacheConnection() { mCommitCallbackRegistrar.add("Inspect.OwnerProfile", boost::bind(&LLFloaterInspect::onClickOwnerProfile, this)); mCommitCallbackRegistrar.add("Inspect.CreatorProfile", boost::bind(&LLFloaterInspect::onClickCreatorProfile, this)); @@ -67,6 +69,14 @@ BOOL LLFloaterInspect::postBuild() LLFloaterInspect::~LLFloaterInspect(void) { + if (mOwnerNameCacheConnection.connected()) + { + mOwnerNameCacheConnection.disconnect(); + } + if (mCreatorNameCacheConnection.connected()) + { + mCreatorNameCacheConnection.disconnect(); + } if(!LLFloaterReg::instanceVisible("build")) { if(LLToolMgr::getInstance()->getBaseTool() == LLToolCompInspect::getInstance()) @@ -80,7 +90,6 @@ LLFloaterInspect::~LLFloaterInspect(void) { LLFloaterReg::showInstance("build", LLSD(), TRUE); } - //sInstance = NULL; } void LLFloaterInspect::onOpen(const LLSD& key) @@ -167,15 +176,6 @@ LLUUID LLFloaterInspect::getSelectedUUID() return LLUUID::null; } -void LLFloaterInspect::onGetAvNameCallback(const LLUUID& idCreator, const LLAvatarName& av_name, void* FloaterPtr) -{ - if (FloaterPtr) - { - LLFloaterInspect* floater = (LLFloaterInspect*)FloaterPtr; - floater->dirty(); - } -} - void LLFloaterInspect::refresh() { LLUUID creator_id; @@ -229,7 +229,11 @@ void LLFloaterInspect::refresh() else { owner_name = LLTrans::getString("RetrievingData"); - LLAvatarNameCache::get(idOwner, boost::bind(&LLFloaterInspect::onGetAvNameCallback, _1, _2, this)); + if (mOwnerNameCacheConnection.connected()) + { + mOwnerNameCacheConnection.disconnect(); + } + mOwnerNameCacheConnection = LLAvatarNameCache::get(idOwner, boost::bind(&LLFloaterInspect::setDirty, this)); } if (LLAvatarNameCache::get(idCreator, &av_name)) @@ -239,7 +243,11 @@ void LLFloaterInspect::refresh() else { creator_name = LLTrans::getString("RetrievingData"); - LLAvatarNameCache::get(idCreator, boost::bind(&LLFloaterInspect::onGetAvNameCallback, _1, _2, this)); + if (mCreatorNameCacheConnection.connected()) + { + mCreatorNameCacheConnection.disconnect(); + } + mCreatorNameCacheConnection = LLAvatarNameCache::get(idCreator, boost::bind(&LLFloaterInspect::setDirty, this)); } row["id"] = obj->getObject()->getID(); diff --git a/indra/newview/llfloaterinspect.h b/indra/newview/llfloaterinspect.h index 7ee83ccdb4..495f8f0a39 100644 --- a/indra/newview/llfloaterinspect.h +++ b/indra/newview/llfloaterinspect.h @@ -55,8 +55,6 @@ public: void onClickOwnerProfile(); void onSelectObject(); - static void onGetAvNameCallback(const LLUUID& idCreator, const LLAvatarName& av_name, void* FloaterPtr); - LLScrollListCtrl* mObjectList; protected: // protected members @@ -64,13 +62,14 @@ protected: bool mDirty; private: + void onGetAvNameCallback(const LLUUID& idCreator, const LLAvatarName& av_name); LLFloaterInspect(const LLSD& key); virtual ~LLFloaterInspect(void); - // static data -// static LLFloaterInspect* sInstance; LLSafeHandle<LLObjectSelection> mObjectSelection; + boost::signals2::connection mOwnerNameCacheConnection; + boost::signals2::connection mCreatorNameCacheConnection; }; #endif //LL_LLFLOATERINSPECT_H diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index cf2481f99a..79387747a5 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -103,7 +103,8 @@ LLFloaterReporter::LLFloaterReporter(const LLSD& key) mPicking( FALSE), mPosition(), mCopyrightWarningSeen( FALSE ), - mResourceDatap(new LLResourceData()) + mResourceDatap(new LLResourceData()), + mAvatarNameCacheConnection() { } @@ -187,6 +188,11 @@ BOOL LLFloaterReporter::postBuild() // virtual LLFloaterReporter::~LLFloaterReporter() { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + // child views automatically deleted mObjectID = LLUUID::null; @@ -313,7 +319,11 @@ void LLFloaterReporter::setFromAvatarID(const LLUUID& avatar_id) std::string avatar_link = LLSLURL("agent", mObjectID, "inspect").getSLURLString(); getChild<LLUICtrl>("owner_name")->setValue(avatar_link); - LLAvatarNameCache::get(avatar_id, boost::bind(&LLFloaterReporter::onAvatarNameCache, this, _1, _2)); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(avatar_id, boost::bind(&LLFloaterReporter::onAvatarNameCache, this, _1, _2)); } void LLFloaterReporter::onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name) diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h index 7d68431710..d54e7f6ab0 100644 --- a/indra/newview/llfloaterreporter.h +++ b/indra/newview/llfloaterreporter.h @@ -137,6 +137,7 @@ private: std::list<LLMeanCollisionData*> mMCDList; std::string mDefaultSummary; LLResourceData* mResourceDatap; + boost::signals2::connection mAvatarNameCacheConnection; }; #endif diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index c97a6792f3..ec13a6ff1d 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -81,6 +81,7 @@ private: LLUUID mAuthorizedBuyer; bool mParcelSoldWithObjects; SelectionObserver mParcelSelectionObserver; + boost::signals2::connection mAvatarNameCacheConnection; void updateParcelInfo(); void refreshUI(); @@ -129,13 +130,18 @@ LLFloater* LLFloaterSellLand::buildFloater(const LLSD& key) LLFloaterSellLandUI::LLFloaterSellLandUI(const LLSD& key) : LLFloater(key), mParcelSelectionObserver(this), - mRegion(0) + mRegion(0), + mAvatarNameCacheConnection() { LLViewerParcelMgr::getInstance()->addObserver(&mParcelSelectionObserver); } LLFloaterSellLandUI::~LLFloaterSellLandUI() { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } LLViewerParcelMgr::getInstance()->removeObserver(&mParcelSelectionObserver); } @@ -230,8 +236,11 @@ void LLFloaterSellLandUI::updateParcelInfo() if(mSellToBuyer) { - LLAvatarNameCache::get(mAuthorizedBuyer, - boost::bind(&LLFloaterSellLandUI::onBuyerNameCache, this, _2)); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(mAuthorizedBuyer, boost::bind(&LLFloaterSellLandUI::onBuyerNameCache, this, _2)); } } diff --git a/indra/newview/llfloatervoicevolume.cpp b/indra/newview/llfloatervoicevolume.cpp index a1df73a065..82d366a48e 100644 --- a/indra/newview/llfloatervoicevolume.cpp +++ b/indra/newview/llfloatervoicevolume.cpp @@ -81,12 +81,14 @@ private: LLUUID mAvatarID; // Need avatar name information to spawn friend add request LLAvatarName mAvatarName; + boost::signals2::connection mAvatarNameCacheConnection; }; LLFloaterVoiceVolume::LLFloaterVoiceVolume(const LLSD& sd) : LLInspect(LLSD()) // single_instance, doesn't really need key , mAvatarID() // set in onOpen() *Note: we used to show partner's name but we dont anymore --angela 3rd Dec* , mAvatarName() +, mAvatarNameCacheConnection() { LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::GLOBAL, this); LLTransientFloater::init(this); @@ -94,6 +96,10 @@ LLFloaterVoiceVolume::LLFloaterVoiceVolume(const LLSD& sd) LLFloaterVoiceVolume::~LLFloaterVoiceVolume() { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } LLTransientFloaterMgr::getInstance()->removeControlView(this); } @@ -126,8 +132,11 @@ void LLFloaterVoiceVolume::onOpen(const LLSD& data) getChild<LLUICtrl>("avatar_name")->setValue(""); updateVolumeControls(); - LLAvatarNameCache::get(mAvatarID, - boost::bind(&LLFloaterVoiceVolume::onAvatarNameCache, this, _1, _2)); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(mAvatarID, boost::bind(&LLFloaterVoiceVolume::onAvatarNameCache, this, _1, _2)); } void LLFloaterVoiceVolume::updateVolumeControls() diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 4e2ac09dd8..d3569694f1 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -253,7 +253,8 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& mTextIMPossible(true), mOtherParticipantIsAvatar(true), mStartCallOnInitialize(false), - mStartedAsIMCall(voice) + mStartedAsIMCall(voice), + mAvatarNameCacheConnection() { // set P2P type by default mSessionType = P2P_SESSION; @@ -334,9 +335,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& // history files have consistent (English) names in different locales. if (isAdHocSessionType() && IM_SESSION_INVITE == mType) { - LLAvatarNameCache::get(mOtherParticipantID, - boost::bind(&LLIMModel::LLIMSession::onAdHocNameCache, - this, _2)); + mAvatarNameCacheConnection = LLAvatarNameCache::get(mOtherParticipantID,boost::bind(&LLIMModel::LLIMSession::onAdHocNameCache,this, _2)); } } @@ -450,6 +449,11 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES LLIMModel::LLIMSession::~LLIMSession() { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + delete mSpeakers; mSpeakers = NULL; @@ -2056,7 +2060,8 @@ BOOL LLOutgoingCallDialog::postBuild() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) : -LLCallDialog(payload) +LLCallDialog(payload), +mAvatarNameCacheConnection() { } @@ -2126,9 +2131,11 @@ BOOL LLIncomingCallDialog::postBuild() else { // Get the full name information - LLAvatarNameCache::get(caller_id, - boost::bind(&LLIncomingCallDialog::onAvatarNameCache, - this, _1, _2, call_type)); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(caller_id, boost::bind(&LLIncomingCallDialog::onAvatarNameCache, this, _1, _2, call_type)); } setIcon(session_id, caller_id); diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 19b738069c..b46ce33ba6 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -142,6 +142,7 @@ public: void onAdHocNameCache(const LLAvatarName& av_name); static LLUUID generateHash(const std::set<LLUUID>& sorted_uuids); + boost::signals2::connection mAvatarNameCacheConnection; }; @@ -547,7 +548,14 @@ class LLIncomingCallDialog : public LLCallDialog { public: LLIncomingCallDialog(const LLSD& payload); - + ~LLIncomingCallDialog() + { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + } + /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); @@ -564,6 +572,8 @@ private: const LLAvatarName& av_name, const std::string& call_type); + boost::signals2::connection mAvatarNameCacheConnection; + /*virtual*/ void onLifetimeExpired(); }; diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 3507b729be..2136bd289f 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -88,6 +88,7 @@ private: // an in-flight request for avatar properties from LLAvatarPropertiesProcessor // is represented by this object LLFetchAvatarData* mPropertiesRequest; + boost::signals2::connection mAvatarNameCacheConnection; }; ////////////////////////////////////////////////////////////////////////////// @@ -140,7 +141,8 @@ LLInspectAvatar::LLInspectAvatar(const LLSD& sd) : LLInspect( LLSD() ), // single_instance, doesn't really need key mAvatarID(), // set in onOpen() *Note: we used to show partner's name but we dont anymore --angela 3rd Dec* mAvatarName(), - mPropertiesRequest(NULL) + mPropertiesRequest(NULL), + mAvatarNameCacheConnection() { // can't make the properties request until the widgets are constructed // as it might return immediately, so do it in onOpen. @@ -151,6 +153,10 @@ LLInspectAvatar::LLInspectAvatar(const LLSD& sd) LLInspectAvatar::~LLInspectAvatar() { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } // clean up any pending requests so they don't call back into a deleted // view delete mPropertiesRequest; @@ -226,9 +232,11 @@ void LLInspectAvatar::requestUpdate() getChild<LLUICtrl>("avatar_icon")->setValue(LLSD(mAvatarID) ); - LLAvatarNameCache::get(mAvatarID, - boost::bind(&LLInspectAvatar::onAvatarNameCache, - this, _1, _2)); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(mAvatarID,boost::bind(&LLInspectAvatar::onAvatarNameCache,this, _1, _2)); } void LLInspectAvatar::processAvatarData(LLAvatarData* data) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 1e60b10a68..cb6290368c 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4713,9 +4713,7 @@ void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string act if (item && (item->getCreatorUUID() != gAgent.getID()) && (!item->getCreatorUUID().isNull())) { - std::string callingcard_name; - gCacheName->getFullName(item->getCreatorUUID(), callingcard_name); - // IDEVO + std::string callingcard_name = LLCacheName::getDefaultName(); LLAvatarName av_name; if (LLAvatarNameCache::get(item->getCreatorUUID(), &av_name)) { diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 855007e403..1ff241ccb8 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -64,7 +64,8 @@ LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p) mNameColumnIndex(p.name_column.column_index), mNameColumn(p.name_column.column_name), mAllowCallingCardDrop(p.allow_calling_card_drop), - mShortNames(p.short_names) + mShortNames(p.short_names), + mAvatarNameCacheConnection() {} // public @@ -327,9 +328,13 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( else { // ...schedule a callback - LLAvatarNameCache::get(id, - boost::bind(&LLNameListCtrl::onAvatarNameCache, - this, _1, _2, item->getHandle())); + // This is not correct and will likely lead to partially populated lists in cases where avatar names are not cached. + // *TODO : Change this to have 2 callbacks : one callback per list item and one for the whole list. + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(id,boost::bind(&LLNameListCtrl::onAvatarNameCache,this, _1, _2, item->getHandle())); } break; } diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 3ac0565761..271802d48a 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -111,6 +111,13 @@ public: protected: LLNameListCtrl(const Params&); + virtual ~LLNameListCtrl() + { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + } friend class LLUICtrlFactory; public: // Add a user to the list by name. It will be added, the name @@ -154,6 +161,7 @@ private: std::string mNameColumn; BOOL mAllowCallingCardDrop; bool mShortNames; // display name only, no SLID + boost::signals2::connection mAvatarNameCacheConnection; }; diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 51b4d2ea65..69d2c84e8a 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -79,13 +79,18 @@ LLPanelGroupGeneral::LLPanelGroupGeneral() mCtrlReceiveNotices(NULL), mCtrlListGroup(NULL), mActiveTitleLabel(NULL), - mComboActiveTitle(NULL) + mComboActiveTitle(NULL), + mAvatarNameCacheConnection() { } LLPanelGroupGeneral::~LLPanelGroupGeneral() { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } } BOOL LLPanelGroupGeneral::postBuild() @@ -728,9 +733,12 @@ void LLPanelGroupGeneral::updateMembers() else { // If name is not cached, onNameCache() should be called when it is cached and add this member to list. - LLAvatarNameCache::get(mMemberProgress->first, - boost::bind(&LLPanelGroupGeneral::onNameCache, - this, mUdpateSessionID, member, _1, _2)); + // *TODO : Use a callback per member, not for the panel group. + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(mMemberProgress->first, boost::bind(&LLPanelGroupGeneral::onNameCache, this, mUdpateSessionID, member, _1, _2)); } } @@ -770,8 +778,7 @@ void LLPanelGroupGeneral::addMember(LLGroupMemberData* member) void LLPanelGroupGeneral::onNameCache(const LLUUID& update_id, LLGroupMemberData* member, const LLUUID& id, const LLAvatarName& av_name) { - if (!member - || update_id != mUdpateSessionID) + if (!member || update_id != mUdpateSessionID) { return; } diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h index b179f78c56..cecf613a7e 100644 --- a/indra/newview/llpanelgroupgeneral.h +++ b/indra/newview/llpanelgroupgeneral.h @@ -112,6 +112,7 @@ private: LLComboBox *mComboMature; LLGroupMgrGroupData::member_list_t::iterator mMemberProgress; + boost::signals2::connection mAvatarNameCacheConnection; }; #endif diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index a2bbc5400c..1951a96c54 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -89,6 +89,8 @@ public: void (*mCloseCallback)(void* data); void* mCloseCallbackUserData; + + boost::signals2::connection mAvatarNameCacheConnection; }; @@ -102,12 +104,17 @@ LLPanelGroupInvite::impl::impl(const LLUUID& group_id): mGroupName( NULL ), mConfirmedOwnerInvite( false ), mCloseCallback( NULL ), - mCloseCallbackUserData( NULL ) + mCloseCallbackUserData( NULL ), + mAvatarNameCacheConnection() { } LLPanelGroupInvite::impl::~impl() { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } } void LLPanelGroupInvite::impl::addUsers(const std::vector<std::string>& names, @@ -380,8 +387,24 @@ void LLPanelGroupInvite::impl::callbackAddUsers(const uuid_vec_t& agent_ids, voi std::vector<std::string> names; for (S32 i = 0; i < (S32)agent_ids.size(); i++) { - LLAvatarNameCache::get(agent_ids[i], - boost::bind(&LLPanelGroupInvite::impl::onAvatarNameCache, _1, _2, user_data)); + LLAvatarName av_name; + if (LLAvatarNameCache::get(agent_ids[i], &av_name)) + { + LLPanelGroupInvite::impl::onAvatarNameCache(agent_ids[i], av_name, user_data); + } + else + { + impl* selfp = (impl*) user_data; + if (selfp) + { + if (selfp->mAvatarNameCacheConnection.connected()) + { + selfp->mAvatarNameCacheConnection.disconnect(); + } + // *TODO : Add a callback per avatar name being fetched. + selfp->mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_ids[i],boost::bind(&LLPanelGroupInvite::impl::onAvatarNameCache, _1, _2, user_data)); + } + } } } @@ -473,8 +496,7 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids) if (!LLAvatarNameCache::get(agent_id, &av_name)) { // actually it should happen, just in case - LLAvatarNameCache::get(LLUUID(agent_id), boost::bind( - &LLPanelGroupInvite::addUserCallback, this, _1, _2)); + //LLAvatarNameCache::get(LLUUID(agent_id), boost::bind(&LLPanelGroupInvite::addUserCallback, this, _1, _2)); // for this special case! //when there is no cached name we should remove resident from agent_ids list to avoid breaking of sequence // removed id will be added in callback diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 7ad7e7149b..e6b85386dd 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -743,13 +743,18 @@ LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab() mChanged(FALSE), mPendingMemberUpdate(FALSE), mHasMatch(FALSE), - mNumOwnerAdditions(0) + mNumOwnerAdditions(0), + mAvatarNameCacheConnection() { mUdpateSessionID = LLUUID::null; } LLPanelGroupMembersSubTab::~LLPanelGroupMembersSubTab() { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } if (mMembersList) { gSavedSettings.setString("GroupMembersSortOrder", mMembersList->getSortColumnName()); @@ -1678,8 +1683,12 @@ void LLPanelGroupMembersSubTab::updateMembers() else { // If name is not cached, onNameCache() should be called when it is cached and add this member to list. - LLAvatarNameCache::get(mMemberProgress->first, boost::bind(&LLPanelGroupMembersSubTab::onNameCache, - this, mUdpateSessionID, mMemberProgress->second, _1, _2)); + // *TODO : Add one callback per fetched avatar name + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(mMemberProgress->first, boost::bind(&LLPanelGroupMembersSubTab::onNameCache, this, mUdpateSessionID, mMemberProgress->second, _1, _2)); } } diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index 8b454e020a..29b56f83d8 100644 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -217,6 +217,7 @@ protected: U32 mNumOwnerAdditions; LLGroupMgrGroupData::member_list_t::iterator mMemberProgress; + boost::signals2::connection mAvatarNameCacheConnection; }; class LLPanelGroupRolesSubTab : public LLPanelGroupSubTab diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index ce8057eead..3660169f01 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -79,13 +79,18 @@ LLPanelPlaceProfile::LLPanelPlaceProfile() mForSalePanel(NULL), mYouAreHerePanel(NULL), mSelectedParcelID(-1), - mAccordionCtrl(NULL) + mAccordionCtrl(NULL), + mAvatarNameCacheConnection() {} // virtual LLPanelPlaceProfile::~LLPanelPlaceProfile() { gIdleCallbacks.deleteFunction(&LLPanelPlaceProfile::updateYouAreHereBanner, this); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } } // virtual @@ -499,9 +504,11 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, std::string parcel_owner = LLSLURL("agent", parcel->getOwnerID(), "inspect").getSLURLString(); mParcelOwner->setText(parcel_owner); - LLAvatarNameCache::get(region->getOwner(), - boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, - _1, _2, mRegionOwnerText)); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(region->getOwner(), boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mRegionOwnerText)); } if(LLParcel::OS_LEASE_PENDING == parcel->getOwnershipStatus()) @@ -523,9 +530,11 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID(); if(auth_buyer_id.notNull()) { - LLAvatarNameCache::get(auth_buyer_id, - boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, - _1, _2, mSaleToText)); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(auth_buyer_id, boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mSaleToText)); // Show sales info to a specific person or a group he belongs to. if (auth_buyer_id != gAgent.getID() && !gAgent.isInGroup(auth_buyer_id)) diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h index a33fc12ce4..6d42118d37 100644 --- a/indra/newview/llpanelplaceprofile.h +++ b/indra/newview/llpanelplaceprofile.h @@ -38,7 +38,7 @@ class LLPanelPlaceProfile : public LLPanelPlaceInfo public: LLPanelPlaceProfile(); /*virtual*/ ~LLPanelPlaceProfile(); - + /*virtual*/ BOOL postBuild(); /*virtual*/ void resetLocation(); @@ -116,6 +116,8 @@ private: LLTextEditor* mResaleText; LLTextBox* mSaleToText; LLAccordionCtrl* mAccordionCtrl; + + boost::signals2::connection mAvatarNameCacheConnection; }; #endif // LL_LLPANELPLACEPROFILE_H diff --git a/indra/newview/llpathfindingobject.cpp b/indra/newview/llpathfindingobject.cpp index 858d3203c0..900763eae4 100644 --- a/indra/newview/llpathfindingobject.cpp +++ b/indra/newview/llpathfindingobject.cpp @@ -173,6 +173,7 @@ void LLPathfindingObject::fetchOwnerName() mHasOwnerName = LLAvatarNameCache::get(mOwnerUUID, &mOwnerName); if (!mHasOwnerName) { + disconnectAvatarNameCacheConnection(); mAvatarNameCacheConnection = LLAvatarNameCache::get(mOwnerUUID, boost::bind(&LLPathfindingObject::handleAvatarNameFetch, this, _1, _2)); } } diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index c81f6ace70..babb5065f7 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -972,24 +972,8 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l || !existing_inspector->getVisible() || existing_inspector->getKey()["avatar_id"].asUUID() != hover_object->getID()) { - // IDEVO: try to get display name + username + // Try to get display name + username std::string final_name; - std::string full_name; - if (!gCacheName->getFullName(hover_object->getID(), full_name)) - { - LLNameValue* firstname = hover_object->getNVPair("FirstName"); - LLNameValue* lastname = hover_object->getNVPair("LastName"); - if (firstname && lastname) - { - full_name = LLCacheName::buildFullName( - firstname->getString(), lastname->getString()); - } - else - { - full_name = LLTrans::getString("TooltipPerson"); - } - } - LLAvatarName av_name; if (LLAvatarNameCache::get(hover_object->getID(), &av_name)) { @@ -997,7 +981,7 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l } else { - final_name = full_name; + final_name = LLTrans::getString("TooltipPerson");; } // *HACK: We may select this object, so pretend it was clicked diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp index 4bd38562bc..6bd5631df6 100644 --- a/indra/newview/llviewerdisplayname.cpp +++ b/indra/newview/llviewerdisplayname.cpp @@ -53,6 +53,7 @@ namespace LLViewerDisplayName sNameChangedSignal.connect(cb); } + void doNothing() { } } class LLSetDisplayNameResponder : public LLHTTPClient::Responder @@ -139,9 +140,9 @@ public: LLUUID agent_id = gAgent.getID(); // Flush stale data LLAvatarNameCache::erase( agent_id ); - // Queue request for new data - LLAvatarName ignored; - LLAvatarNameCache::get( agent_id, &ignored ); + // Queue request for new data: nothing to do on callback though... + // Note: no need to disconnect the callback as it never gets out of scope + LLAvatarNameCache::get(agent_id, boost::bind(&LLViewerDisplayName::doNothing)); // Kill name tag, as it is wrong LLVOAvatar::invalidateNameTag( agent_id ); } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 5bb7db5c0d..f5da94dc87 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2254,7 +2254,7 @@ static std::string clean_name_from_task_im(const std::string& msg, return msg; } -void notification_display_name_callback(const LLUUID& id, +static void notification_display_name_callback(const LLUUID& id, const LLAvatarName& av_name, const std::string& name, LLSD& substitutions, @@ -2278,7 +2278,7 @@ protected: }; // Callback for name resolution of a god/estate message -void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string message) +static void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string message) { LLSD args; args["NAME"] = av_name.getCompleteName(); @@ -3212,12 +3212,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) args["NAME"] = name; LLSD payload; payload["from_id"] = from_id; - LLAvatarNameCache::get(from_id, boost::bind(¬ification_display_name_callback, - _1, - _2, - "FriendshipAccepted", - args, - payload)); + LLAvatarNameCache::get(from_id, boost::bind(¬ification_display_name_callback,_1,_2,"FriendshipAccepted",args,payload)); } break; @@ -5651,11 +5646,9 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) _1, _2, _3, notification, final_args, payload)); } - else { - LLAvatarNameCache::get(name_id, - boost::bind(&money_balance_avatar_notify, - _1, _2, - notification, final_args, payload)); + else + { + LLAvatarNameCache::get(name_id, boost::bind(&money_balance_avatar_notify, _1, _2, notification, final_args, payload)); } } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 7cc4e3ed04..951c145f25 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3193,8 +3193,9 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) LLAvatarName av_name; if (!LLAvatarNameCache::get(getID(), &av_name)) { - // ...call this function back when the name arrives and force a rebuild - LLAvatarNameCache::get(getID(),boost::bind(&LLVOAvatar::clearNameTag, this)); + // Force a rebuild at next idle + // Note: do not connect a callback on idle(). + clearNameTag(); } // Might be blank if name not available yet, that's OK diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 6fdda12a1c..bd7914af6f 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -316,7 +316,9 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() : mCaptureBufferRecording(false), mCaptureBufferRecorded(false), mCaptureBufferPlaying(false), - mPlayRequestCount(0) + mPlayRequestCount(0), + + mAvatarNameCacheConnection() { mSpeakerVolume = scale_speaker_volume(0); @@ -349,6 +351,10 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() : LLVivoxVoiceClient::~LLVivoxVoiceClient() { + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } } //--------------------------------------------------- @@ -6192,9 +6198,11 @@ void LLVivoxVoiceClient::notifyFriendObservers() void LLVivoxVoiceClient::lookupName(const LLUUID &id) { - LLAvatarNameCache::get(id, - boost::bind(&LLVivoxVoiceClient::onAvatarNameCache, - this, _1, _2)); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + mAvatarNameCacheConnection = LLAvatarNameCache::get(id, boost::bind(&LLVivoxVoiceClient::onAvatarNameCache, this, _1, _2)); } void LLVivoxVoiceClient::onAvatarNameCache(const LLUUID& agent_id, diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index f2a3a7d3dd..69f33df94b 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -641,6 +641,7 @@ protected: void lookupName(const LLUUID &id); void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name); void avatarNameResolved(const LLUUID &id, const std::string &name); + boost::signals2::connection mAvatarNameCacheConnection; ///////////////////////////// // Voice fonts -- cgit v1.2.3 From c2d332a89cb29d54df40f1f120304d871278fb76 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 17 Dec 2012 20:16:33 -0800 Subject: CHUI-580 : WIP : Added disconnect of callbacks once they're called to prevent filling up the callback queue --- indra/llui/llnotifications.cpp | 2 ++ indra/llui/llurlentry.cpp | 8 ++++++-- indra/newview/llavatariconctrl.cpp | 2 ++ indra/newview/llavatarlistitem.cpp | 2 ++ indra/newview/llchathistory.cpp | 2 ++ indra/newview/llconversationlog.cpp | 1 + indra/newview/llconversationmodel.cpp | 2 ++ indra/newview/llfloaterinspect.cpp | 16 ++++++++++++++-- indra/newview/llfloaterinspect.h | 3 ++- indra/newview/llfloaterreporter.cpp | 2 ++ indra/newview/llfloatersellland.cpp | 2 ++ indra/newview/llfloatervoicevolume.cpp | 2 ++ indra/newview/llimview.cpp | 3 +++ indra/newview/llinspectavatar.cpp | 2 ++ indra/newview/llnamelistctrl.cpp | 2 ++ indra/newview/llpanelgroupgeneral.cpp | 2 ++ indra/newview/llpanelgroupinvite.cpp | 4 ++++ indra/newview/llpanelgrouproles.cpp | 2 ++ indra/newview/llpanelplaceprofile.cpp | 19 +++---------------- indra/newview/llpanelplaceprofile.h | 2 -- indra/newview/llvoicevivox.cpp | 1 + 21 files changed, 58 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 6b00225605..8fb7a9d864 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1827,6 +1827,8 @@ void LLPostponedNotification::fetchAvatarName(const LLUUID& id) void LLPostponedNotification::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); + std::string name = av_name.getCompleteName(); // from PE merge - we should figure out if this is the right thing to do diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 1758218b7d..99ee688888 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -372,7 +372,9 @@ void LLUrlEntryAgent::callObservers(const std::string &id, void LLUrlEntryAgent::onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name) { - std::string label = av_name.getCompleteName(); + mAvatarNameCacheConnection.disconnect(); + + std::string label = av_name.getCompleteName(); // received the agent name from the server - tell our observers callObservers(id.asString(), label, mIcon); @@ -525,6 +527,8 @@ LLUrlEntryAgentName::LLUrlEntryAgentName() : void LLUrlEntryAgentName::onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); + std::string label = getName(av_name); // received the agent name from the server - tell our observers callObservers(id.asString(), label, mIcon); @@ -562,7 +566,7 @@ std::string LLUrlEntryAgentName::getLabel(const std::string &url, const LLUrlLab { mAvatarNameCacheConnection.disconnect(); } - mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgentCompleteName::onAvatarNameCache, this, _1, _2)); + mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgentName::onAvatarNameCache, this, _1, _2)); addObserver(agent_id_string, url, cb); return LLTrans::getString("LoadingData"); } diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 60a2c14911..714bde6f37 100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -313,6 +313,8 @@ void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type) void LLAvatarIconCtrl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); + if (agent_id == mAvatarId) { // Most avatar icon controls are next to a UI element that shows diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index f5308563b5..3ed0c7c482 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -459,6 +459,8 @@ void LLAvatarListItem::setNameInternal(const std::string& name, const std::strin void LLAvatarListItem::onAvatarNameCache(const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); + setAvatarName(av_name.getDisplayName()); setAvatarToolTip(av_name.getUserName()); diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 764ee4a8ea..3f959c0510 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -552,6 +552,8 @@ private: void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); + mFrom = av_name.getDisplayName(); LLTextBox* user_name = getChild<LLTextBox>("user_name"); diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index f8ccb08e66..3b75cd8203 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -518,5 +518,6 @@ void LLConversationLog::onNewMessageReceived(const LLSD& data) void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, const LLIMModel::LLIMSession* session) { + mAvatarNameCacheConnection.disconnect(); updateConversationName(session, av_name.getCompleteName()); } diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index ef9e0e02e5..b1f45d6d64 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -446,6 +446,8 @@ void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); + mName = av_name.getUserName(); mDisplayName = av_name.getDisplayName(); mNeedsRefresh = true; diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp index 3636bba355..5a1dfc99ab 100644 --- a/indra/newview/llfloaterinspect.cpp +++ b/indra/newview/llfloaterinspect.cpp @@ -233,7 +233,7 @@ void LLFloaterInspect::refresh() { mOwnerNameCacheConnection.disconnect(); } - mOwnerNameCacheConnection = LLAvatarNameCache::get(idOwner, boost::bind(&LLFloaterInspect::setDirty, this)); + mOwnerNameCacheConnection = LLAvatarNameCache::get(idOwner, boost::bind(&LLFloaterInspect::onGetOwnerNameCallback, this)); } if (LLAvatarNameCache::get(idCreator, &av_name)) @@ -247,7 +247,7 @@ void LLFloaterInspect::refresh() { mCreatorNameCacheConnection.disconnect(); } - mCreatorNameCacheConnection = LLAvatarNameCache::get(idCreator, boost::bind(&LLFloaterInspect::setDirty, this)); + mCreatorNameCacheConnection = LLAvatarNameCache::get(idCreator, boost::bind(&LLFloaterInspect::onGetCreatorNameCallback, this)); } row["id"] = obj->getObject()->getID(); @@ -297,6 +297,18 @@ void LLFloaterInspect::dirty() setDirty(); } +void LLFloaterInspect::onGetOwnerNameCallback() +{ + mOwnerNameCacheConnection.disconnect(); + setDirty(); +} + +void LLFloaterInspect::onGetCreatorNameCallback() +{ + mCreatorNameCacheConnection.disconnect(); + setDirty(); +} + void LLFloaterInspect::draw() { if (mDirty) diff --git a/indra/newview/llfloaterinspect.h b/indra/newview/llfloaterinspect.h index 495f8f0a39..44381eac96 100644 --- a/indra/newview/llfloaterinspect.h +++ b/indra/newview/llfloaterinspect.h @@ -62,7 +62,8 @@ protected: bool mDirty; private: - void onGetAvNameCallback(const LLUUID& idCreator, const LLAvatarName& av_name); + void onGetOwnerNameCallback(); + void onGetCreatorNameCallback(); LLFloaterInspect(const LLSD& key); virtual ~LLFloaterInspect(void); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 79387747a5..0e4c7406c5 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -328,6 +328,8 @@ void LLFloaterReporter::setFromAvatarID(const LLUUID& avatar_id) void LLFloaterReporter::onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); + if (mObjectID == avatar_id) { mOwnerName = av_name.getCompleteName(); diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index ec13a6ff1d..0cb37dabe7 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -246,6 +246,8 @@ void LLFloaterSellLandUI::updateParcelInfo() void LLFloaterSellLandUI::onBuyerNameCache(const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); + getChild<LLUICtrl>("sell_to_agent")->setValue(av_name.getCompleteName()); getChild<LLUICtrl>("sell_to_agent")->setToolTip(av_name.getUserName()); } diff --git a/indra/newview/llfloatervoicevolume.cpp b/indra/newview/llfloatervoicevolume.cpp index 82d366a48e..38446e46df 100644 --- a/indra/newview/llfloatervoicevolume.cpp +++ b/indra/newview/llfloatervoicevolume.cpp @@ -199,6 +199,8 @@ void LLFloaterVoiceVolume::onAvatarNameCache( const LLUUID& agent_id, const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); + if (agent_id != mAvatarID) { return; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d3569694f1..9195ea2344 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -341,6 +341,8 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& void LLIMModel::LLIMSession::onAdHocNameCache(const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); + if (!av_name.isValidName()) { S32 separator_index = mName.rfind(" "); @@ -2178,6 +2180,7 @@ void LLIncomingCallDialog::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, const std::string& call_type) { + mAvatarNameCacheConnection.disconnect(); std::string title = av_name.getCompleteName(); setCallerName(title, av_name.getCompleteName(), call_type); } diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 2136bd289f..26d3a2bd12 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -269,6 +269,8 @@ void LLInspectAvatar::onAvatarNameCache( const LLUUID& agent_id, const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); + if (agent_id == mAvatarID) { getChild<LLUICtrl>("user_name")->setValue(av_name.getDisplayName()); diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 1ff241ccb8..7f396b7b7e 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -393,6 +393,8 @@ void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, LLHandle<LLNameListItem> item) { + mAvatarNameCacheConnection.disconnect(); + std::string name; if (mShortNames) name = av_name.getDisplayName(); diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 684c975e2d..0cd93b330a 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -777,6 +777,8 @@ void LLPanelGroupGeneral::addMember(LLGroupMemberData* member) void LLPanelGroupGeneral::onNameCache(const LLUUID& update_id, LLGroupMemberData* member, const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); if (!gdatap diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index 77d74a5d1a..133b269c11 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -417,6 +417,10 @@ void LLPanelGroupInvite::impl::onAvatarNameCache(const LLUUID& agent_id, if (selfp) { + if (selfp->mAvatarNameCacheConnection.connected()) + { + selfp->mAvatarNameCacheConnection.disconnect(); + } std::vector<std::string> names; uuid_vec_t agent_ids; agent_ids.push_back(agent_id); diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 907b02993a..cfdac11d26 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -1609,6 +1609,8 @@ void LLPanelGroupMembersSubTab::addMemberToList(LLGroupMemberData* data) void LLPanelGroupMembersSubTab::onNameCache(const LLUUID& update_id, LLGroupMemberData* member, const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); if (!gdatap || gdatap->getMemberVersion() != update_id diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index 3660169f01..83b70d9f29 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -79,18 +79,13 @@ LLPanelPlaceProfile::LLPanelPlaceProfile() mForSalePanel(NULL), mYouAreHerePanel(NULL), mSelectedParcelID(-1), - mAccordionCtrl(NULL), - mAvatarNameCacheConnection() + mAccordionCtrl(NULL) {} // virtual LLPanelPlaceProfile::~LLPanelPlaceProfile() { gIdleCallbacks.deleteFunction(&LLPanelPlaceProfile::updateYouAreHereBanner, this); - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } } // virtual @@ -504,11 +499,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, std::string parcel_owner = LLSLURL("agent", parcel->getOwnerID(), "inspect").getSLURLString(); mParcelOwner->setText(parcel_owner); - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } - mAvatarNameCacheConnection = LLAvatarNameCache::get(region->getOwner(), boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mRegionOwnerText)); + LLAvatarNameCache::get(region->getOwner(), boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mRegionOwnerText)); } if(LLParcel::OS_LEASE_PENDING == parcel->getOwnershipStatus()) @@ -530,11 +521,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID(); if(auth_buyer_id.notNull()) { - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } - mAvatarNameCacheConnection = LLAvatarNameCache::get(auth_buyer_id, boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mSaleToText)); + LLAvatarNameCache::get(auth_buyer_id, boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mSaleToText)); // Show sales info to a specific person or a group he belongs to. if (auth_buyer_id != gAgent.getID() && !gAgent.isInGroup(auth_buyer_id)) diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h index 6d42118d37..f4c6145881 100644 --- a/indra/newview/llpanelplaceprofile.h +++ b/indra/newview/llpanelplaceprofile.h @@ -116,8 +116,6 @@ private: LLTextEditor* mResaleText; LLTextBox* mSaleToText; LLAccordionCtrl* mAccordionCtrl; - - boost::signals2::connection mAvatarNameCacheConnection; }; #endif // LL_LLPANELPLACEPROFILE_H diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index d89ecb6306..5e121bbcee 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -6208,6 +6208,7 @@ void LLVivoxVoiceClient::lookupName(const LLUUID &id) void LLVivoxVoiceClient::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) { + mAvatarNameCacheConnection.disconnect(); std::string display_name = av_name.getDisplayName(); avatarNameResolved(agent_id, display_name); } -- cgit v1.2.3 From 355e7a061311df30f019fd722df6072b745b0ef6 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Tue, 18 Dec 2012 12:25:19 +0200 Subject: CHUI-586 (Scroll bar only partially shown initially on torn off conversations) --- indra/newview/llfloaterimsessiontab.cpp | 17 ++++++++++++++++- indra/newview/llfloaterimsessiontab.h | 2 ++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index ea99a1c5bf..07907095f8 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -177,6 +177,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id) // LLFloater::mLastHostHandle = floater_container (a "future" host) conversp->setHost(floater_container); conversp->setHost(NULL); + conversp->forceReshape(); } // Added floaters share some state (like sort order) with their host conversp->setSortOrder(floater_container->getSortOrder()); @@ -224,7 +225,8 @@ BOOL LLFloaterIMSessionTab::postBuild() setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); - mSaveRect = isTornOff(); + mSaveRect = isNearbyChat() + && !gSavedSettings.getBOOL("NearbyChatIsNotTornOff"); initRectControl(); if (isChatMultiTab()) @@ -649,6 +651,15 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() showTranslationCheckbox(); } + +void LLFloaterIMSessionTab::forceReshape() +{ + LLRect floater_rect = getRect(); + reshape(llmax(floater_rect.getWidth(), this->getMinWidth()), + llmax(floater_rect.getHeight(), this->getMinHeight()), + true); +} + void LLFloaterIMSessionTab::reshapeChatHistory() { @@ -755,6 +766,10 @@ void LLFloaterIMSessionTab::onTearOffClicked() mSaveRect = isTornOff(); initRectControl(); LLFloater::onClickTearOff(this); + if (isTornOff()) + { + forceReshape(); + } refreshConversation(); } diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index cd0bcd481c..9aeda9ddf9 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -96,6 +96,8 @@ public: virtual void updateMessages() {} LLConversationItem* getCurSelectedViewModelItem(); + void forceReshape(); + protected: // callback for click on any items of the visual states menu -- cgit v1.2.3 From 6b165ce2ade6db7d5e6cb23e039e4949dc71e617 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Tue, 18 Dec 2012 15:09:50 +0200 Subject: CHUI-562 FIXED Gear button is added for p2p torn-off floater. --- indra/newview/llfloaterimsession.cpp | 33 ++++++++ indra/newview/llfloaterimsession.h | 3 + indra/newview/llfloaterimsessiontab.cpp | 53 +++++++++++- indra/newview/llfloaterimsessiontab.h | 5 +- .../skins/default/xui/en/floater_im_session.xml | 15 ++++ .../skins/default/xui/en/menu_im_conversation.xml | 94 ++++++++++++++++++++++ 6 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/menu_im_conversation.xml (limited to 'indra') diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index a0ca7286f1..f2afe9d7bb 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -83,6 +83,9 @@ LLFloaterIMSession::LLFloaterIMSession(const LLUUID& session_id) setOverlapsScreenChannel(true); LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); + mEnableCallbackRegistrar.add("Avatar.EnableGearItem", boost::bind(&LLFloaterIMSession::enableGearMenuItem, this, _2)); + mCommitCallbackRegistrar.add("Avatar.GearDoToSelected", boost::bind(&LLFloaterIMSession::GearDoToSelected, this, _2)); + mEnableCallbackRegistrar.add("Avatar.CheckGearItem", boost::bind(&LLFloaterIMSession::checkGearMenuItem, this, _2)); setDocked(true); } @@ -190,6 +193,36 @@ void LLFloaterIMSession::onSendMsg( LLUICtrl* ctrl, void* userdata ) self->setTyping(false); } +bool LLFloaterIMSession::enableGearMenuItem(const LLSD& userdata) +{ + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; + selected_uuids.push_back(mOtherParticipantUUID); + + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + return floater_container->enableContextMenuItem(command, selected_uuids); +} + +void LLFloaterIMSession::GearDoToSelected(const LLSD& userdata) +{ + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; + selected_uuids.push_back(mOtherParticipantUUID); + + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + floater_container->doToParticipants(command, selected_uuids); +} + +bool LLFloaterIMSession::checkGearMenuItem(const LLSD& userdata) +{ + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; + selected_uuids.push_back(mOtherParticipantUUID); + + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + return floater_container->checkContextMenuItem(command, selected_uuids); +} + void LLFloaterIMSession::sendMsgFromInputEditor() { if (gAgent.isGodlike() diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index 1d8957b1d9..43d84eb8c0 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -99,6 +99,9 @@ public: void setPositioned(bool b) { mPositioned = b; }; void onVisibilityChange(const LLSD& new_visibility); + bool enableGearMenuItem(const LLSD& userdata); + void GearDoToSelected(const LLSD& userdata); + bool checkGearMenuItem(const LLSD& userdata); // Implements LLVoiceClientStatusObserver::onChange() to enable the call // button when voice is available diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index ea99a1c5bf..267dba562c 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -197,6 +197,8 @@ BOOL LLFloaterIMSessionTab::postBuild() mTearOffBtn = getChild<LLButton>("tear_off_btn"); mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this)); + mGearBtn = getChild<LLButton>("gear_btn"); + mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); // Add a scroller for the folder (participant) view @@ -239,11 +241,11 @@ BOOL LLFloaterIMSessionTab::postBuild() // Now ready to build the conversation and participants list buildConversationViewParticipant(); refreshConversation(); - + // Zero expiry time is set only once to allow initial update. mRefreshTimer->setTimerExpirySec(0); mRefreshTimer->start(); - + initBtns(); return result; } @@ -756,6 +758,53 @@ void LLFloaterIMSessionTab::onTearOffClicked() initRectControl(); LLFloater::onClickTearOff(this); refreshConversation(); + updateGearBtn(); +} + +void LLFloaterIMSessionTab::updateGearBtn() +{ + + bool prevVisibility = mGearBtn->getVisible(); + mGearBtn->setVisible(checkIfTornOff() && mIsP2PChat); + + + // Move buttons if Gear button changed visibility + if(prevVisibility != mGearBtn->getVisible()) + { + LLRect gear_btn_rect = mGearBtn->getRect(); + LLRect add_btn_rect = getChild<LLButton>("add_btn")->getRect(); + LLRect call_btn_rect = getChild<LLButton>("voice_call_btn")->getRect(); + S32 gap_width = call_btn_rect.mLeft - add_btn_rect.mRight; + S32 right_shift = gear_btn_rect.getWidth() + gap_width; + if(mGearBtn->getVisible()) + { + // Move buttons to the right to give space for Gear button + add_btn_rect.translate(right_shift,0); + call_btn_rect.translate(right_shift,0); + } + else + { + add_btn_rect.translate(-right_shift,0); + call_btn_rect.translate(-right_shift,0); + } + getChild<LLButton>("add_btn")->setRect(add_btn_rect); + getChild<LLButton>("voice_call_btn")->setRect(call_btn_rect); + } +} + +void LLFloaterIMSessionTab::initBtns() +{ + LLRect gear_btn_rect = mGearBtn->getRect(); + LLRect add_btn_rect = getChild<LLButton>("add_btn")->getRect(); + LLRect call_btn_rect = getChild<LLButton>("voice_call_btn")->getRect(); + S32 gap_width = call_btn_rect.mLeft - add_btn_rect.mRight; + S32 right_shift = gear_btn_rect.getWidth() + gap_width; + + add_btn_rect.translate(-right_shift,0); + call_btn_rect.translate(-right_shift,0); + + getChild<LLButton>("add_btn")->setRect(add_btn_rect); + getChild<LLButton>("voice_call_btn")->setRect(call_btn_rect); } // static diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index cd0bcd481c..b05708059a 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -92,7 +92,8 @@ public: void setSortOrder(const LLConversationSort& order); virtual void onTearOffClicked(); - + void updateGearBtn(); + void initBtns(); virtual void updateMessages() {} LLConversationItem* getCurSelectedViewModelItem(); @@ -157,6 +158,8 @@ protected: LLButton* mExpandCollapseBtn; LLButton* mTearOffBtn; LLButton* mCloseBtn; + LLButton* mGearBtn; + private: // Handling selection and contextual menu diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index e4b127b7b9..4dbd52d05e 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -79,6 +79,21 @@ tool_tip="View/sort options" top="5" width="31" /> + <menu_button + menu_filename="menu_im_conversation.xml" + follows="top|left" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + top="5" + left_pad="4" + name="gear_btn" + visible="false" + tool_tip="Actions on selected person" + width="31"/> <button enabled="false" follows="top|left" diff --git a/indra/newview/skins/default/xui/en/menu_im_conversation.xml b/indra/newview/skins/default/xui/en/menu_im_conversation.xml new file mode 100644 index 0000000000..8882d0a7d8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_im_conversation.xml @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Conversation Gear Menu"> + <menu_item_call + label="View Profile" + layout="topleft" + name="View Profile"> + <on_click function="Avatar.GearDoToSelected" parameter="view_profile" /> + <on_enable function="Avatar.EnableGearItem" parameter="can_view_profile" /> + </menu_item_call> + <menu_item_call + label="Add Friend" + layout="topleft" + name="Add Friend"> + <on_click function="Avatar.GearDoToSelected" parameter="add_friend" /> + <on_enable function="Avatar.EnableGearItem" parameter="can_add" /> + </menu_item_call> + <menu_item_call + label="Remove friend" + layout="topleft" + name="remove_friend"> + <on_click function="Avatar.GearDoToSelected" parameter="remove_friend" /> + <on_enable function="Avatar.EnableGearItem" parameter="can_delete" /> + </menu_item_call> + <menu_item_call + label="Offer teleport" + layout="topleft" + name="offer_teleport"> + <on_click function="Avatar.GearDoToSelected" parameter="offer_teleport"/> + <on_enable function="Avatar.EnableGearItem" parameter="can_offer_teleport"/> + </menu_item_call> + <menu_item_call + label="Invite to group..." + layout="topleft" + name="invite_to_group"> + <on_click function="Avatar.GearDoToSelected" parameter="invite_to_group" /> + <on_enable function="Avatar.EnableGearItem" parameter="can_invite" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="View Icons Separator" /> + <menu_item_call + label="Chat history..." + layout="topleft" + name="chat_history"> + <on_click function="Avatar.GearDoToSelected" parameter="chat_history"/> + <on_enable function="Avatar.EnableGearItem" parameter="can_chat_history"/> + </menu_item_call> + <menu_item_separator + layout="topleft"/> + <menu_item_call + label="Map" + layout="topleft" + name="map"> + <on_click function="Avatar.GearDoToSelected" parameter="map" /> + <on_enable function="Avatar.EnableGearItem" parameter="can_show_on_map" /> + </menu_item_call> + <menu_item_call + label="Share" + layout="topleft" + name="Share"> + <on_click function="Avatar.GearDoToSelected" parameter="share" /> + <on_enable function="Avatar.EnableGearItem" parameter="can_share" /> + </menu_item_call> + <menu_item_call + label="Pay" + layout="topleft" + name="Pay"> + <on_click function="Avatar.GearDoToSelected" parameter="pay" /> + <on_enable function="Avatar.EnableGearItem" parameter="can_pay" /> + </menu_item_call> + <menu_item_separator + layout="topleft"/> + <menu_item_check + label="Block Voice" + layout="topleft" + name="Block/Unblock"> + <on_check function="Avatar.CheckGearItem" parameter="is_blocked" /> + <on_click function="Avatar.GearDoToSelected" parameter="block_unblock" /> + <on_enable function="Avatar.EnableGearItem" parameter="can_block" /> + </menu_item_check> + <menu_item_check + label="Block Text" + layout="topleft" + name="MuteText"> + <on_check function="Avatar.CheckGearItem" parameter="is_muted" /> + <on_click function="Avatar.GearDoToSelected" parameter="mute_unmute" /> + <on_enable function="Avatar.EnableGearItem" parameter="can_block" /> + </menu_item_check> + <menu_item_separator + layout="topleft"/> +</toggleable_menu> + -- cgit v1.2.3 From 90971d817193b416b580bfb46ed888776a59f972 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Tue, 18 Dec 2012 17:41:03 +0200 Subject: Additional fix for CHUI-562 --- indra/newview/llfloaterimsessiontab.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 267dba562c..01b30305c4 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -764,7 +764,7 @@ void LLFloaterIMSessionTab::onTearOffClicked() void LLFloaterIMSessionTab::updateGearBtn() { - bool prevVisibility = mGearBtn->getVisible(); + BOOL prevVisibility = mGearBtn->getVisible(); mGearBtn->setVisible(checkIfTornOff() && mIsP2PChat); -- cgit v1.2.3 From d2102c9b9f7ad31d3b5061a19f7b955af2f34b9f Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 19 Dec 2012 17:26:55 +0200 Subject: CHUI-601 : Fixed : Crash when dismissing a conversation while a participant is selected DeletePointer() for the items was replaced by Function LLFolderViewItem::destroyView(): Function LLFolderViewItem::destroyView(), before removing the item, immediately removes it from the Selection List of the Root Folder. As a result, at the time of the call of sanitizeSelection(), will not need to try to handle the elements that have already been deleted. --- indra/llui/llfolderviewitem.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 0a06ce66aa..dc7e4777a7 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1481,17 +1481,20 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) void LLFolderViewFolder::destroyView() { - std::for_each(mItems.begin(), mItems.end(), DeletePointer()); - mItems.clear(); + while (!mItems.empty()) + { + LLFolderViewItem *itemp = mItems.back(); + itemp->destroyView(); // LLFolderViewItem::destroyView() removes entry from mItems + } while (!mFolders.empty()) { LLFolderViewFolder *folderp = mFolders.back(); - folderp->destroyView(); // removes entry from mFolders + folderp->destroyView(); // LLFolderVievFolder::destroyView() removes entry from mFolders } LLFolderViewItem::destroyView(); - } +} // extractItem() removes the specified item from the folder, but // doesn't delete it. -- cgit v1.2.3 From b34e3a1b40fd72b4c4cdc1553c3f5934e9e9cef5 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 18 Dec 2012 18:30:14 +0200 Subject: Clean up: Removed unnecessary call removeConversationListItem() when floater closes (If session's floater will be removed for any reason, then will start a removing of the corresponding session and removeConversationListItem() will call from a session's observer); Local variable are renamed in accordance with the code styling --- indra/newview/llfloaterimcontainer.cpp | 7 ++++--- indra/newview/llfloaterimsessiontab.cpp | 13 ------------- indra/newview/llfloaterimsessiontab.h | 1 - 3 files changed, 4 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index ba5ec363d6..390eec84f6 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1412,17 +1412,18 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener - bool isWidgetSelected = false; + bool is_widget_selected = false; LLFolderViewItem* new_selection = NULL; LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); if (widget) { - isWidgetSelected = widget->isSelected(); + is_widget_selected = widget->isSelected(); new_selection = mConversationsRoot->getNextFromChild(widget); if(new_selection == NULL) { new_selection = mConversationsRoot->getPreviousFromChild(widget); } + widget->destroyView(); } @@ -1445,7 +1446,7 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c } } } - return isWidgetSelected; + return is_widget_selected; } LLConversationViewSession* LLFloaterIMContainer::createConversationItemWidget(LLConversationItem* item) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index d6955f37f2..7984034ded 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -748,19 +748,6 @@ void LLFloaterIMSessionTab::onOpen(const LLSD& key) } } -// virtual -void LLFloaterIMSessionTab::onClose(bool app_quitting) -{ - // Always suppress the IM from the conversations list on close if present for any reason - if (LLFloaterIMSessionTab::isChatMultiTab()) - { - LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); - if (im_box) - { - im_box->removeConversationListItem(mKey); - } - } -} void LLFloaterIMSessionTab::onTearOffClicked() { diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index a452c77224..0fa99a46be 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -77,7 +77,6 @@ public: // LLFloater overrides /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void onClose(bool app_quitting); /*virtual*/ BOOL postBuild(); /*virtual*/ void draw(); /*virtual*/ void setVisible(BOOL visible); -- cgit v1.2.3 From e64c8fdc145c6ae2727173d310a732a471aaf569 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Tue, 18 Dec 2012 18:57:13 +0200 Subject: CHUI-583 FIXED Menu items with appropriate links are added --- indra/newview/skins/default/xui/en/menu_viewer.xml | 53 +++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 3e7329c0b5..00424e97f6 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1267,7 +1267,58 @@ function="Floater.Show" parameter="hud" /> </menu_item_call>--> - + <menu_item_separator/> + + <menu_item_call + label="User’s guide" + name="User’s guide"> + <menu_item_call.on_click + function="Advanced.WebBrowserTest" + parameter="http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-User-s-Guide/ta-p/1244857"/> + </menu_item_call> + <menu_item_call + label="Knowledge Base" + name="Knowledge Base"> + <menu_item_call.on_click + function="Advanced.WebBrowserTest" + parameter="http://community.secondlife.com/t5/tkb/communitypage"/> + </menu_item_call> + <menu_item_call + label="Wiki" + name="Wiki"> + <menu_item_call.on_click + function="Advanced.WebBrowserTest" + parameter="http://wiki.secondlife.com"/> + </menu_item_call> + <menu_item_call + label="Community Forums" + name="Community Forums"> + <menu_item_call.on_click + function="Advanced.WebBrowserTest" + parameter="http://community.secondlife.com/t5/Forums/ct-p/Forums"/> + </menu_item_call> + <menu_item_call + label="Support portal" + name="Support portal"> + <menu_item_call.on_click + function="Advanced.WebBrowserTest" + parameter="https://support.secondlife.com/"/> + </menu_item_call> + <menu_item_separator/> + <menu_item_call + label="[SECOND_LIFE] News" + name="Second Life News"> + <menu_item_call.on_click + function="Advanced.WebBrowserTest" + parameter="http://community.secondlife.com/t5/Featured-News/bg-p/blog_feature_news"/> + </menu_item_call> + <menu_item_call + label="[SECOND_LIFE] Blogs" + name="Second Life Blogs"> + <menu_item_call.on_click + function="Advanced.WebBrowserTest" + parameter="http://community.secondlife.com/t5/Blogs/ct-p/Blogs"/> + </menu_item_call> <menu_item_separator/> <menu_item_call -- cgit v1.2.3 From 610b25ad3a070c984cb303250428a4a9b8301c6f Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Tue, 18 Dec 2012 18:33:16 +0200 Subject: CHUI-591 FIXED Issues with resizing conversations floater --- indra/newview/skins/default/xui/en/floater_im_container.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 37a3b9ac59..1837100c28 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -38,7 +38,7 @@ name="conversations_layout_panel" min_dim="38" width="225" - expanded_min_dim="200"> + expanded_min_dim="156"> <layout_stack animate="false" follows="left|top|right" @@ -108,7 +108,7 @@ image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" - left="5" + left="1" name="expand_collapse_btn" tool_tip="Collapse/Expand this list" width="31" /> @@ -128,7 +128,7 @@ auto_resize="true" user_resize="true" name="messages_layout_panel" - expanded_min_dim="225"> + expanded_min_dim="186"> <panel_container bottom="-1" follows="all" -- cgit v1.2.3 From fc89db6ca4f0cc41e9b20e52a2735ff1db143314 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 19 Dec 2012 00:09:47 +0200 Subject: CHUI-591 FIXED Issues with resizing conversations floater: small correction of size in right panel of conversation floater; --- indra/newview/skins/default/xui/en/floater_im_container.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 1837100c28..3475c7da33 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -128,7 +128,7 @@ auto_resize="true" user_resize="true" name="messages_layout_panel" - expanded_min_dim="186"> + expanded_min_dim="222"> <panel_container bottom="-1" follows="all" -- cgit v1.2.3 From cc900b732dd1af2790248485a270197a4006e0f7 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 19 Dec 2012 02:44:48 +0200 Subject: CHUI-592 FIXED Unread notifications are not being saved in notification chiclet --- indra/newview/llchiclet.cpp | 216 ++++++++++++++++++++- indra/newview/llchiclet.h | 208 +++++++++++++++++++- indra/newview/llchicletbar.cpp | 3 + indra/newview/llsyswellwindow.cpp | 15 ++ indra/newview/llsyswellwindow.h | 7 + indra/newview/skins/default/textures/textures.xml | 2 + .../xui/da/menu_notification_well_button.xml | 4 + .../xui/de/menu_notification_well_button.xml | 4 + .../xui/en/menu_notification_well_button.xml | 16 ++ .../skins/default/xui/en/panel_chiclet_bar.xml | 44 +++++ .../xui/es/menu_notification_well_button.xml | 4 + .../xui/fr/menu_notification_well_button.xml | 4 + .../xui/it/menu_notification_well_button.xml | 4 + .../xui/ja/menu_notification_well_button.xml | 4 + .../xui/pl/menu_notification_well_button.xml | 4 + .../xui/pt/menu_notification_well_button.xml | 4 + .../xui/ru/menu_notification_well_button.xml | 4 + .../xui/tr/menu_notification_well_button.xml | 4 + .../xui/zh/menu_notification_well_button.xml | 4 + 19 files changed, 546 insertions(+), 9 deletions(-) create mode 100644 indra/newview/skins/default/xui/da/menu_notification_well_button.xml create mode 100644 indra/newview/skins/default/xui/de/menu_notification_well_button.xml create mode 100644 indra/newview/skins/default/xui/en/menu_notification_well_button.xml create mode 100644 indra/newview/skins/default/xui/es/menu_notification_well_button.xml create mode 100644 indra/newview/skins/default/xui/fr/menu_notification_well_button.xml create mode 100644 indra/newview/skins/default/xui/it/menu_notification_well_button.xml create mode 100644 indra/newview/skins/default/xui/ja/menu_notification_well_button.xml create mode 100644 indra/newview/skins/default/xui/pl/menu_notification_well_button.xml create mode 100644 indra/newview/skins/default/xui/pt/menu_notification_well_button.xml create mode 100644 indra/newview/skins/default/xui/ru/menu_notification_well_button.xml create mode 100644 indra/newview/skins/default/xui/tr/menu_notification_well_button.xml create mode 100644 indra/newview/skins/default/xui/zh/menu_notification_well_button.xml (limited to 'indra') diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 1acbdd32b7..2fdcb17570 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -27,15 +27,17 @@ #include "llviewerprecompiledheaders.h" // must be first include #include "llchiclet.h" +#include "llchicletbar.h" #include "llfloaterimsession.h" #include "llfloaterimcontainer.h" #include "llfloaterreg.h" #include "lllocalcliprect.h" -#include "llnotifications.h" #include "llscriptfloater.h" #include "llsingleton.h" +#include "llsyswellwindow.h" static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel"); +static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification"); static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script"); static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer"); @@ -46,6 +48,195 @@ boost::signals2::signal<LLChiclet* (const LLUUID&), ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// +LLSysWellChiclet::Params::Params() + : button("button") + , unread_notifications("unread_notifications") + , max_displayed_count("max_displayed_count", 99) +{ + button.name = "button"; + button.tab_stop = FALSE; + button.label = LLStringUtil::null; +} + +LLSysWellChiclet::LLSysWellChiclet(const Params& p) + : LLChiclet(p) + , mButton(NULL) + , mCounter(0) + , mMaxDisplayedCount(p.max_displayed_count) + , mIsNewMessagesState(false) + , mFlashToLitTimer(NULL) + , mContextMenu(NULL) +{ + LLButton::Params button_params = p.button; + mButton = LLUICtrlFactory::create<LLButton>(button_params); + addChild(mButton); + + mFlashToLitTimer = new LLFlashTimer(boost::bind(&LLSysWellChiclet::changeLitState, this, _1)); +} + +LLSysWellChiclet::~LLSysWellChiclet() +{ + delete mFlashToLitTimer; +} + +void LLSysWellChiclet::setCounter(S32 counter) +{ + // do nothing if the same counter is coming. EXT-3678. + if (counter == mCounter) return; + + // note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter) + std::string s_count; + if(counter != 0) + { + static std::string more_messages_exist("+"); + std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : ""); + s_count = llformat("%d%s" + , llmin(counter, mMaxDisplayedCount) + , more_messages.c_str() + ); + } + + mButton->setLabel(s_count); + + mCounter = counter; +} + +boost::signals2::connection LLSysWellChiclet::setClickCallback( + const commit_callback_t& cb) +{ + return mButton->setClickedCallback(cb); +} + +void LLSysWellChiclet::setToggleState(BOOL toggled) { + mButton->setToggleState(toggled); +} + +void LLSysWellChiclet::changeLitState(bool blink) +{ + setNewMessagesState(!mIsNewMessagesState); +} + +void LLSysWellChiclet::setNewMessagesState(bool new_messages) +{ + /* + Emulate 4 states of button by background images, see detains in EXT-3147 + xml attribute Description + image_unselected "Unlit" - there are no new messages + image_selected "Unlit" + "Selected" - there are no new messages and the Well is open + image_pressed "Lit" - there are new messages + image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open + */ + mButton->setForcePressedState(new_messages); + + mIsNewMessagesState = new_messages; +} + +void LLSysWellChiclet::updateWidget(bool is_window_empty) +{ + mButton->setEnabled(!is_window_empty); + + if (LLChicletBar::instanceExists()) + { + LLChicletBar::getInstance()->showWellButton(getName(), !is_window_empty); + } +} +// virtual +BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + if(!mContextMenu) + { + createMenu(); + } + if (mContextMenu) + { + mContextMenu->show(x, y); + LLMenuGL::showPopup(this, mContextMenu, x, y); + } + return TRUE; +} + +/************************************************************************/ +/* LLNotificationChiclet implementation */ +/************************************************************************/ +LLNotificationChiclet::LLNotificationChiclet(const Params& p) +: LLSysWellChiclet(p), + mUreadSystemNotifications(0) +{ + mNotificationChannel.reset(new ChicletNotificationChannel(this)); + // ensure that notification well window exists, to synchronously + // handle toast add/delete events. + LLNotificationWellWindow::getInstance()->setSysWellChiclet(this); +} + +void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data) +{ + std::string action = user_data.asString(); + if("close all" == action) + { + LLNotificationWellWindow::getInstance()->closeAll(); + } +} + +bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data) +{ + std::string item = user_data.asString(); + if (item == "can close all") + { + return mUreadSystemNotifications != 0; + } + return true; +} + +void LLNotificationChiclet::createMenu() +{ + if(mContextMenu) + { + llwarns << "Menu already exists" << llendl; + return; + } + + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("NotificationWellChicletMenu.Action", + boost::bind(&LLNotificationChiclet::onMenuItemClicked, this, _2)); + + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + enable_registrar.add("NotificationWellChicletMenu.EnableItem", + boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2)); + + mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu> + ("menu_notification_well_button.xml", + LLMenuGL::sMenuContainer, + LLViewerMenuHolderGL::child_registry_t::instance()); +} + +/*virtual*/ +void LLNotificationChiclet::setCounter(S32 counter) +{ + LLSysWellChiclet::setCounter(counter); + updateWidget(getCounter() == 0); + +} + +bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification ) +{ + if (notification->getName() == "ScriptDialog") + { + return false; + } + + if( !(notification->canLogToIM() && notification->hasFormElements()) + && (!notification->getPayload().has("give_inventory_notification") + || notification->getPayload()["give_inventory_notification"])) + { + return true; + } + return false; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + LLChiclet::Params::Params() : show_counter("show_counter", true) , enable_counter("enable_counter", false) @@ -57,12 +248,6 @@ LLChiclet::LLChiclet(const Params& p) , mSessionId(LLUUID::null) , mShowCounter(p.show_counter) { - -} - -LLChiclet::~LLChiclet() -{ - } boost::signals2::connection LLChiclet::setLeftButtonClickCallback( @@ -125,6 +310,15 @@ BOOL LLIMChiclet::postBuild() return TRUE; } +void LLIMChiclet::enableCounterControl(bool enable) +{ + mCounterEnabled = enable; + if(!enable) + { + LLChiclet::setShowCounter(false); + } +} + void LLIMChiclet::setRequiredWidth() { S32 required_width = mDefaultWidth; @@ -791,13 +985,19 @@ bool LLChicletPanel::isAnyIMFloaterDoked() ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// +LLChicletNotificationCounterCtrl::Params::Params() + : max_displayed_count("max_displayed_count", 99) +{ +} +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// LLChicletAvatarIconCtrl::LLChicletAvatarIconCtrl(const Params& p) : LLAvatarIconCtrl(p) { } - ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index bd6c1a3e71..efaf03384a 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -29,10 +29,70 @@ #include "llavatariconctrl.h" #include "llbutton.h" +#include "llnotifications.h" +#include "lltextbox.h" class LLMenuGL; class LLFloaterIMSession; +/** + * Class for displaying amount of messages/notifications(unread). + */ +class LLChicletNotificationCounterCtrl : public LLTextBox +{ +public: + + struct Params : public LLInitParam::Block<Params, LLTextBox::Params> + { + /** + * Contains maximum displayed count of unread messages. Default value is 9. + * + * If count is less than "max_unread_count" will be displayed as is. + * Otherwise 9+ will be shown (for default value). + */ + Optional<S32> max_displayed_count; + + Params(); + }; + + /** + * Sets number of notifications + */ + virtual void setCounter(S32 counter); + + /** + * Returns number of notifications + */ + virtual S32 getCounter() const { return mCounter; } + + /** + * Returns width, required to display amount of notifications in text form. + * Width is the only valid value. + */ + /*virtual*/ LLRect getRequiredRect(); + + /** + * Sets number of notifications using LLSD + */ + /*virtual*/ void setValue(const LLSD& value); + + /** + * Returns number of notifications wrapped in LLSD + */ + /*virtual*/ LLSD getValue() const; + +protected: + + LLChicletNotificationCounterCtrl(const Params& p); + friend class LLUICtrlFactory; + +private: + + S32 mCounter; + S32 mInitialWidth; + S32 mMaxDisplayedCount; +}; + /** * Class for displaying avatar's icon in P2P chiclet. */ @@ -104,7 +164,7 @@ public: Params(); }; - /*virtual*/ ~LLChiclet(); + virtual ~LLChiclet() {} /** * Associates chat session id with chiclet. @@ -116,6 +176,11 @@ public: */ virtual const LLUUID& getSessionId() const { return mSessionId; } + /** + * Sets show counter state. + */ + virtual void setShowCounter(bool show) { mShowCounter = show; } + /** * Connects chiclet clicked event with callback. */ @@ -194,6 +259,22 @@ public: */ BOOL postBuild(); + /** + * Sets IM session name. This name will be displayed in chiclet tooltip. + */ + virtual void setIMSessionName(const std::string& name) { setToolTip(name); } + + /** + * Sets id of person/group user is chatting with. + * Session id should be set before calling this + */ + virtual void setOtherParticipantId(const LLUUID& other_participant_id) { mOtherParticipantId = other_participant_id; } + + /** + * Enables/disables the counter control for a chiclet. + */ + virtual void enableCounterControl(bool enable); + /** * Sets required width for a chiclet according to visible controls. */ @@ -366,6 +447,131 @@ private: LLChicletInvOfferIconCtrl* mChicletIconCtrl; }; +/** + * Implements notification chiclet. Used to display total amount of unread messages + * across all IM sessions, total amount of system notifications. See EXT-3147 for details + */ +class LLSysWellChiclet : public LLChiclet +{ +public: + + struct Params : public LLInitParam::Block<Params, LLChiclet::Params> + { + Optional<LLButton::Params> button; + + Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications; + + /** + * Contains maximum displayed count of unread messages. Default value is 9. + * + * If count is less than "max_unread_count" will be displayed as is. + * Otherwise 9+ will be shown (for default value). + */ + Optional<S32> max_displayed_count; + + Params(); + }; + + /*virtual*/ void setCounter(S32 counter); + + // *TODO: mantipov: seems getCounter is not necessary for LLNotificationChiclet + // but inherited interface requires it to implement. + // Probably it can be safe removed. + /*virtual*/S32 getCounter() { return mCounter; } + + boost::signals2::connection setClickCallback(const commit_callback_t& cb); + + /*virtual*/ ~LLSysWellChiclet(); + + void setToggleState(BOOL toggled); + + void setNewMessagesState(bool new_messages); + //this method should change a widget according to state of the SysWellWindow + virtual void updateWidget(bool is_window_empty); + +protected: + + LLSysWellChiclet(const Params& p); + friend class LLUICtrlFactory; + + /** + * Change Well 'Lit' state from 'Lit' to 'Unlit' and vice-versa. + * + * There is an assumption that it will be called 2*N times to do not change its start state. + * @see FlashToLitTimer + */ + void changeLitState(bool blink); + + /** + * Displays menu. + */ + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + + virtual void createMenu() = 0; + +protected: + class FlashToLitTimer; + LLButton* mButton; + S32 mCounter; + S32 mMaxDisplayedCount; + bool mIsNewMessagesState; + + LLFlashTimer* mFlashToLitTimer; + LLContextMenu* mContextMenu; +}; + +class LLNotificationChiclet : public LLSysWellChiclet +{ + LOG_CLASS(LLNotificationChiclet); + + friend class LLUICtrlFactory; +public: + struct Params : public LLInitParam::Block<Params, LLSysWellChiclet::Params>{}; + +protected: + struct ChicletNotificationChannel : public LLNotificationChannel + { + ChicletNotificationChannel(LLNotificationChiclet* chiclet) + : LLNotificationChannel(LLNotificationChannel::Params().filter(filterNotification).name(chiclet->getSessionId().asString())) + , mChiclet(chiclet) + { + // connect counter handlers to the signals + connectToChannel("Group Notifications"); + connectToChannel("Offer"); + connectToChannel("Notifications"); + } + + static bool filterNotification(LLNotificationPtr notify); + // connect counter updaters to the corresponding signals + /*virtual*/ void onAdd(LLNotificationPtr p) { mChiclet->setCounter(++mChiclet->mUreadSystemNotifications); } + /*virtual*/ void onDelete(LLNotificationPtr p) { mChiclet->setCounter(--mChiclet->mUreadSystemNotifications); } + + LLNotificationChiclet* const mChiclet; + }; + + boost::scoped_ptr<ChicletNotificationChannel> mNotificationChannel; + + LLNotificationChiclet(const Params& p); + + /** + * Processes clicks on chiclet menu. + */ + void onMenuItemClicked(const LLSD& user_data); + + /** + * Enables chiclet menu items. + */ + bool enableMenuItem(const LLSD& user_data); + + /** + * Creates menu. + */ + /*virtual*/ void createMenu(); + + /*virtual*/ void setCounter(S32 counter); + S32 mUreadSystemNotifications; +}; + /** * Storage class for all IM chiclets. Provides mechanism to display, * scroll, create, remove chiclets. diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index fde7764129..a51c844775 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -30,6 +30,7 @@ #include "llchiclet.h" #include "lllayoutstack.h" #include "llpaneltopinfobar.h" +#include "llsyswellwindow.h" namespace { @@ -58,6 +59,8 @@ BOOL LLChicletBar::postBuild() mToolbarStack = getChild<LLLayoutStack>("toolbar_stack"); mChicletPanel = getChild<LLChicletPanel>("chiclet_list"); + showWellButton("notification_well", !LLNotificationWellWindow::getInstance()->isWindowEmpty()); + LLPanelTopInfoBar::instance().setResizeCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this)); LLPanelTopInfoBar::instance().setVisibleCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this)); diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 8a43855a7d..e92bd766ca 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -40,6 +40,7 @@ LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLTransientDockableFloater(NULL, true, key), mChannel(NULL), mMessageList(NULL), + mSysWellChiclet(NULL), NOTIFICATION_WELL_ANCHOR_NAME("notification_well_panel"), IM_WELL_ANCHOR_NAME("im_well_panel"), mIsReshapedByUser(false) @@ -79,6 +80,15 @@ void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask) setVisible(TRUE); } +void LLSysWellWindow::setSysWellChiclet(LLSysWellChiclet* chiclet) +{ + mSysWellChiclet = chiclet; + if(NULL != mSysWellChiclet) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + } +} + //--------------------------------------------------------------------------------- LLSysWellWindow::~LLSysWellWindow() { @@ -89,6 +99,10 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id) { if(mMessageList->removeItemByValue(id)) { + if (NULL != mSysWellChiclet) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + } reshapeWindow(); } else @@ -334,6 +348,7 @@ void LLNotificationWellWindow::addItem(LLSysWellItem::Params p) LLSysWellItem* new_item = new LLSysWellItem(p); if (mMessageList->addItem(new_item, value, ADD_TOP)) { + mSysWellChiclet->updateWidget(isWindowEmpty()); reshapeWindow(); new_item->setOnItemCloseCallback(boost::bind(&LLNotificationWellWindow::onItemClose, this, _1)); new_item->setOnItemClickCallback(boost::bind(&LLNotificationWellWindow::onItemClick, this, _1)); diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 406ab1b59e..cc5c057d8b 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -66,6 +66,8 @@ public: void onStartUpToastClick(S32 x, S32 y, MASK mask); + void setSysWellChiclet(LLSysWellChiclet* chiclet); + // size constants for the window and for its elements static const S32 MAX_WINDOW_HEIGHT = 200; static const S32 MIN_WINDOW_WIDTH = 318; @@ -84,6 +86,11 @@ protected: LLNotificationsUI::LLScreenChannel* mChannel; LLFlatListView* mMessageList; + /** + * Reference to an appropriate Well chiclet to release "new message" state. EXT-3147 + */ + LLSysWellChiclet* mSysWellChiclet; + bool mIsReshapedByUser; }; diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index bf6e933dfd..a07d7e4855 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -365,6 +365,8 @@ with the same filename but different name <texture name="Nearby_chat_icon" file_name="icons/nearby_chat_icon.png" preload="false" /> + <texture name="Notices_Unread" file_name="bottomtray/Notices_Unread.png" preload="true" /> + <texture name="NoEntryLines" file_name="world/NoEntryLines.png" use_mips="true" preload="false" /> <texture name="NoEntryPassLines" file_name="world/NoEntryPassLines.png" use_mips="true" preload="false" /> diff --git a/indra/newview/skins/default/xui/da/menu_notification_well_button.xml b/indra/newview/skins/default/xui/da/menu_notification_well_button.xml new file mode 100644 index 0000000000..40b35b5fdd --- /dev/null +++ b/indra/newview/skins/default/xui/da/menu_notification_well_button.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Notification Well Button Context Menu"> + <menu_item_call label="Luk alle" name="Close All"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/de/menu_notification_well_button.xml b/indra/newview/skins/default/xui/de/menu_notification_well_button.xml new file mode 100644 index 0000000000..0f2784f160 --- /dev/null +++ b/indra/newview/skins/default/xui/de/menu_notification_well_button.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Notification Well Button Context Menu"> + <menu_item_call label="Alle schließen" name="Close All"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_notification_well_button.xml b/indra/newview/skins/default/xui/en/menu_notification_well_button.xml new file mode 100644 index 0000000000..263ac40f4e --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_notification_well_button.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<context_menu + layout="topleft" + name="Notification Well Button Context Menu"> + <menu_item_call + label="Close All" + layout="topleft" + name="Close All"> + <menu_item_call.on_click + function="NotificationWellChicletMenu.Action" + parameter="close all" /> + <menu_item_call.on_enable + function="NotificationWellChicletMenu.EnableItem" + parameter="can close all" /> + </menu_item_call> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml index 390047d493..fc321fdd23 100644 --- a/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_chiclet_bar.xml @@ -77,5 +77,49 @@ width="12" /> </chiclet_panel> </layout_panel> + <layout_panel auto_resize="false" + width="4" + min_width="4"/> + <layout_panel + auto_resize="false" + follows="right" + height="28" + layout="topleft" + min_height="28" + min_width="37" + name="notification_well_panel" + top="0" + width="37"> + <chiclet_notification + follows="right" + height="23" + layout="topleft" + left="0" + max_displayed_count="99" + name="notification_well" + top="5" + width="35"> + <button + auto_resize="false" + bottom_pad="3" + follows="right" + halign="center" + height="23" + image_overlay="Notices_Unread" + image_overlay_alignment="center" + image_pressed="WellButton_Lit" + image_pressed_selected="WellButton_Lit_Selected" + image_selected="PushButton_Press" + label_color="Black" + left="0" + name="Unread" + tool_tip="Notifications" + width="34"> + <init_callback + function="Button.SetDockableFloaterToggle" + parameter="notification_well_window" /> + </button> + </chiclet_notification> + </layout_panel> </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/es/menu_notification_well_button.xml b/indra/newview/skins/default/xui/es/menu_notification_well_button.xml new file mode 100644 index 0000000000..0562d35be7 --- /dev/null +++ b/indra/newview/skins/default/xui/es/menu_notification_well_button.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Notification Well Button Context Menu"> + <menu_item_call label="Cerrar todo" name="Close All"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/fr/menu_notification_well_button.xml b/indra/newview/skins/default/xui/fr/menu_notification_well_button.xml new file mode 100644 index 0000000000..323bfdbf16 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/menu_notification_well_button.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Notification Well Button Context Menu"> + <menu_item_call label="Tout fermer" name="Close All"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/it/menu_notification_well_button.xml b/indra/newview/skins/default/xui/it/menu_notification_well_button.xml new file mode 100644 index 0000000000..8c82e30f0e --- /dev/null +++ b/indra/newview/skins/default/xui/it/menu_notification_well_button.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Notification Well Button Context Menu"> + <menu_item_call label="Chiudi tutto" name="Close All"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/ja/menu_notification_well_button.xml b/indra/newview/skins/default/xui/ja/menu_notification_well_button.xml new file mode 100644 index 0000000000..913bae8958 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/menu_notification_well_button.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Notification Well Button Context Menu"> + <menu_item_call label="すべて閉じる" name="Close All"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/pl/menu_notification_well_button.xml b/indra/newview/skins/default/xui/pl/menu_notification_well_button.xml new file mode 100644 index 0000000000..bd3d42f9b1 --- /dev/null +++ b/indra/newview/skins/default/xui/pl/menu_notification_well_button.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Notification Well Button Context Menu"> + <menu_item_call label="Zamknij" name="Close All"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/pt/menu_notification_well_button.xml b/indra/newview/skins/default/xui/pt/menu_notification_well_button.xml new file mode 100644 index 0000000000..43ad4134ec --- /dev/null +++ b/indra/newview/skins/default/xui/pt/menu_notification_well_button.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Notification Well Button Context Menu"> + <menu_item_call label="Fechar tudo" name="Close All"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/ru/menu_notification_well_button.xml b/indra/newview/skins/default/xui/ru/menu_notification_well_button.xml new file mode 100644 index 0000000000..4d067e232a --- /dev/null +++ b/indra/newview/skins/default/xui/ru/menu_notification_well_button.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Notification Well Button Context Menu"> + <menu_item_call label="Закрыть все" name="Close All"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/tr/menu_notification_well_button.xml b/indra/newview/skins/default/xui/tr/menu_notification_well_button.xml new file mode 100644 index 0000000000..39c66268f5 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/menu_notification_well_button.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Notification Well Button Context Menu"> + <menu_item_call label="Tümünü Kapat" name="Close All"/> +</context_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_notification_well_button.xml b/indra/newview/skins/default/xui/zh/menu_notification_well_button.xml new file mode 100644 index 0000000000..b629f73584 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/menu_notification_well_button.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<context_menu name="Notification Well Button Context Menu"> + <menu_item_call label="全部關閉" name="Close All"/> +</context_menu> -- cgit v1.2.3 From 13a619cb5fc8da621d4e7becbf95ca2a8014deb3 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 18 Dec 2012 18:15:28 -0800 Subject: CHUI-385: Problem: When the new session was created with multiple participants the old conversation floater was being recycled. When the conversation floater was re-initialized it did not remove and update the chat messages. Resolution: When the conversation floater is recycled simply call reloadMessages(). --- indra/newview/llfloaterimsession.cpp | 5 +---- indra/newview/llfloaterimsession.h | 4 ---- indra/newview/llimview.cpp | 3 ++- 3 files changed, 3 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index f2afe9d7bb..ff07ddfcbf 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -73,8 +73,7 @@ LLFloaterIMSession::LLFloaterIMSession(const LLUUID& session_id) mTypingTimer(), mTypingTimeoutTimer(), mPositioned(false), - mSessionInitialized(false), - mStartConferenceInSameFloater(false) + mSessionInitialized(false) { mIsNearbyChat = false; @@ -462,8 +461,6 @@ void LLFloaterIMSession::addP2PSessionParticipants(const LLSD& notification, con return; } - mStartConferenceInSameFloater = true; - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); // first check whether this is a voice session diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index 43d84eb8c0..6a2f4b29eb 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -127,8 +127,6 @@ public: //used as a callback on receiving new IM message static void sRemoveTypingIndicator(const LLSD& data); static void onIMChicletCreated(const LLUUID& session_id); - - bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; } const LLUUID& getOtherParticipantUUID() {return mOtherParticipantUUID;} static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); @@ -188,8 +186,6 @@ private: bool mSessionInitialized; LLSD mQueuedMsgsForInit; - bool mStartConferenceInSameFloater; - uuid_vec_t mInvitedParticipants; // connection to voice channel state change signal diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index da3d2e89bf..868dba9687 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2699,12 +2699,13 @@ LLUUID LLIMMgr::addSession( { LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(floater_id); - if (im_floater && im_floater->getStartConferenceInSameFloater()) + if (im_floater) { // The IM floater should be initialized with a new session_id // so that it is found by that id when creating a chiclet in LLFloaterIMSession::onIMChicletCreated, // and a new floater is not created. im_floater->initIMSession(session_id); + im_floater->reloadMessages(); } } -- cgit v1.2.3 From c73947ac1fc6c48bca75ea7d6beeda63eb695b2b Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Tue, 18 Dec 2012 18:48:15 -0800 Subject: CHUI-499: Adding ability to serialize the communication notifications to local disk per user. --- indra/llui/llnotifications.cpp | 2 + indra/llui/llnotifications.h | 3 + indra/newview/CMakeLists.txt | 4 + indra/newview/llchannelmanager.cpp | 2 + indra/newview/llcommunicationchannel.cpp | 73 ++++++++++++++ indra/newview/llcommunicationchannel.h | 59 ++++++++++++ .../newview/lldonotdisturbnotificationstorage.cpp | 106 +++++++++++++++++++++ indra/newview/lldonotdisturbnotificationstorage.h | 57 +++++++++++ indra/newview/llimview.cpp | 6 +- indra/newview/llnotificationhandler.h | 1 - indra/newview/llviewerwindow.cpp | 3 +- 11 files changed, 311 insertions(+), 5 deletions(-) create mode 100644 indra/newview/llcommunicationchannel.cpp create mode 100644 indra/newview/llcommunicationchannel.h create mode 100644 indra/newview/lldonotdisturbnotificationstorage.cpp create mode 100644 indra/newview/lldonotdisturbnotificationstorage.h (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 937dcf0afc..c9b4399bef 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -992,10 +992,12 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt bool abortProcessing = false; if (passesFilter) { + onFilterPass(pNotification); abortProcessing = mPassedFilter(payload); } else { + onFilterFail(pNotification); abortProcessing = mFailedFilter(payload); } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 8bb79b57e3..42dee4c3e9 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -774,6 +774,9 @@ protected: virtual void onDelete(LLNotificationPtr p) {} virtual void onChange(LLNotificationPtr p) {} + virtual void onFilterPass(LLNotificationPtr p) {} + virtual void onFilterFail(LLNotificationPtr p) {} + bool updateItem(const LLSD& payload, LLNotificationPtr pNotification); LLNotificationFilter mFilter; }; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index da1d96414b..d43f9e9988 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -137,6 +137,7 @@ set(viewer_SOURCE_FILES llcommanddispatcherlistener.cpp llcommandhandler.cpp llcommandlineparser.cpp + llcommunicationchannel.cpp llcompilequeue.cpp llconfirmationmanager.cpp llconversationlog.cpp @@ -152,6 +153,7 @@ set(viewer_SOURCE_FILES lldebugview.cpp lldelayedgestureerror.cpp lldirpicker.cpp + lldonotdisturbnotificationstorage.cpp lldndbutton.cpp lldrawable.cpp lldrawpool.cpp @@ -723,6 +725,7 @@ set(viewer_HEADER_FILES llcommanddispatcherlistener.h llcommandhandler.h llcommandlineparser.h + llcommunicationchannel.h llcompilequeue.h llconfirmationmanager.h llconversationlog.h @@ -738,6 +741,7 @@ set(viewer_HEADER_FILES lldebugview.h lldelayedgestureerror.h lldirpicker.h + lldonotdisturbnotificationstorage.h lldndbutton.h lldrawable.h lldrawpool.h diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 79e2d376ea..dd2bcc742b 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -29,6 +29,7 @@ #include "llchannelmanager.h" #include "llappviewer.h" +#include "lldonotdisturbnotificationstorage.h" #include "llpersistentnotificationstorage.h" #include "llviewercontrol.h" #include "llviewerwindow.h" @@ -138,6 +139,7 @@ void LLChannelManager::onLoginCompleted() } LLPersistentNotificationStorage::getInstance()->loadNotifications(); + LLDoNotDisturbNotificationStorage::getInstance()->initialize(); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llcommunicationchannel.cpp b/indra/newview/llcommunicationchannel.cpp new file mode 100644 index 0000000000..353447e4b6 --- /dev/null +++ b/indra/newview/llcommunicationchannel.cpp @@ -0,0 +1,73 @@ +/** +* @file llcommunicationchannel.cpp +* @brief Implementation of llcommunicationchannel +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" // must be first include + +#include "llcommunicationchannel.h" + +#include <string> +#include <map> + +#include "llagent.h" +#include "lldate.h" +#include "llnotifications.h" + + +LLCommunicationChannel::LLCommunicationChannel(const std::string& pName, const std::string& pParentName) + : LLNotificationChannel(pName, pParentName, filterByDoNotDisturbStatus) +{ +} + +LLCommunicationChannel::~LLCommunicationChannel() +{ +} + +bool LLCommunicationChannel::filterByDoNotDisturbStatus(LLNotificationPtr) +{ + return !gAgent.isDoNotDisturb(); +} + +LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::beginHistory() const +{ + return mHistory.begin(); +} + +LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::endHistory() const +{ + return mHistory.end(); +} + +void LLCommunicationChannel::onFilterFail(LLNotificationPtr pNotificationPtr) +{ + std::string notificationType = pNotificationPtr->getType(); + if ((notificationType == "groupnotify") + || (notificationType == "offer") + || (notificationType == "notifytoast")) + { + mHistory.insert(std::make_pair<LLDate, LLNotificationPtr>(pNotificationPtr->getDate(), pNotificationPtr)); + } +} diff --git a/indra/newview/llcommunicationchannel.h b/indra/newview/llcommunicationchannel.h new file mode 100644 index 0000000000..a4756b8993 --- /dev/null +++ b/indra/newview/llcommunicationchannel.h @@ -0,0 +1,59 @@ +/** +* @file llcommunicationchannel.h +* @brief Header file for llcommunicationchannel +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#ifndef LL_LLCOMMUNICATIONCHANNEL_H +#define LL_LLCOMMUNICATIONCHANNEL_H + +#include <string> +#include <map> + +#include "lldate.h" +#include "llerror.h" +#include "llnotifications.h" + +class LLCommunicationChannel : public LLNotificationChannel +{ + LOG_CLASS(LLCommunicationChannel); +public: + LLCommunicationChannel(const std::string& pName, const std::string& pParentName); + virtual ~LLCommunicationChannel(); + + static bool filterByDoNotDisturbStatus(LLNotificationPtr); + + typedef std::multimap<LLDate, LLNotificationPtr> history_list_t; + history_list_t::const_iterator beginHistory() const; + history_list_t::const_iterator endHistory() const; + +protected: + virtual void onFilterFail(LLNotificationPtr pNotificationPtr); + +private: + + history_list_t mHistory; +}; + +#endif // LL_LLCOMMUNICATIONCHANNEL_H + diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp new file mode 100644 index 0000000000..472a0dd9ee --- /dev/null +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -0,0 +1,106 @@ +/** +* @file lldonotdisturbnotificationstorage.cpp +* @brief Implementation of lldonotdisturbnotificationstorage +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" + +#include "lldonotdisturbnotificationstorage.h" + +#include "llcommunicationchannel.h" +#include "lldir.h" +#include "llerror.h" +#include "llfasttimer_class.h" +#include "llnotifications.h" +#include "llnotificationstorage.h" +#include "llsd.h" +#include "llsingleton.h" + +LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() + : LLSingleton<LLDoNotDisturbNotificationStorage>() + , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")) +{ +} + +LLDoNotDisturbNotificationStorage::~LLDoNotDisturbNotificationStorage() +{ +} + +void LLDoNotDisturbNotificationStorage::initialize() +{ + getCommunicationChannel()->connectFailedFilter(boost::bind(&LLDoNotDisturbNotificationStorage::onChannelChanged, this, _1)); +} + +static LLFastTimer::DeclareTimer FTM_SAVE_DND_NOTIFICATIONS("Save DND Notifications"); + +void LLDoNotDisturbNotificationStorage::saveNotifications() +{ + LLFastTimer _(FTM_SAVE_DND_NOTIFICATIONS); + + LLNotificationChannelPtr channelPtr = getCommunicationChannel(); + const LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get()); + llassert(commChannel != NULL); + + LLSD output = LLSD::emptyMap(); + LLSD& data = output["data"]; + data = LLSD::emptyArray(); + + for (LLCommunicationChannel::history_list_t::const_iterator historyIter = commChannel->beginHistory(); + historyIter != commChannel->endHistory(); ++historyIter) + { + LLNotificationPtr notificationPtr = historyIter->second; + + if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && !notificationPtr->isExpired()) + { + data.append(notificationPtr->asLLSD()); + } + } + + writeNotifications(output); +} + +static LLFastTimer::DeclareTimer FTM_LOAD_DND_NOTIFICATIONS("Load DND Notifications"); + +void LLDoNotDisturbNotificationStorage::loadNotifications() +{ +} + +LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChannel() const +{ + LLNotificationChannelPtr channelPtr = LLNotifications::getInstance()->getChannel("Communication"); + llassert(channelPtr); + return channelPtr; +} + + +bool LLDoNotDisturbNotificationStorage::onChannelChanged(const LLSD& pPayload) +{ + if (pPayload["sigtype"].asString() != "load") + { + saveNotifications(); + } + + return false; +} diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h new file mode 100644 index 0000000000..60bcd89ec3 --- /dev/null +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -0,0 +1,57 @@ +/** +* @file lldonotdisturbnotificationstorage.h +* @brief Header file for lldonotdisturbnotificationstorage +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#ifndef LL_LLDONOTDISTURBNOTIFICATIONSTORAGE_H +#define LL_LLDONOTDISTURBNOTIFICATIONSTORAGE_H + +#include "llerror.h" +#include "llnotifications.h" +#include "llnotificationstorage.h" +#include "llsingleton.h" + +class LLSD; + +class LLDoNotDisturbNotificationStorage : public LLSingleton<LLDoNotDisturbNotificationStorage>, public LLNotificationStorage +{ + LOG_CLASS(LLDoNotDisturbNotificationStorage); +public: + LLDoNotDisturbNotificationStorage(); + ~LLDoNotDisturbNotificationStorage(); + + void initialize(); + + void saveNotifications(); + void loadNotifications(); + +protected: + +private: + LLNotificationChannelPtr getCommunicationChannel() const; + bool onChannelChanged(const LLSD& pPayload); +}; + +#endif // LL_LLDONOTDISTURBNOTIFICATIONSTORAGE_H + diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index c9672413bf..26be7f6bbf 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -149,7 +149,7 @@ void on_new_message(const LLSD& msg) } // do not show notification in "do not disturb" mode or it goes from agent - if (gAgent.isDoNotDisturb() || gAgent.getID() == participant_id) + if (gAgent.getID() == participant_id) { return; } @@ -2500,7 +2500,7 @@ void LLIMMgr::addMessage( } bool new_session = !hasSession(new_session_id); - if (new_session && !gAgent.isDoNotDisturb()) + if (new_session) { LLAvatarName av_name; if (LLAvatarNameCache::get(other_participant_id, &av_name) && !name_is_setted) @@ -2543,7 +2543,7 @@ void LLIMMgr::addMessage( } //Play sound for new conversations - if(gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE) + if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE)) { make_ui_sound("UISndNewIncomingIMSession"); } diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index a78f0c067b..bff4efa9ea 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -119,7 +119,6 @@ public: /** * Handler for chat message notifications. */ -// XXX stinson 12/06/2012 : can I just remove the LLChatHandler class? class LLChatHandler : public LLEventHandler { public: diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 424898536e..1c463015e2 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -37,6 +37,7 @@ #include "llagent.h" #include "llagentcamera.h" +#include "llcommunicationchannel.h" #include "llfloaterreg.h" #include "llmeshrepository.h" #include "llnotificationhandler.h" @@ -1557,7 +1558,7 @@ LLViewerWindow::LLViewerWindow(const Params& p) mViewerWindowListener.reset(new LLViewerWindowListener(this)); mSystemChannel.reset(new LLNotificationChannel("System", "Visible", LLNotificationFilters::includeEverything)); - mCommunicationChannel.reset(new LLNotificationChannel("Communication", "Visible", !boost::bind(&LLAgent::isDoNotDisturb, &gAgent))); + mCommunicationChannel.reset(new LLCommunicationChannel("Communication", "Visible")); mAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alerts", "alert")); mModalAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alertmodal", "alertmodal")); -- cgit v1.2.3 From a4975ace20faa3b6de952f26865dca53dcb9060c Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Tue, 18 Dec 2012 19:10:19 -0800 Subject: CHUI-569: Ensure that we create a friend request notification even in the case of do-not-disturb mode. The DND mode will log it to a file to be re-created when DND mode is exited. --- indra/newview/llviewermessage.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 5bb7db5c0d..04dd7c911b 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3169,17 +3169,16 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) payload["online"] = (offline == IM_ONLINE); payload["sender"] = msg->getSender().getIPandPort(); - if (is_do_not_disturb) - { - send_do_not_disturb_message(msg, from_id); - LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1); - } - else if (is_muted) + if (is_muted) { LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1); } else { + if (is_do_not_disturb) + { + send_do_not_disturb_message(msg, from_id); + } args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString(); if(message.empty()) { -- cgit v1.2.3 From da59ef8013801eac3695cea0ae8c1097275b6832 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Tue, 18 Dec 2012 19:22:21 -0800 Subject: Removing copy from the DoNotDisturbModeSet notification as we are no longer auto deleting inventory offers. --- indra/newview/skins/default/xui/en/notifications.xml | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 94307d2f93..35ce787847 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3696,7 +3696,6 @@ Do Not Disturb is on. You will not be notified of incoming communications. - Other residents will receive your Do Not Disturb response (set in Preferences > General). - Teleportation offers will be declined. - Voice calls will be rejected. -- Inventory offers will go to your Trash. <usetemplate ignoretext="I change my status to Do Not Disturb mode" name="okignore" -- cgit v1.2.3 From 8adca4583ec95ac063f79990ac092998f24415b8 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 18 Dec 2012 22:57:56 -0800 Subject: CHUI-600 : WIP : Flash conversation item in different color than select and start flashing only when shown --- indra/llui/llfolderviewitem.cpp | 46 +++++++++++++++++++++------------- indra/llui/llfolderviewitem.h | 5 +++- indra/newview/llconversationview.cpp | 20 ++++++++++++--- indra/newview/llconversationview.h | 5 +++- indra/newview/skins/default/colors.xml | 6 +++++ 5 files changed, 60 insertions(+), 22 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 0a06ce66aa..100904c5a2 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -50,6 +50,7 @@ std::map<U8, LLFontGL*> LLFolderViewItem::sFonts; // map of styles to fonts bool LLFolderViewItem::sColorSetInitialized = false; LLUIColor LLFolderViewItem::sFgColor; LLUIColor LLFolderViewItem::sHighlightBgColor; +LLUIColor LLFolderViewItem::sFlashBgColor; LLUIColor LLFolderViewItem::sFocusOutlineColor; LLUIColor LLFolderViewItem::sMouseOverColor; LLUIColor LLFolderViewItem::sFilterBGColor; @@ -151,6 +152,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) { sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE); sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); @@ -686,26 +688,31 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L return mIsCurSelection; } -void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor, +void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor) { - - //--------------------------------------------------------------------------------// - // Draw highlight for selected items - // - const S32 focus_top = getRect().getHeight(); const S32 focus_bottom = getRect().getHeight() - mItemHeight; const bool folder_open = (getRect().getHeight() > mItemHeight + 4); const S32 FOCUS_LEFT = 1; + + // Determine which background color to use for highlighting + LLUIColor bgColor = (isFlashing() ? flashColor : selectColor); - if (isHighlightAllowed()) // always render "current" item (only render other selected items if - // mShowSingleSelection is FALSE) or flashing item + //--------------------------------------------------------------------------------// + // Draw highlight for selected items + // Note: Always render "current" item or flashing item, only render other selected + // items if mShowSingleSelection is FALSE. + // + if (isHighlightAllowed()) + { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLColor4 bg_color = bgColor; - if (!isHighlightActive()) + + // Highlight for selected but not current items + if (!isHighlightActive() && !isFlashing()) { + LLColor4 bg_color = bgColor; // do time-based fade of extra objects F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); if (getRoot() && getRoot()->getShowSingleSelection()) @@ -718,25 +725,30 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo // fading in bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); } + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + bg_color, hasKeyboardFocus); } - if (isHighlightAllowed() || isHighlightActive()) + // Highlight for currently selected or flashing item + if (isHighlightActive()) { + // Background gl_rect_2d(FOCUS_LEFT, focus_top, getRect().getWidth() - 2, focus_bottom, - bg_color, hasKeyboardFocus); - } - - if (isHighlightActive()) - { + bgColor, hasKeyboardFocus); + // Outline gl_rect_2d(FOCUS_LEFT, focus_top, getRect().getWidth() - 2, focus_bottom, focusOutlineColor, FALSE); } + if (folder_open) { gl_rect_2d(FOCUS_LEFT, @@ -810,7 +822,7 @@ void LLFolderViewItem::draw() drawOpenFolderArrow(default_params, sFgColor); - drawHighlight(show_context, filled, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); + drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); //--------------------------------------------------------------------------------// // Draw open icon diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index d7f5e86aea..ca31931e19 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -128,6 +128,7 @@ protected: static LLUIColor sFgColor; static LLUIColor sFgDisabledColor; static LLUIColor sHighlightBgColor; + static LLUIColor sFlashBgColor; static LLUIColor sFocusOutlineColor; static LLUIColor sMouseOverColor; static LLUIColor sFilterBGColor; @@ -141,6 +142,8 @@ protected: virtual void addFolder(LLFolderViewFolder*) { } virtual bool isHighlightAllowed(); virtual bool isHighlightActive(); + virtual bool isFlashing() { return false; } + virtual void setFlashState(bool) { } static LLFontGL* getLabelFontForStyle(U8 style); @@ -269,7 +272,7 @@ public: // virtual void handleDropped(); virtual void draw(); void drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color); - void drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor); + void drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor); void drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index c0a209f22d..d3a0e882f5 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -101,7 +101,17 @@ LLConversationViewSession::~LLConversationViewSession() void LLConversationViewSession::setFlashState(bool flash_state) { mFlashStateOn = flash_state; - (flash_state ? mFlashTimer->startFlashing() : mFlashTimer->stopFlashing()); + mFlashStarted = false; + mFlashTimer->stopFlashing(); +} + +void LLConversationViewSession::startFlashing() +{ + if (mFlashStateOn && !mFlashStarted) + { + mFlashStarted = true; + mFlashTimer->startFlashing(); + } } bool LLConversationViewSession::isHighlightAllowed() @@ -198,8 +208,11 @@ void LLConversationViewSession::draw() drawOpenFolderArrow(default_params, sFgColor); } + // Indicate that flash can start (moot operation if already started, done or not flashing) + startFlashing(); + // draw highlight for selected items - drawHighlight(show_context, true, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); + drawHighlight(show_context, true, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); // Draw children if root folder, or any other folder that is open. Do not draw children when animating to closed state or you get rendering overlap. bool draw_children = getRoot() == static_cast<LLFolderViewFolder*>(this) || isOpen(); @@ -427,6 +440,7 @@ void LLConversationViewParticipant::draw() static LLUIColor sFgDisabledColor = LLUIColorTable::instance().getColor("MenuItemDisabledColor", DEFAULT_WHITE); static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + static LLUIColor sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE); static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); @@ -450,7 +464,7 @@ void LLConversationViewParticipant::draw() color = mIsSelected ? sHighlightFgColor : sFgColor; } - drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); + drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); drawLabel(font, text_left, y, color, right_x); refresh(); diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 1e20fb8b7e..74443e1d88 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -58,6 +58,7 @@ protected: /*virtual*/ bool isHighlightAllowed(); /*virtual*/ bool isHighlightActive(); + /*virtual*/ bool isFlashing() { return mFlashStateOn; } LLFloaterIMContainer* mContainer; @@ -83,11 +84,12 @@ public: virtual void refresh(); - void setFlashState(bool flash_state); + /*virtual*/ void setFlashState(bool flash_state); private: void onCurrentVoiceSessionChanged(const LLUUID& session_id); + void startFlashing(); LLPanel* mItemPanel; LLPanel* mCallIconLayoutPanel; @@ -95,6 +97,7 @@ private: LLOutputMonitorCtrl* mSpeakingIndicator; LLFlashTimer* mFlashTimer; bool mFlashStateOn; + bool mFlashStarted; bool mCollapsedMode; bool mHasArrow; diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 05230b8bd5..becdbda067 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -11,6 +11,9 @@ <color name="EmphasisColor_35" value="0.38 0.694 0.573 0.35" /> + <color + name="BeaconColor" + value="1 .67 .2 1" /> <color name="White" value="1 1 1 1" /> @@ -522,6 +525,9 @@ <color name="MenuItemHighlightBgColor" reference="EmphasisColor_35" /> + <color + name="MenuItemFlashBgColor" + reference="BeaconColor" /> <color name="MenuItemHighlightFgColor" reference="White" /> -- cgit v1.2.3 From 6b9ead91459d702727b54ab7e51614c2d5959f5f Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Tue, 18 Dec 2012 23:07:27 -0800 Subject: CHUI-499: Refactoring the LLPersistentNotificationStorage implementation for shared usage with the new LLDoNotDisturbNotificationStorage class. --- indra/newview/llnotificationstorage.cpp | 69 +++++++++++++++++++++++ indra/newview/llnotificationstorage.h | 3 + indra/newview/llpersistentnotificationstorage.cpp | 67 +--------------------- 3 files changed, 73 insertions(+), 66 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index d25a212059..4746e4bbd4 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -29,14 +29,39 @@ #include "llnotificationstorage.h" #include <string> +#include <map> #include "llerror.h" #include "llfile.h" +#include "llnotifications.h" #include "llpointer.h" #include "llsd.h" #include "llsdserialize.h" +#include "llsingleton.h" +#include "llviewermessage.h" +class LLResponderRegistry : public LLSingleton<LLResponderRegistry> +{ +public: + LLResponderRegistry(); + ~LLResponderRegistry(); + + LLNotificationResponderInterface* createResponder(const std::string& pNotificationName, const LLSD& pParams); + +protected: + +private: + template<typename RESPONDER_TYPE> static LLNotificationResponderInterface* create(const LLSD& pParams); + + typedef boost::function<LLNotificationResponderInterface* (const LLSD& params)> responder_constructor_t; + + void add(const std::string& pNotificationName, const responder_constructor_t& pConstructor); + + typedef std::map<std::string, responder_constructor_t> build_map_t; + build_map_t mBuildMap; +}; + LLNotificationStorage::LLNotificationStorage(std::string pFileName) : mFileName(pFileName) { @@ -90,3 +115,47 @@ bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const return didFileRead; } + +LLNotificationResponderInterface* LLNotificationStorage::createResponder(const std::string& pNotificationName, const LLSD& pParams) const +{ + return LLResponderRegistry::getInstance()->createResponder(pNotificationName, pParams); +} + +LLResponderRegistry::LLResponderRegistry() + : LLSingleton<LLResponderRegistry>() + , mBuildMap() +{ + add("ObjectGiveItem", &create<LLOfferInfo>); + add("UserGiveItem", &create<LLOfferInfo>); +} + +LLResponderRegistry::~LLResponderRegistry() +{ +} + +LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& pNotificationName, const LLSD& pParams) +{ + build_map_t::const_iterator it = mBuildMap.find(pNotificationName); + if(mBuildMap.end() == it) + { + return NULL; + } + responder_constructor_t ctr = it->second; + return ctr(pParams); +} + +template<typename RESPONDER_TYPE> LLNotificationResponderInterface* LLResponderRegistry::create(const LLSD& pParams) +{ + RESPONDER_TYPE* responder = new RESPONDER_TYPE(); + responder->fromLLSD(pParams); + return responder; +} + +void LLResponderRegistry::add(const std::string& pNotificationName, const responder_constructor_t& pConstructor) +{ + if (mBuildMap.find(pNotificationName) != mBuildMap.end()) + { + LL_ERRS("LLResponderRegistry") << "Responder is already registered : " << pNotificationName << LL_ENDL; + } + mBuildMap.insert(std::make_pair<std::string, responder_constructor_t>(pNotificationName, pConstructor)); +} diff --git a/indra/newview/llnotificationstorage.h b/indra/newview/llnotificationstorage.h index ab4da4e73f..7aabf7d09e 100644 --- a/indra/newview/llnotificationstorage.h +++ b/indra/newview/llnotificationstorage.h @@ -31,6 +31,7 @@ #include "llerror.h" +class LLNotificationResponderInterface; class LLSD; class LLNotificationStorage @@ -44,6 +45,8 @@ protected: bool writeNotifications(const LLSD& pNotificationData) const; bool readNotifications(LLSD& pNotificationData) const; + LLNotificationResponderInterface* createResponder(const std::string& pNotificationName, const LLSD& pParams) const; + private: std::string mFileName; }; diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index 7aaad64fd7..224aaa2146 100644 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -36,34 +36,6 @@ #include "llscriptfloater.h" #include "llviewermessage.h" -class LLResponderRegistry -{ -public: - - static void registerResponders(); - - static LLNotificationResponderInterface* createResponder(const std::string& notification_name, const LLSD& params); - -protected: - -private: - template<typename RESPONDER_TYPE> - static LLNotificationResponderInterface* create(const LLSD& params) - { - RESPONDER_TYPE* responder = new RESPONDER_TYPE(); - responder->fromLLSD(params); - return responder; - } - - typedef boost::function<LLNotificationResponderInterface* (const LLSD& params)> responder_constructor_t; - - static void add(const std::string& notification_name, const responder_constructor_t& ctr); - - typedef std::map<std::string, responder_constructor_t> build_map_t; - - static build_map_t sBuildMap; -}; - LLPersistentNotificationStorage::LLPersistentNotificationStorage() : LLSingleton<LLPersistentNotificationStorage>() , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml")) @@ -114,7 +86,6 @@ static LLFastTimer::DeclareTimer FTM_LOAD_NOTIFICATIONS("Load Notifications"); void LLPersistentNotificationStorage::loadNotifications() { LLFastTimer _(FTM_LOAD_NOTIFICATIONS); - LLResponderRegistry::registerResponders(); LLNotifications::instance().getChannel("Persistent")-> connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1)); @@ -144,8 +115,7 @@ void LLPersistentNotificationStorage::loadNotifications() LLSD notification_params = *notification_it; LLNotificationPtr notification(new LLNotification(notification_params)); - LLNotificationResponderPtr responder(LLResponderRegistry:: - createResponder(notification_params["name"], notification_params["responder"])); + LLNotificationResponderPtr responder(createResponder(notification_params["name"], notification_params["responder"])); notification->setResponseFunctor(responder); instance.add(notification); @@ -172,39 +142,4 @@ bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& pay return false; } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLResponderRegistry::build_map_t LLResponderRegistry::sBuildMap; - -void LLResponderRegistry::registerResponders() -{ - sBuildMap.clear(); - - add("ObjectGiveItem", &create<LLOfferInfo>); - add("UserGiveItem", &create<LLOfferInfo>); -} - -LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& notification_name, const LLSD& params) -{ - build_map_t::const_iterator it = sBuildMap.find(notification_name); - if(sBuildMap.end() == it) - { - return NULL; - } - responder_constructor_t ctr = it->second; - return ctr(params); -} - -void LLResponderRegistry::add(const std::string& notification_name, const responder_constructor_t& ctr) -{ - if(sBuildMap.find(notification_name) != sBuildMap.end()) - { - llwarns << "Responder is already registered : " << notification_name << llendl; - llassert(!"Responder already registered"); - } - sBuildMap[notification_name] = ctr; -} - // EOF -- cgit v1.2.3 From bd6d34d312c3e3322ab62f3a60253fb88fcbc9e3 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Wed, 19 Dec 2012 01:48:37 -0800 Subject: CHUI-499: Loading the DND notifications upon exit from DND mode and after login. --- indra/newview/llagent.cpp | 14 ++-- indra/newview/llchannelmanager.cpp | 2 + indra/newview/llcommunicationchannel.cpp | 6 ++ indra/newview/llcommunicationchannel.h | 2 + .../newview/lldonotdisturbnotificationstorage.cpp | 76 ++++++++++++++++++++++ 5 files changed, 96 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 49c570c30b..fc3be9ca21 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -41,6 +41,7 @@ #include "llchannelmanager.h" #include "llchicletbar.h" #include "llconsole.h" +#include "lldonotdisturbnotificationstorage.h" #include "llenvmanager.h" #include "llfirstuse.h" #include "llfloatercamera.h" @@ -1389,11 +1390,16 @@ BOOL LLAgent::getAFK() const //----------------------------------------------------------------------------- // setDoNotDisturb() //----------------------------------------------------------------------------- -void LLAgent::setDoNotDisturb(bool pIsDotNotDisturb) +void LLAgent::setDoNotDisturb(bool pIsDoNotDisturb) { - mIsDoNotDisturb = pIsDotNotDisturb; - sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, (pIsDotNotDisturb ? ANIM_REQUEST_START : ANIM_REQUEST_STOP)); - LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(pIsDotNotDisturb); + bool isDoNotDisturbSwitchedOff = (mIsDoNotDisturb && !pIsDoNotDisturb); + mIsDoNotDisturb = pIsDoNotDisturb; + sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, (pIsDoNotDisturb ? ANIM_REQUEST_START : ANIM_REQUEST_STOP)); + LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(pIsDoNotDisturb); + if (isDoNotDisturbSwitchedOff) + { + LLDoNotDisturbNotificationStorage::getInstance()->loadNotifications(); + } } //----------------------------------------------------------------------------- diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index dd2bcc742b..43757d0174 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -139,7 +139,9 @@ void LLChannelManager::onLoginCompleted() } LLPersistentNotificationStorage::getInstance()->loadNotifications(); + LLDoNotDisturbNotificationStorage::getInstance()->initialize(); + LLDoNotDisturbNotificationStorage::getInstance()->loadNotifications(); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llcommunicationchannel.cpp b/indra/newview/llcommunicationchannel.cpp index 353447e4b6..4b0a70ffd8 100644 --- a/indra/newview/llcommunicationchannel.cpp +++ b/indra/newview/llcommunicationchannel.cpp @@ -39,6 +39,7 @@ LLCommunicationChannel::LLCommunicationChannel(const std::string& pName, const std::string& pParentName) : LLNotificationChannel(pName, pParentName, filterByDoNotDisturbStatus) + , mHistory() { } @@ -61,6 +62,11 @@ LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::e return mHistory.end(); } +void LLCommunicationChannel::clearHistory() +{ + mHistory.clear(); +} + void LLCommunicationChannel::onFilterFail(LLNotificationPtr pNotificationPtr) { std::string notificationType = pNotificationPtr->getType(); diff --git a/indra/newview/llcommunicationchannel.h b/indra/newview/llcommunicationchannel.h index a4756b8993..0e15e1cd15 100644 --- a/indra/newview/llcommunicationchannel.h +++ b/indra/newview/llcommunicationchannel.h @@ -46,6 +46,8 @@ public: typedef std::multimap<LLDate, LLNotificationPtr> history_list_t; history_list_t::const_iterator beginHistory() const; history_list_t::const_iterator endHistory() const; + + void clearHistory(); protected: virtual void onFilterFail(LLNotificationPtr pNotificationPtr); diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 472a0dd9ee..43fd7705aa 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -29,14 +29,25 @@ #include "lldonotdisturbnotificationstorage.h" +#define XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT 0 + +#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT +#include "llchannelmanager.h" +#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT #include "llcommunicationchannel.h" #include "lldir.h" #include "llerror.h" #include "llfasttimer_class.h" #include "llnotifications.h" +#include "llnotificationhandler.h" #include "llnotificationstorage.h" +#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT +#include "llscreenchannel.h" +#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT +#include "llscriptfloater.h" #include "llsd.h" #include "llsingleton.h" +#include "lluuid.h" LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() : LLSingleton<LLDoNotDisturbNotificationStorage>() @@ -85,6 +96,71 @@ static LLFastTimer::DeclareTimer FTM_LOAD_DND_NOTIFICATIONS("Load DND Notificati void LLDoNotDisturbNotificationStorage::loadNotifications() { + LLFastTimer _(FTM_LOAD_DND_NOTIFICATIONS); + + LL_INFOS("stinsonDebug") << "STINSON DEBUG: loading notifiations" << LL_ENDL; + + LLSD input; + if (!readNotifications(input) ||input.isUndefined()) + { + return; + } + + LLSD& data = input["data"]; + if (data.isUndefined()) + { + return; + } + +#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT + LLNotificationsUI::LLScreenChannel* notification_channel = + dynamic_cast<LLNotificationsUI::LLScreenChannel*>(LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); +#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT + + LLNotifications& instance = LLNotifications::instance(); + + for (LLSD::array_const_iterator notification_it = data.beginArray(); + notification_it != data.endArray(); + ++notification_it) + { + LLSD notification_params = *notification_it; + LLNotificationPtr notification(new LLNotification(notification_params)); + + LL_INFOS("stinsonDebug") << "STINSON DEBUG: loading notification of type '" << notification->getType() << "'" << LL_ENDL; + + const LLUUID& notificationID = notification->id(); + if (instance.find(notificationID)) + { + instance.update(notification); + } + else + { + LLNotificationResponderPtr responder(createResponder(notification_params["name"], notification_params["responder"])); + notification->setResponseFunctor(responder); + + instance.add(notification); + } + +#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT + // hide script floaters so they don't confuse the user and don't overlap startup toast + LLScriptFloaterManager::getInstance()->setFloaterVisible(notification->getID(), false); + + if(notification_channel) + { + // hide saved toasts so they don't confuse the user + notification_channel->hideToast(notification->getID()); + } +#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT + } + + // Clear the communication channel history and rewrite the save file to empty it as well + LLNotificationChannelPtr channelPtr = getCommunicationChannel(); + LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get()); + llassert(commChannel != NULL); + commChannel->clearHistory(); + + saveNotifications(); } LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChannel() const -- cgit v1.2.3 From ca4c5d3bcb18afefc181bdc164d1c338abef7488 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Wed, 19 Dec 2012 11:28:38 -0800 Subject: Switching some notification types from "offer" to be "notify" as the notifications were not offers. --- indra/newview/skins/default/xui/en/notifications.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 35ce787847..05798da8e2 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6583,7 +6583,7 @@ However, this region contains content accessible to adults only. log_to_im="true" log_to_chat="false" show_toast="false" - type="offer"> + type="notify"> Teleport offer sent to [TO_NAME] </notification> @@ -6636,7 +6636,7 @@ However, this region contains content accessible to adults only. name="FriendshipOffered" log_to_im="true" show_toast="false" - type="offer"> + type="notify"> <tag>friendship</tag> You have offered friendship to [TO_NAME] </notification> @@ -6666,7 +6666,7 @@ However, this region contains content accessible to adults only. icon="notify.tga" name="FriendshipAccepted" log_to_im="true" - type="offer"> + type="notify"> <tag>friendship</tag> <nolink>[NAME]</nolink> accepted your friendship offer. </notification> @@ -6686,7 +6686,7 @@ However, this region contains content accessible to adults only. name="FriendshipAcceptedByMe" log_to_im="true" show_toast="false" - type="offer"> + type="notify"> <tag>friendship</tag> Friendship offer accepted. </notification> @@ -6696,7 +6696,7 @@ Friendship offer accepted. name="FriendshipDeclinedByMe" log_to_im="true" show_toast="false" - type="offer"> + type="notify"> <tag>friendship</tag> Friendship offer declined. </notification> -- cgit v1.2.3 From dcfcc191dd3caaa84d0f789a928a83adf55c13b1 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 19 Dec 2012 12:45:59 -0800 Subject: Pull merge from richard/viewer-chui --- indra/newview/llconversationview.cpp | 1 + indra/newview/llimview.cpp | 14 +++++++------- indra/newview/skins/default/colors.xml | 3 --- 3 files changed, 8 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index d3a0e882f5..fdba5b7289 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -109,6 +109,7 @@ void LLConversationViewSession::startFlashing() { if (mFlashStateOn && !mFlashStarted) { + llinfos << "Merov debug : Start the flashing for " << getName() << llendl; mFlashStarted = true; mFlashTimer->startFlashing(); } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 5b4d5466a1..39f54dfd4d 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -155,6 +155,8 @@ void on_new_message(const LLSD& msg) } // execution of the action + llinfos << "Merov debug : on_new_message action = " << action << llendl; + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); @@ -174,13 +176,11 @@ void on_new_message(const LLSD& msg) if ("toast" == action) { // Skip toasting if we have open window of IM with this session id - if ( - session_floater + if (session_floater && session_floater->isInVisibleChain() && session_floater->hasFocus() && !session_floater->isMinimized() - && !(session_floater->getHost() - && session_floater->getHost()->isMinimized()) + && !(session_floater->getHost() && session_floater->getHost()->isMinimized()) ) { return; @@ -222,10 +222,10 @@ void on_new_message(const LLSD& msg) gToolBarView->flashCommand(LLCommandId("chat"), true); } //conversation floater is open but a different conversation is focused - else - { + //else + //{ im_box->flashConversationItemWidget(session_id, true); - } + //} } } diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index c3df04d0a6..becdbda067 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -11,9 +11,6 @@ <color name="EmphasisColor_35" value="0.38 0.694 0.573 0.35" /> - <color - name="BeaconColor" - value="1 .67 .2 1" /> <color name="BeaconColor" value="1 .67 .2 1" /> -- cgit v1.2.3 From ef6121cba1c72549cca10763645254ae3aaf2887 Mon Sep 17 00:00:00 2001 From: William Todd Stinson <stinson@lindenlab.com> Date: Wed, 19 Dec 2012 15:37:12 -0800 Subject: CHUI-499: Code clean-up and adding some more types badly defined. --- indra/newview/lldonotdisturbnotificationstorage.cpp | 17 +++++++++++------ indra/newview/llnotificationstorage.cpp | 6 ++++++ 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 43fd7705aa..bf3dcae1f3 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -98,8 +98,6 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() { LLFastTimer _(FTM_LOAD_DND_NOTIFICATIONS); - LL_INFOS("stinsonDebug") << "STINSON DEBUG: loading notifiations" << LL_ENDL; - LLSD input; if (!readNotifications(input) ||input.isUndefined()) { @@ -127,8 +125,6 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() LLSD notification_params = *notification_it; LLNotificationPtr notification(new LLNotification(notification_params)); - LL_INFOS("stinsonDebug") << "STINSON DEBUG: loading notification of type '" << notification->getType() << "'" << LL_ENDL; - const LLUUID& notificationID = notification->id(); if (instance.find(notificationID)) { @@ -136,8 +132,17 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() } else { - LLNotificationResponderPtr responder(createResponder(notification_params["name"], notification_params["responder"])); - notification->setResponseFunctor(responder); + LLNotificationResponderInterface* responder = createResponder(notification_params["name"], notification_params["responder"]); + if (responder == NULL) + { + LL_WARNS("LLDoNotDisturbNotificationStorage") << "cannot create responder for notification of type '" + << notification->getType() << "'" << LL_ENDL; + } + else + { + LLNotificationResponderPtr responderPtr(responder); + notification->setResponseFunctor(responderPtr); + } instance.add(notification); } diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index 4746e4bbd4..b797775369 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -126,7 +126,13 @@ LLResponderRegistry::LLResponderRegistry() , mBuildMap() { add("ObjectGiveItem", &create<LLOfferInfo>); + add("OwnObjectGiveItem", &create<LLOfferInfo>); add("UserGiveItem", &create<LLOfferInfo>); + + add("TeleportOffered", &create<LLOfferInfo>); + add("TeleportOffered_MaturityExceeded", &create<LLOfferInfo>); + + add("OfferFriendship", &create<LLOfferInfo>); } LLResponderRegistry::~LLResponderRegistry() -- cgit v1.2.3 From c81cf89086b0282121c6577b6fde75e050c1a0e8 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 19 Dec 2012 17:10:31 -0800 Subject: CHUI-600 : Fix the orange (provided by Leo), fix the conversation item flashing (when shown) --- indra/newview/llconversationview.cpp | 6 ++++-- indra/newview/llfloaterimcontainer.cpp | 25 ++++++++++++++----------- indra/newview/llfloaterimcontainer.h | 1 + indra/newview/llimview.cpp | 3 --- indra/newview/skins/default/colors.xml | 2 +- 5 files changed, 20 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index fdba5b7289..e51efd48f5 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -81,7 +81,9 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes mSpeakingIndicator(NULL), mVoiceClientObserver(NULL), mCollapsedMode(false), - mHasArrow(true) + mHasArrow(true), + mFlashStateOn(false), + mFlashStarted(false) { mFlashTimer = new LLFlashTimer(); } @@ -109,7 +111,6 @@ void LLConversationViewSession::startFlashing() { if (mFlashStateOn && !mFlashStarted) { - llinfos << "Merov debug : Start the flashing for " << getName() << llendl; mFlashStarted = true; mFlashTimer->startFlashing(); } @@ -245,6 +246,7 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) if(result && getRoot()->getCurSelectedItem() == this) { LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + im_container->clearAllFlashStates(); im_container->selectConversationPair(session_id, false); im_container->collapseMessagesPane(false); } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 390eec84f6..58ba186b57 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1229,6 +1229,20 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id) selectConversationPair(session_id, true); } +void LLFloaterIMContainer::clearAllFlashStates() +{ + llinfos << "Merov debug : clear all flash states" << llendl; + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + for (;widget_it != mConversationsWidgets.end(); ++widget_it) + { + LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); + if (widget) + { + widget->setFlashState(false); + } + } +} + void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) { selectConversationPair(session_id, true); @@ -1240,17 +1254,6 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool BOOL handled = TRUE; LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); - // On selection, stop the flash state on all conversation widgets - conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); - for (;widget_it != mConversationsWidgets.end(); ++widget_it) - { - LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); - if (widget) - { - widget->setFlashState(false); - } - } - /* widget processing */ if (select_widget) { diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 5db1565cea..09a24c0105 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -69,6 +69,7 @@ public: void showConversation(const LLUUID& session_id); void selectConversation(const LLUUID& session_id); BOOL selectConversationPair(const LLUUID& session_id, bool select_widget); + void clearAllFlashStates(); /*virtual*/ void tabClose(); void showStub(bool visible); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 39f54dfd4d..65048e352e 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -155,9 +155,6 @@ void on_new_message(const LLSD& msg) } // execution of the action - llinfos << "Merov debug : on_new_message action = " << action << llendl; - - LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index becdbda067..0de217fc0d 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -13,7 +13,7 @@ value="0.38 0.694 0.573 0.35" /> <color name="BeaconColor" - value="1 .67 .2 1" /> + value="0.749 0.298 0 1" /> <color name="White" value="1 1 1 1" /> -- cgit v1.2.3 From b15ba74485e24db9a996a2f6a9438ac48224ea7a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 19 Dec 2012 17:19:48 -0800 Subject: CHUI-607: Due to a problem in design we have two checkboxes that determine whether a conversation transcript should be saved. By defaut commiting a change that makes both checkboxes checked by default. This makes it so that a new user can see their transcript/chat history. --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 24fa0a0cd4..ebc915ec5a 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4676,7 +4676,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>LandBrushSize</key> <map> -- cgit v1.2.3 From ba297b167f75d8a09c959952a300d492f2aec88b Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 19 Dec 2012 20:07:08 -0800 Subject: CHUI-600 : Fixed! Modified the button flash state so it sticks after the animation and is dismissed on toggle --- indra/llui/llbutton.cpp | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 99384439d2..7ca9b869a8 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -311,7 +311,7 @@ void LLButton::onCommit() { make_ui_sound("UISndClickRelease"); } - + if (mIsToggle) { toggleState(); @@ -613,10 +613,6 @@ void LLButton::draw() static LLCachedControl<bool> sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true); F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); - if (mFlashingTimer) - { - mFlashing = mFlashingTimer->isFlashingInProgress(); - } bool flash = mFlashing && sEnableButtonFlashing; bool pressed_by_keyboard = FALSE; @@ -701,7 +697,8 @@ void LLButton::draw() imagep = mImageDisabled; } - if (mFlashing) + // Selected has a higher priority than flashing. If both are set, flashing is ignored. + if (mFlashing && !selected) { // if button should flash and we have icon for flashing, use it as image for button if(flash && mImageFlash) @@ -711,13 +708,13 @@ void LLButton::draw() imagep = mImageFlash; } // else use usual flashing via flash_color - else + else if (mFlashingTimer) { LLColor4 flash_color = mFlashBgColor.get(); use_glow_effect = TRUE; glow_type = LLRender::BT_ALPHA; // blend the glow - if (mFlashingTimer->isCurrentlyHighlighted()) + if (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress()) { glow_color = flash_color; } @@ -773,8 +770,7 @@ void LLButton::draw() if (use_glow_effect) { mCurGlowStrength = lerp(mCurGlowStrength, - mFlashing ? (mFlashingTimer->isCurrentlyHighlighted() || mNeedsHighlight? 1.0 : 0.0) - : mHoverGlowStrength, + mFlashing ? (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress() || mNeedsHighlight? 1.0 : 0.0) : mHoverGlowStrength, LLCriticalDamp::getInterpolant(0.05f)); } else @@ -961,23 +957,18 @@ void LLButton::setToggleState(BOOL b) { setControlValue(b); // will fire LLControlVariable callbacks (if any) setValue(b); // may or may not be redundant + setFlashing(false); // stop flash state whenever the selected/unselected state if reset // Unselected label assignments autoResize(); } } -void LLButton::setFlashing( bool b ) +void LLButton::setFlashing(bool b) { if (mFlashingTimer) { - if (b) - { - mFlashingTimer->startFlashing(); - } - else - { - mFlashingTimer->stopFlashing(); - } + mFlashing = b; + (b ? mFlashingTimer->startFlashing() : mFlashingTimer->stopFlashing()); } else if (b != mFlashing) { -- cgit v1.2.3 From ed716d996987722c32a105fac79daf1af4e5fb23 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine <mberezhnoy@productengine.com> Date: Thu, 20 Dec 2012 09:42:34 +0200 Subject: CHUI-588 (Clicking nearby chat toast doesn't highlight proper conversation line item) --- indra/newview/llfloaterimsessiontab.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 7984034ded..53d2f31b79 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -308,7 +308,7 @@ void LLFloaterIMSessionTab::onFocusReceived() LLFloaterIMContainer* container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); if (container) { - container->selectConversationPair(mSessionID, ! getHost()); + container->selectConversationPair(mSessionID, true); container->showStub(! getHost()); } } -- cgit v1.2.3 From eb68845767309900b6b5915f6358ae5027fb7136 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 20 Dec 2012 15:01:50 +0200 Subject: CHUI-606 Default settings in CHUI viewer do not keep IM logs for users: Preferences > Chat > Keep a convers. log was turned on --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 24fa0a0cd4..ebc915ec5a 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4676,7 +4676,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>LandBrushSize</key> <map> -- cgit v1.2.3 From c81a0b0a5701425aa52521d8600a280d05040517 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Thu, 20 Dec 2012 15:23:36 +0200 Subject: CHUI-602 FIXED Don't call getUUID() if there is no selected participants --- indra/newview/llfloaterimcontainer.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 58ba186b57..92ea6dacde 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1101,7 +1101,14 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) uuid_vec_t uuids; getParticipantUUIDs(uuids); - if("can_activate_group" == item) + + // If nothing is selected, everything needs to be disabled + if (uuids.size() <= 0) + { + return false; + } + + if("can_activate_group" == item) { LLUUID selected_group_id = getCurSelectedViewModelItem()->getUUID(); return gAgent.getGroupID() != selected_group_id; @@ -1116,12 +1123,6 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v { return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); } - - // If nothing is selected, everything needs to be disabled - if (uuids.size() <= 0) - { - return false; - } // Extract the single select info bool is_single_select = (uuids.size() == 1); -- cgit v1.2.3 From 2aefdb47ca1d02bfe8b74928dee479072ef151a3 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 20 Dec 2012 15:24:14 +0200 Subject: CHUI-618 User sees no indication of offline messages received with conversation log preference turned off: flashing of CHUI button if offline messages was received --- indra/newview/llimview.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 65048e352e..cdc51ad2fc 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2488,16 +2488,23 @@ void LLIMMgr::addMessage( } // Open conversation log if offline messages are present and user allows a Call Log - if (is_offline_msg && gSavedSettings.getBOOL("KeepConversationLogTranscripts")) - { - LLFloaterConversationLog* floater_log = - LLFloaterReg::getTypedInstance<LLFloaterConversationLog>("conversation"); - if (floater_log && !(floater_log->isFrontmost())) + if (is_offline_msg) + { + if (gSavedSettings.getBOOL("KeepConversationLogTranscripts")) { - floater_log->openFloater(); - floater_log->setFrontmost(TRUE); + LLFloaterConversationLog* floater_log = + LLFloaterReg::getTypedInstance<LLFloaterConversationLog>("conversation"); + if (floater_log && !(floater_log->isFrontmost())) + { + floater_log->openFloater(); + floater_log->setFrontmost(TRUE); + } } - } + else + { + gToolBarView->flashCommand(LLCommandId("chat"), true); + } + } //*NOTE session_name is empty in case of incoming P2P sessions std::string fixed_session_name = from; -- cgit v1.2.3 From 95380b0aaa635c18c03801048559ba811640bc02 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Thu, 20 Dec 2012 22:37:04 +0200 Subject: CHUI-513 FIXED Revise initial conversation floater size --- indra/newview/app_settings/settings_per_account.xml | 2 +- indra/newview/skins/default/xui/en/floater_im_container.xml | 7 ++----- indra/newview/skins/default/xui/en/floater_im_session.xml | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index ca22041671..4ff494fbfb 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -53,7 +53,7 @@ <key>Type</key> <string>S32</string> <key>Value</key> - <integer>268</integer> + <integer>205</integer> </map> <key>ConversationsMessagePaneCollapsed</key> <map> diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 3475c7da33..cbf1830093 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -3,9 +3,8 @@ can_close="true" can_minimize="true" can_resize="true" - height="230" + height="210" layout="topleft" - min_height="50" name="floater_im_box" help_topic="floater_im_box" save_rect="true" @@ -15,7 +14,7 @@ title="CONVERSATIONS" bottom="-50" right="-5" - width="500"> + width="450"> <string name="collapse_icon" value="Conv_toolbar_collapse"/> @@ -37,7 +36,6 @@ user_resize="true" name="conversations_layout_panel" min_dim="38" - width="225" expanded_min_dim="156"> <layout_stack animate="false" @@ -121,7 +119,6 @@ opaque="true" top_pad="0" left="5" - height="390" right="-1"/> </layout_panel> <layout_panel diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 4dbd52d05e..9e2132dc3b 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -206,7 +206,7 @@ auto_resize="true" visible="true" name="left_part_holder" - min_width="225"> + min_width="221"> <panel name="trnsAndChat_panel" follows="all" -- cgit v1.2.3 From 090636f107a2d3ba3438a6690f36eac3ec257314 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 20 Dec 2012 18:36:01 -0800 Subject: CHUI-429 : Fixed! Add a flag to filter multi/single selection situations in menu building. Implement in conversation contextual menu. --- indra/llui/llfolderview.cpp | 5 +- indra/llui/llfolderview.h | 1 + indra/newview/llconversationmodel.cpp | 67 ++++++++++++---------- indra/newview/llconversationmodel.h | 2 +- indra/newview/llfloaterimcontainer.cpp | 1 - .../skins/default/xui/en/menu_conversation.xml | 7 +++ 6 files changed, 50 insertions(+), 33 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index a33ffc4240..7ae79d94fe 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1913,14 +1913,15 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) // Successively filter out invalid options - U32 flags = FIRST_SELECTED_ITEM; + U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0); + U32 flags = multi_select_flag | FIRST_SELECTED_ITEM; for (selected_items_t::iterator item_itor = mSelectedItems.begin(); item_itor != mSelectedItems.end(); ++item_itor) { LLFolderViewItem* selected_item = (*item_itor); selected_item->buildContextMenu(*menu, flags); - flags = 0x0; + flags = multi_select_flag; } addNoOptions(menu); diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index d4a1434c73..2ee7417240 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -400,5 +400,6 @@ public: // Flags for buildContextMenu() const U32 SUPPRESS_OPEN_ITEM = 0x1; const U32 FIRST_SELECTED_ITEM = 0x2; +const U32 ITEM_IN_MULTI_SELECTION = 0x4; #endif // LL_LLFOLDERVIEW_H diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index d03ad92fbc..005439301a 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -102,35 +102,44 @@ void LLConversationItem::showProperties(void) { } -void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items) -{ - items.push_back(std::string("view_profile")); - items.push_back(std::string("im")); - items.push_back(std::string("offer_teleport")); - items.push_back(std::string("voice_call")); - items.push_back(std::string("chat_history")); - items.push_back(std::string("separator_chat_history")); - items.push_back(std::string("add_friend")); - items.push_back(std::string("remove_friend")); - items.push_back(std::string("invite_to_group")); - items.push_back(std::string("separator_invite_to_group")); - items.push_back(std::string("map")); - items.push_back(std::string("share")); - items.push_back(std::string("pay")); - items.push_back(std::string("block_unblock")); - items.push_back(std::string("MuteText")); - - if(this->getType() != CONV_SESSION_1_ON_1 && mDisplayModeratorOptions) +void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32 flags) +{ + if (flags & ITEM_IN_MULTI_SELECTION) { - items.push_back(std::string("Moderator Options Separator")); - items.push_back(std::string("Moderator Options")); - items.push_back(std::string("AllowTextChat")); - items.push_back(std::string("moderate_voice_separator")); - items.push_back(std::string("ModerateVoiceToggleMuteSelected")); - items.push_back(std::string("ModerateVoiceMute")); - items.push_back(std::string("ModerateVoiceUnmute")); + items.push_back(std::string("im")); + items.push_back(std::string("offer_teleport")); + items.push_back(std::string("voice_call")); + items.push_back(std::string("remove_friends")); + } + else + { + items.push_back(std::string("view_profile")); + items.push_back(std::string("im")); + items.push_back(std::string("offer_teleport")); + items.push_back(std::string("voice_call")); + items.push_back(std::string("chat_history")); + items.push_back(std::string("separator_chat_history")); + items.push_back(std::string("add_friend")); + items.push_back(std::string("remove_friend")); + items.push_back(std::string("invite_to_group")); + items.push_back(std::string("separator_invite_to_group")); + items.push_back(std::string("map")); + items.push_back(std::string("share")); + items.push_back(std::string("pay")); + items.push_back(std::string("block_unblock")); + items.push_back(std::string("MuteText")); + + if ((getType() != CONV_SESSION_1_ON_1) && mDisplayModeratorOptions) + { + items.push_back(std::string("Moderator Options Separator")); + items.push_back(std::string("Moderator Options")); + items.push_back(std::string("AllowTextChat")); + items.push_back(std::string("moderate_voice_separator")); + items.push_back(std::string("ModerateVoiceToggleMuteSelected")); + items.push_back(std::string("ModerateVoiceMute")); + items.push_back(std::string("ModerateVoiceUnmute")); + } } - } // @@ -306,7 +315,7 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags) { items.push_back(std::string("close_conversation")); items.push_back(std::string("separator_disconnect_from_voice")); - buildParticipantMenuOptions(items); + buildParticipantMenuOptions(items, flags); } else if(this->getType() == CONV_SESSION_GROUP) { @@ -440,7 +449,7 @@ void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t items; menuentry_vec_t disabled_items; - buildParticipantMenuOptions(items); + buildParticipantMenuOptions(items, flags); hide_context_entries(menu, items, disabled_items); } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 743a6ba40b..02002d8f70 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -130,7 +130,7 @@ public: void postEvent(const std::string& event_type, LLConversationItemSession* session, LLConversationItemParticipant* participant); - void buildParticipantMenuOptions(menuentry_vec_t& items); + void buildParticipantMenuOptions(menuentry_vec_t& items, U32 flags); protected: std::string mName; // Name of the session or the participant diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 92ea6dacde..2019a35faa 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1232,7 +1232,6 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id) void LLFloaterIMContainer::clearAllFlashStates() { - llinfos << "Merov debug : clear all flash states" << llendl; conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); for (;widget_it != mConversationsWidgets.end(); ++widget_it) { diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index e0edf384d6..46c6e19fa5 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -75,6 +75,13 @@ <on_click function="Avatar.DoToSelected" parameter="remove_friend" /> <on_enable function="Avatar.EnableItem" parameter="can_delete" /> </menu_item_call> + <menu_item_call + label="Remove friends" + layout="topleft" + name="remove_friends"> + <on_click function="Avatar.DoToSelected" parameter="remove_friend" /> + <on_enable function="Avatar.EnableItem" parameter="can_delete" /> + </menu_item_call> <menu_item_call label="Invite to group..." layout="topleft" -- cgit v1.2.3 From d1898ef3b8cf1344bd1f3980b500d4d2f5c10593 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 20 Dec 2012 19:57:51 +0200 Subject: CHUI-605 : Fixed : Keep conversation log requires restart to change preference: connected LLConversationLog::enableLogging() as listener to "LogInstantMessages" control changes --- indra/newview/llconversationlog.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 1171b3db41..eb3a3731ee 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -187,16 +187,23 @@ void LLConversationLogFriendObserver::changed(U32 mask) LLConversationLog::LLConversationLog() { - LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); - if (ctrl) + LLControlVariable* log_instant_message = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); + LLControlVariable* keep_convers_log = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); + bool is_log_message = false; + bool is_keep_log = false; + + if (log_instant_message) { - ctrl->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); - if (ctrl->getValue().asBoolean() - && gSavedSettings.getBOOL("KeepConversationLogTranscripts")) - { - enableLogging(true); - } + log_instant_message->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); + is_log_message = log_instant_message->getValue().asBoolean(); } + if (keep_convers_log) + { + keep_convers_log->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); + is_keep_log = keep_convers_log->getValue().asBoolean(); + } + + enableLogging(is_log_message && is_keep_log); } void LLConversationLog::enableLogging(bool enable) -- cgit v1.2.3 From 2610af9798374ce9fff7623d7aa7e269b2a78174 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 21 Dec 2012 15:35:56 +0200 Subject: CHUI-619 FUI button and conversation line items blink at different rates: changed rate --- indra/newview/app_settings/settings.xml | 2 +- indra/newview/llimview.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ebc915ec5a..507eb33f2d 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -13173,7 +13173,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>0.25</real> + <real>0.5</real> </map> <key>WindLightUseAtmosShaders</key> <map> diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cdc51ad2fc..708400cbe1 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -964,7 +964,7 @@ const std::string LLIMModel::getName(const LLUUID& session_id) const { LLIMSession* session = findIMSession(session_id); - if (!session) + if (!session) { llwarns << "session " << session_id << "does not exist " << llendl; return LLTrans::getString("no_session_message"); -- cgit v1.2.3 From 7549a392cc32dc36f0bc673a6569f01731cc1bbd Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 21 Dec 2012 16:28:33 +0200 Subject: CHUI-566 Flashing and color on Conversations FUI button and conversation line item: change behavior for the case "If conversations (container) floater open but not on top" --- indra/newview/llimview.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 708400cbe1..d736b81bb7 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -160,6 +160,7 @@ void on_new_message(const LLSD& msg) //session floater not focused (visible or not) bool session_floater_not_focused = session_floater && !session_floater->hasFocus(); + //conv. floater is closed bool conversation_floater_is_closed = !( im_box @@ -210,20 +211,16 @@ void on_new_message(const LLSD& msg) else if ("flash" == action) { - if (session_floater_not_focused) + if (conversation_floater_not_focused) { - //User is not focused on conversation containing the message - - if(conversation_floater_not_focused) + if(session_floater_not_focused) { + //User is not focused on conversation containing the message gToolBarView->flashCommand(LLCommandId("chat"), true); } - //conversation floater is open but a different conversation is focused - //else - //{ - im_box->flashConversationItemWidget(session_id, true); - //} - } + + im_box->flashConversationItemWidget(session_id, true); + } } else if("openconversations" == action) -- cgit v1.2.3 From 765a5a73dd3e2e7a88141e26f4aa7b479229ad2e Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Fri, 21 Dec 2012 16:45:58 +0200 Subject: CHUI-621 FIXED Notification chiclet UI error --- indra/newview/llchiclet.cpp | 2 +- .../skins/default/textures/bottomtray/Notices_Unread.png | Bin 0 -> 3693 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 indra/newview/skins/default/textures/bottomtray/Notices_Unread.png (limited to 'indra') diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 2fdcb17570..3dbb43c657 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -76,7 +76,7 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p) LLSysWellChiclet::~LLSysWellChiclet() { - delete mFlashToLitTimer; + mFlashToLitTimer->unset(); } void LLSysWellChiclet::setCounter(S32 counter) diff --git a/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png b/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png new file mode 100644 index 0000000000..0ac5b72b8f Binary files /dev/null and b/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png differ -- cgit v1.2.3 From dd7509f56de5e8a47680b33176e90c11ed518066 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 21 Dec 2012 20:05:40 +0200 Subject: CHUI-411 Entries in chat history viewer do not show all dates of entries and some entries show on multiple pages Type of variable for the time saving was changed from S32 to long int ("capacity" of S32-timer is only ~18 hours!) --- indra/newview/llconversationlog.cpp | 45 +++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 22 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index eb3a3731ee..e44749fd79 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -236,17 +236,20 @@ void LLConversationLog::logConversation(const LLUUID& session_id, BOOL has_offli const LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); LLConversation* conversation = findConversation(session); - if (session && conversation) + if (session) { - if(has_offline_msg) + if (conversation) { - updateOfflineIMs(session, has_offline_msg); + if(has_offline_msg) + { + updateOfflineIMs(session, has_offline_msg); + } + updateConversationTimestamp(conversation); + } + else + { + createConversation(session); } - updateConversationTimestamp(conversation); - } - else if (session && !conversation) - { - createConversation(session); } } @@ -307,19 +310,17 @@ void LLConversationLog::updateConversationTimestamp(LLConversation* conversation LLConversation* LLConversationLog::findConversation(const LLIMModel::LLIMSession* session) { - if (!session) + if (session) { - return NULL; - } + const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID; - const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID; - - conversations_vec_t::iterator conv_it = mConversations.begin(); - for(; conv_it != mConversations.end(); ++conv_it) - { - if (conv_it->getSessionID() == session_id) + conversations_vec_t::iterator conv_it = mConversations.begin(); + for(; conv_it != mConversations.end(); ++conv_it) { - return &*conv_it; + if (conv_it->getSessionID() == session_id) + { + return &*conv_it; + } } } @@ -411,8 +412,8 @@ bool LLConversationLog::saveToFile(const std::string& filename) // [1343221177] 0 1 0 John Doe| 7e4ec5be-783f-49f5-71dz-16c58c64c145 4ec62a74-c246-0d25-2af6-846beac2aa55 john.doe| // [1343222639] 2 0 0 Ad-hoc Conference| c3g67c89-c479-4c97-b21d-32869bcfe8rc 68f1c33e-4135-3e3e-a897-8c9b23115c09 Ad-hoc Conference hash597394a0-9982-766d-27b8-c75560213b9a| - fprintf(fp, "[%d] %d %d %d %s| %s %s %s|\n", - (S32)conv_it->getTime(), + fprintf(fp, "[%ld] %d %d %d %s| %s %s %s|\n", + conv_it->getTime(), (S32)conv_it->getConversationType(), (S32)0, (S32)conv_it->hasOfflineMessages(), @@ -446,7 +447,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename) char history_file_name[MAX_STRING]; int has_offline_ims; int stype; - S32 time; + time_t time; // before CHUI-348 it was a flag of conversation voice state int prereserved_unused; @@ -456,7 +457,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename) part_id_buffer[0] = '\0'; conv_id_buffer[0] = '\0'; - sscanf(buffer, "[%d] %d %d %d %[^|]| %s %s %[^|]|", + sscanf(buffer, "[%ld] %d %d %d %[^|]| %s %s %[^|]|", &time, &stype, &prereserved_unused, -- cgit v1.2.3 From 6df0377d1dd810cc1656c6c2664af2c7c87705fc Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Fri, 21 Dec 2012 20:11:01 +0200 Subject: CHUI-622 FIXED Default size of conversation log floater seems large --- .../default/xui/en/floater_conversation_log.xml | 163 ++++++++++----------- 1 file changed, 80 insertions(+), 83 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml index c9c52e5ce5..960db137b3 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -1,91 +1,88 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <floater - can_resize="true" - positioning="cascading" - height="400" - min_height="100" - min_width="390" - layout="topleft" - name="floater_conversation_log" - save_rect="true" - single_instance="true" - reuse_instance="true" - title="CONVERSATION LOG" - width="450"> - + can_resize="true" + positioning="cascading" + height="200" + min_height="100" + min_width="200" + layout="topleft" + name="floater_conversation_log" + save_rect="true" + single_instance="true" + reuse_instance="true" + title="CONVERSATION LOG" + width="300"> <string name="logging_calls_disabled"> Conversations are not being logged. To log conversations in the future, select "Save IM logs on my computer" under Preferences > Privacy. </string> - - <panel - follows="left|top|right" - height="27" - layout="topleft" - left="0" - name="buttons_panel" - top="0"> - <filter_editor - follows="left|top|right" - height="23" - layout="topleft" - left="8" - label="Filter People" - max_length_chars="300" - name="people_filter_input" - text_color="Black" - text_pad_left="10" - top="4" - width="364" /> - <menu_button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Conv_toolbar_sort" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="5" - menu_filename="menu_conversation_log_view.xml" - menu_position="bottomleft" - name="conversation_view_btn" - tool_tip="View/sort options" - top="3" - width="31" /> - <menu_button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="2" - name="conversations_gear_btn" - tool_tip="Actions on selected person or group" - top="3" - width="31" /> - </panel> - <panel - follows="all" - height="370" - layout="topleft" - left="5" - name="buttons_panel" - right="-5" - top_pad="5"> + <panel + bottom="0" + follows="left|top|right" + height="32" + left="0" + name="buttons_panel" + right="0" + top="0"> + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="8" + label="Filter People" + max_length_chars="300" + name="people_filter_input" + text_color="Black" + text_pad_left="10" + top="4" + width="204" /> + <menu_button + follows="top|right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_sort" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="8" + menu_filename="menu_conversation_log_view.xml" + menu_position="bottomleft" + name="conversation_view_btn" + tool_tip="View/sort options" + top="3" + width="31" /> + <menu_button + follows="top|right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="8" + name="conversations_gear_btn" + tool_tip="Actions on selected person or group" + top="3" + width="31" /> + </panel> + <panel + bottom="-1" + follows="all" + left="0" + name="log_panel" + right="-1" + top="32"> <conversation_log_list - opaque="true" - allow_select="true" - follows="all" - height="360" - layout="topleft" - left="3" - keep_selection_visible_on_reshape="true" - item_pad="2" - multi_select="false" - name="conversation_log_list" - right="-3" - top="5" /> - </panel> + allow_select="true" + bottom="-8" + opaque="true" + follows="all" + left="8" + keep_selection_visible_on_reshape="true" + item_pad="2" + multi_select="false" + name="conversation_log_list" + right="-8" + top="0" /> + </panel> </floater> -- cgit v1.2.3 From 923262f154748eea5ce1eda37df1b9df1eaf0f43 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Mon, 24 Dec 2012 14:20:25 +0200 Subject: CHUI-583 FIXED Link will be opened in external browser if this preference is set. --- indra/newview/llviewermenu.cpp | 15 +++++++++++++++ indra/newview/skins/default/xui/en/menu_viewer.xml | 14 +++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index fe9c00cc27..be9f7d645a 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7586,6 +7586,20 @@ void handle_web_content_test(const LLSD& param) LLWeb::loadURLInternal(url); } +void handle_show_url(const LLSD& param) +{ + std::string url = param.asString(); + if(gSavedSettings.getBOOL("UseExternalBrowser")) + { + LLWeb::loadURLExternal(url); + } + else + { + LLWeb::loadURLInternal(url); + } + +} + void handle_buy_currency_test(void*) { std::string url = @@ -8415,6 +8429,7 @@ void initialize_menus() // Advanced > UI commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2)); // sigh! this one opens the MEDIA browser commit.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2)); // this one opens the Web Content floater + commit.add("Advanced.ShowURL", boost::bind(&handle_show_url, _2)); view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest"); view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr"); view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory"); diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 00424e97f6..76de81559b 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1273,35 +1273,35 @@ label="User’s guide" name="User’s guide"> <menu_item_call.on_click - function="Advanced.WebBrowserTest" + function="Advanced.ShowURL" parameter="http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-User-s-Guide/ta-p/1244857"/> </menu_item_call> <menu_item_call label="Knowledge Base" name="Knowledge Base"> <menu_item_call.on_click - function="Advanced.WebBrowserTest" + function="Advanced.ShowURL" parameter="http://community.secondlife.com/t5/tkb/communitypage"/> </menu_item_call> <menu_item_call label="Wiki" name="Wiki"> <menu_item_call.on_click - function="Advanced.WebBrowserTest" + function="Advanced.ShowURL" parameter="http://wiki.secondlife.com"/> </menu_item_call> <menu_item_call label="Community Forums" name="Community Forums"> <menu_item_call.on_click - function="Advanced.WebBrowserTest" + function="Advanced.ShowURL" parameter="http://community.secondlife.com/t5/Forums/ct-p/Forums"/> </menu_item_call> <menu_item_call label="Support portal" name="Support portal"> <menu_item_call.on_click - function="Advanced.WebBrowserTest" + function="Advanced.ShowURL" parameter="https://support.secondlife.com/"/> </menu_item_call> <menu_item_separator/> @@ -1309,14 +1309,14 @@ label="[SECOND_LIFE] News" name="Second Life News"> <menu_item_call.on_click - function="Advanced.WebBrowserTest" + function="Advanced.ShowURL" parameter="http://community.secondlife.com/t5/Featured-News/bg-p/blog_feature_news"/> </menu_item_call> <menu_item_call label="[SECOND_LIFE] Blogs" name="Second Life Blogs"> <menu_item_call.on_click - function="Advanced.WebBrowserTest" + function="Advanced.ShowURL" parameter="http://community.secondlife.com/t5/Blogs/ct-p/Blogs"/> </menu_item_call> <menu_item_separator/> -- cgit v1.2.3 From 32944ef9e41a96950aa645a016c8f2c6bf71a351 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Mon, 24 Dec 2012 19:01:27 +0200 Subject: CHUI-627 FIXED Unnecessary attributes are deleted in xml --- indra/newview/skins/default/xui/en/floater_conversation_log.xml | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml index 960db137b3..cf61348a66 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -17,12 +17,10 @@ Conversations are not being logged. To log conversations in the future, select "Save IM logs on my computer" under Preferences > Privacy. </string> <panel - bottom="0" follows="left|top|right" height="32" left="0" name="buttons_panel" - right="0" top="0"> <filter_editor follows="left|top|right" -- cgit v1.2.3 From 51747dc6bfcdf0c3a9926f2b28ff30f0686623b3 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Tue, 25 Dec 2012 21:16:30 +0200 Subject: CHUI-623 FIXED No vertical scrollbar in conversation list --- indra/newview/skins/default/xui/en/floater_im_container.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index cbf1830093..e7638fe669 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -113,11 +113,12 @@ </layout_panel> </layout_stack> <panel + bottom="-5" follows="all" layout="topleft" name="conversations_list_panel" opaque="true" - top_pad="0" + top="35" left="5" right="-1"/> </layout_panel> @@ -127,7 +128,7 @@ name="messages_layout_panel" expanded_min_dim="222"> <panel_container - bottom="-1" + bottom="-5" follows="all" layout="topleft" left="0" -- cgit v1.2.3 From 12466171b149ebe94b20cc8c74b7c9b1163fdc33 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Wed, 26 Dec 2012 11:23:59 +0200 Subject: CHUI-632 FIXED Disable Gear button if nothing is selected --- indra/newview/llpanelblockedlist.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index ecab7d2167..df1ccdd9fc 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -137,6 +137,7 @@ void LLPanelBlockedList::updateButtons() { bool hasSelected = NULL != mBlockedList->getSelectedItem(); getChildView("unblock_btn")->setEnabled(hasSelected); + getChildView("blocked_gear_btn")->setEnabled(hasSelected); } void LLPanelBlockedList::unblockItem() -- cgit v1.2.3 From d05df4087c334fe30a9d0fe5224a828c677d0244 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Wed, 26 Dec 2012 11:46:29 +0200 Subject: CHUI-617 FIXED Update Gear button state after initing session. mConversationsRoot creation is moved to postBuild(). --- indra/newview/llfloaterimsession.cpp | 4 +-- indra/newview/llfloaterimsessiontab.cpp | 44 ++++++++++++++------------------- 2 files changed, 20 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index ff07ddfcbf..d36b138c21 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -86,7 +86,7 @@ LLFloaterIMSession::LLFloaterIMSession(const LLUUID& session_id) mCommitCallbackRegistrar.add("Avatar.GearDoToSelected", boost::bind(&LLFloaterIMSession::GearDoToSelected, this, _2)); mEnableCallbackRegistrar.add("Avatar.CheckGearItem", boost::bind(&LLFloaterIMSession::checkGearMenuItem, this, _2)); - setDocked(true); + setDocked(true); } @@ -754,7 +754,7 @@ void LLFloaterIMSession::sessionInitReplyReceived(const LLUUID& im_session_id) } initIMFloater(); - + LLFloaterIMSessionTab::updateGearBtn(); //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) //need to send delayed messages collected while waiting for session initialization diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 53d2f31b79..f5b657fa60 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -240,7 +240,24 @@ BOOL LLFloaterIMSessionTab::postBuild() result = LLDockableFloater::postBuild(); } - // Now ready to build the conversation and participants list + // Create the root using an ad-hoc base item + LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); + LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); + p.rect = LLRect(0, 0, getRect().getWidth(), 0); + p.parent_panel = mParticipantListPanel; + p.listener = base_item; + p.view_model = &mConversationViewModel; + p.root = NULL; + p.use_ellipses = true; + p.options_menu = "menu_conversation.xml"; + mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); + mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + // Attach that root to the scroller + mScroller->addChild(mConversationsRoot); + mConversationsRoot->setScrollContainer(mScroller); + mConversationsRoot->setFollowsAll(); + mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); + buildConversationViewParticipant(); refreshConversation(); @@ -388,31 +405,6 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant() return; } - // Create or recreate the root folder: this is a dummy folder (not shown) but required by the LLFolderView architecture - // We need to redo this when rebuilding as the session id (mSessionID) *may* have changed - if (mConversationsRoot) - { - // Remove the old root if any - mScroller->removeChild(mConversationsRoot); - } - // Create the root using an ad-hoc base item - LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); - LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); - p.rect = LLRect(0, 0, getRect().getWidth(), 0); - p.parent_panel = mParticipantListPanel; - p.listener = base_item; - p.view_model = &mConversationViewModel; - p.root = NULL; - p.use_ellipses = true; - p.options_menu = "menu_conversation.xml"; - mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); - mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); - // Attach that root to the scroller - mScroller->addChild(mConversationsRoot); - mConversationsRoot->setScrollContainer(mScroller); - mConversationsRoot->setFollowsAll(); - mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); - // Create the participants widgets now LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); -- cgit v1.2.3 From 099c9bcc6ffd9760cf935b6bcff8d796d0dff09d Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 26 Dec 2012 20:25:56 +0200 Subject: CHUI-629 FIXED Windows crash on exit when closing viewer with conversation log open with unread offline messages --- indra/newview/llconversationlog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index e44749fd79..0479733706 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -412,7 +412,7 @@ bool LLConversationLog::saveToFile(const std::string& filename) // [1343221177] 0 1 0 John Doe| 7e4ec5be-783f-49f5-71dz-16c58c64c145 4ec62a74-c246-0d25-2af6-846beac2aa55 john.doe| // [1343222639] 2 0 0 Ad-hoc Conference| c3g67c89-c479-4c97-b21d-32869bcfe8rc 68f1c33e-4135-3e3e-a897-8c9b23115c09 Ad-hoc Conference hash597394a0-9982-766d-27b8-c75560213b9a| - fprintf(fp, "[%ld] %d %d %d %s| %s %s %s|\n", + fprintf(fp, "[%lld] %d %d %d %s| %s %s %s|\n", conv_it->getTime(), (S32)conv_it->getConversationType(), (S32)0, -- cgit v1.2.3 From 1eae887434331357e057498905f7f5ff8f9f9c77 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 26 Dec 2012 23:55:23 +0200 Subject: CHUI-629 FIXED Resolve build problems; --- indra/newview/llconversationlog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 0479733706..8c86871134 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -413,7 +413,7 @@ bool LLConversationLog::saveToFile(const std::string& filename) // [1343222639] 2 0 0 Ad-hoc Conference| c3g67c89-c479-4c97-b21d-32869bcfe8rc 68f1c33e-4135-3e3e-a897-8c9b23115c09 Ad-hoc Conference hash597394a0-9982-766d-27b8-c75560213b9a| fprintf(fp, "[%lld] %d %d %d %s| %s %s %s|\n", - conv_it->getTime(), + (S64)conv_it->getTime(), (S32)conv_it->getConversationType(), (S32)0, (S32)conv_it->hasOfflineMessages(), -- cgit v1.2.3 From 7e8d336749b42ce134a67dfe1f1990644f1b263a Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Fri, 28 Dec 2012 15:28:19 +0200 Subject: CHUI-639 FIXED Min. width is increased to avoid overlapping --- indra/newview/skins/default/xui/en/floater_conversation_log.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml index cf61348a66..256e03c4d7 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -5,7 +5,7 @@ positioning="cascading" height="200" min_height="100" - min_width="200" + min_width="230" layout="topleft" name="floater_conversation_log" save_rect="true" -- cgit v1.2.3 From d99fa985c8ff65913e85dfaa9fd91892a197c4cc Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 28 Dec 2012 18:55:24 +0200 Subject: CHUI-566 ADD. FIX Flashing and color on Conversations FUI button and conversation line item Cancel sticking of color, if the button is pressed, or when a flashing of the previously selected button is ended --- indra/llui/llbutton.cpp | 18 +++++++++++++----- indra/newview/llimview.cpp | 16 ++++++---------- 2 files changed, 19 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 7ca9b869a8..a8149a9a1d 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -311,7 +311,7 @@ void LLButton::onCommit() { make_ui_sound("UISndClickRelease"); } - + if (mIsToggle) { toggleState(); @@ -613,8 +613,6 @@ void LLButton::draw() static LLCachedControl<bool> sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true); F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); - bool flash = mFlashing && sEnableButtonFlashing; - bool pressed_by_keyboard = FALSE; if (hasFocus()) { @@ -642,6 +640,17 @@ void LLButton::draw() LLColor4 glow_color; LLRender::eBlendType glow_type = LLRender::BT_ADD_WITH_ALPHA; LLUIImage* imagep = NULL; + + // Cancel sticking of color, if the button is pressed, + // or when a flashing of the previously selected button is ended + if (mFlashingTimer + && ((selected && !mFlashingTimer->isFlashingInProgress()) || pressed)) + { + mFlashing = false; + } + + bool flash = mFlashing && sEnableButtonFlashing; + if (pressed && mDisplayPressedState) { imagep = selected ? mImagePressedSelected : mImagePressed; @@ -697,8 +706,7 @@ void LLButton::draw() imagep = mImageDisabled; } - // Selected has a higher priority than flashing. If both are set, flashing is ignored. - if (mFlashing && !selected) + if (mFlashing) { // if button should flash and we have icon for flashing, use it as image for button if(flash && mImageFlash) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d736b81bb7..48cf7b3463 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -122,7 +122,7 @@ void on_new_message(const LLSD& msg) LLUUID session_id = msg["session_id"].asUUID(); LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); - // determine action for this session + // determine action for this session if (session_id.isNull()) { @@ -148,13 +148,14 @@ void on_new_message(const LLSD& msg) action = gSavedSettings.getString("NotificationGroupChatOptions"); } - // do not show notification in "do not disturb" mode or it goes from agent + // do not show notification which goes from agent if (gAgent.getID() == participant_id) { return; } // execution of the action + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); @@ -173,7 +174,7 @@ void on_new_message(const LLSD& msg) if ("toast" == action) { - // Skip toasting if we have open window of IM with this session id + // Skip toasting and flashing if we have open window of IM with this session id if (session_floater && session_floater->isInVisibleChain() && session_floater->hasFocus() @@ -184,12 +185,6 @@ void on_new_message(const LLSD& msg) return; } - // Skip toasting for system messages and for nearby chat - if (participant_id.isNull()) - { - return; - } - //User is not focused on conversation containing the message if(session_floater_not_focused) { @@ -201,7 +196,8 @@ void on_new_message(const LLSD& msg) gToolBarView->flashCommand(LLCommandId("chat"), true); //Show IM toasts (upper right toasts) - if(session_id.notNull()) + // Skip toasting for system messages and for nearby chat + if(session_id.notNull() && participant_id.notNull()) { LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); } -- cgit v1.2.3 From a25e6eb733bb8f6a0e9f8de1094155f685c6216d Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 28 Dec 2012 16:11:05 +0200 Subject: CHUI-453 FIXED Tooltip on chevron in torn-off conversation is incorrect: implemented suitable tool-tips; fixed a small separate bug ("tooltip_to_separate_window"/"tooltip_to_main_window" for Tear-Off Button: was shown reverse) --- indra/newview/llfloaterimsessiontab.cpp | 24 ++++++++++++++-------- .../skins/default/xui/en/floater_im_session.xml | 9 ++++++++ 2 files changed, 24 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 4e79bd0ac8..a79b4b3f1d 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -606,8 +606,8 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() // prevent start conversation before its container LLFloaterIMContainer::getInstance(); - bool is_torn_off = checkIfTornOff(); - if (!is_torn_off) + bool is_not_torn_off = !checkIfTornOff(); + if (is_not_torn_off) { hideAllStandardButtons(); } @@ -616,7 +616,7 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() // Participant list should be visible only in torn off floaters. bool is_participant_list_visible = - is_torn_off + !is_not_torn_off && gSavedSettings.getBOOL("IMShowControlPanel") && !mIsP2PChat; @@ -624,22 +624,28 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() // Display collapse image (<<) if the floater is hosted // or if it is torn off but has an open control panel. - bool is_expanded = !is_torn_off || is_participant_list_visible; + bool is_expanded = is_not_torn_off || is_participant_list_visible; mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); + mExpandCollapseBtn->setToolTip( + is_not_torn_off? + getString("expcol_button_not_tearoff_tooltip") : + (is_expanded? + getString("expcol_button_tearoff_and_expanded_tooltip") : + getString("expcol_button_tearoff_and_collapsed_tooltip"))); // toggle floater's drag handle and title visibility if (mDragHandle) { - mDragHandle->setTitleVisible(is_torn_off); + mDragHandle->setTitleVisible(!is_not_torn_off); } // The button (>>) should be disabled for torn off P2P conversations. - mExpandCollapseBtn->setEnabled(!is_torn_off || !mIsP2PChat); + mExpandCollapseBtn->setEnabled(is_not_torn_off || !mIsP2PChat); - mTearOffBtn->setImageOverlay(getString(is_torn_off? "return_icon" : "tear_off_icon")); - mTearOffBtn->setToolTip(getString(!is_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window")); + mTearOffBtn->setImageOverlay(getString(is_not_torn_off? "tear_off_icon" : "return_icon")); + mTearOffBtn->setToolTip(getString(is_not_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window")); - mCloseBtn->setVisible(!is_torn_off && !mIsNearbyChat); + mCloseBtn->setVisible(is_not_torn_off && !mIsNearbyChat); enableDisableCallBtn(); diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 9e2132dc3b..8f0574177f 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -49,6 +49,15 @@ <floater.string name="end_call_button_tooltip" value="Close voice connection"/> + <floater.string + name="expcol_button_not_tearoff_tooltip" + value="Collapse this pane"/> + <floater.string + name="expcol_button_tearoff_and_expanded_tooltip" + value="Collapse participant list"/> + <floater.string + name="expcol_button_tearoff_and_collapsed_tooltip" + value="Expand participant list"/> <view follows="all" layout="topleft" -- cgit v1.2.3 From 034143225ba60e8bb1163501e2f57c2be932578b Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 2 Jan 2013 13:10:42 -0800 Subject: CHUI-499: Removing debug code --- .../newview/lldonotdisturbnotificationstorage.cpp | 25 ---------------------- 1 file changed, 25 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index bf3dcae1f3..f4560d5668 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -29,11 +29,6 @@ #include "lldonotdisturbnotificationstorage.h" -#define XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT 0 - -#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT -#include "llchannelmanager.h" -#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT #include "llcommunicationchannel.h" #include "lldir.h" #include "llerror.h" @@ -41,9 +36,6 @@ #include "llnotifications.h" #include "llnotificationhandler.h" #include "llnotificationstorage.h" -#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT -#include "llscreenchannel.h" -#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT #include "llscriptfloater.h" #include "llsd.h" #include "llsingleton.h" @@ -109,12 +101,6 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() { return; } - -#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT - LLNotificationsUI::LLScreenChannel* notification_channel = - dynamic_cast<LLNotificationsUI::LLScreenChannel*>(LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); -#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT LLNotifications& instance = LLNotifications::instance(); @@ -146,17 +132,6 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() instance.add(notification); } - -#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT - // hide script floaters so they don't confuse the user and don't overlap startup toast - LLScriptFloaterManager::getInstance()->setFloaterVisible(notification->getID(), false); - - if(notification_channel) - { - // hide saved toasts so they don't confuse the user - notification_channel->hideToast(notification->getID()); - } -#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT } // Clear the communication channel history and rewrite the save file to empty it as well -- cgit v1.2.3 From f40ee4792d948ca99d19bdd6f645faea07e15f47 Mon Sep 17 00:00:00 2001 From: maximbproductengine <maximbproductengine@lindenlab.com> Date: Thu, 3 Jan 2013 06:35:40 +0200 Subject: CHUI-616 (Left Click on participant name in torn off conference moves focus to conversation floater) --- indra/newview/llconversationview.cpp | 21 --------------------- indra/newview/llconversationview.h | 2 -- 2 files changed, 23 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index e51efd48f5..903dd2a407 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -547,27 +547,6 @@ void LLConversationViewParticipant::onMouseLeave(S32 x, S32 y, MASK mask) LLFolderViewItem::onMouseLeave(x, y, mask); } -BOOL LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - LLConversationItem* item = NULL; - LLConversationViewSession* session_widget = - dynamic_cast<LLConversationViewSession *>(this->getParentFolder()); - if (session_widget) - { - item = dynamic_cast<LLConversationItem*>(session_widget->getViewModelItem()); - } - LLUUID session_id = item? item->getUUID() : LLUUID(); - BOOL result = LLFolderViewItem::handleMouseDown(x, y, mask); - - if(result) - { - (LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"))-> - selectConversationPair(session_id, false); - } - - return result; -} - S32 LLConversationViewParticipant::getLabelXPos() { return getIndentation() + mAvatarIcon->getRect().getWidth() + mIconPad; diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 74443e1d88..5f6acfb9ab 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -132,8 +132,6 @@ public: void addToFolder(LLFolderViewFolder* folder); void addToSession(const LLUUID& session_id); - /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - void onMouseEnter(S32 x, S32 y, MASK mask); void onMouseLeave(S32 x, S32 y, MASK mask); -- cgit v1.2.3 From 3d83fc3da5b0fa20bb631bfd2c94368946905675 Mon Sep 17 00:00:00 2001 From: maximbproductengine <maximbproductengine@lindenlab.com> Date: Thu, 3 Jan 2013 06:43:25 +0200 Subject: CHUI-608 (Conversations floater can be resized too small once a conversation is torn off) --- indra/newview/llfloaterimcontainer.h | 3 ++- indra/newview/llfloaterimsessiontab.cpp | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 09a24c0105..8daed46c7d 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -106,6 +106,8 @@ public: bool enableContextMenuItem(const std::string& item, uuid_vec_t& selectedIDS); void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS); + void assignResizeLimits(); + private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; avatarID_panel_map_t mSessions; @@ -154,7 +156,6 @@ private: void toggleAllowTextChat(const LLUUID& participant_uuid); void toggleMute(const LLUUID& participant_id, U32 flags); void openNearbyChat(); - void assignResizeLimits(); LLButton* mExpandCollapseBtn; LLButton* mStubCollapseBtn; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index f5b657fa60..4e79bd0ac8 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -751,6 +751,11 @@ void LLFloaterIMSessionTab::onTearOffClicked() { forceReshape(); } + LLFloaterIMContainer* container = LLFloaterIMContainer::getInstance(); + if (container) + { + container->assignResizeLimits(); + } refreshConversation(); updateGearBtn(); } -- cgit v1.2.3 From c464adc8ae35d3656e8de6aa459eb4615bb34c6f Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Thu, 3 Jan 2013 14:03:33 +0200 Subject: CHUI-636 FIXED Enable group context menu options, if uuid is empty and selected model item is group chat. In addition enable Chat history item for ad-hoc and group conversations. --- indra/newview/llfloaterimcontainer.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 2019a35faa..61a67a1f9f 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1101,12 +1101,20 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) uuid_vec_t uuids; getParticipantUUIDs(uuids); + //Enable Chat history item for ad-hoc and group conversations + if ("can_chat_history" == item) + { + if (getCurSelectedViewModelItem()->getType() != LLConversationItem::CONV_PARTICIPANT) + { + return isConversationLoggingAllowed(); + } + } - // If nothing is selected, everything needs to be disabled + // If nothing is selected(and selected item is not group chat), everything needs to be disabled if (uuids.size() <= 0) - { - return false; - } + { + return getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP; + } if("can_activate_group" == item) { @@ -1123,7 +1131,7 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v { return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); } - + // Extract the single select info bool is_single_select = (uuids.size() == 1); const LLUUID& single_id = uuids.front(); -- cgit v1.2.3 From f4902521f58956eda7701770eec51763a7663d3c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 3 Jan 2013 15:12:11 +0200 Subject: CHUI-631 FIXED 'Nearby chat' is not selected in Conversations floater after closing separate conversation if list of participants was expand in Conversations floater: force select 'Nearby chat' when session floater is destroyed --- indra/newview/llfloaterimsessiontab.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index a79b4b3f1d..76643b0235 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -82,6 +82,13 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) LLFloaterIMSessionTab::~LLFloaterIMSessionTab() { delete mRefreshTimer; + + // Select Nearby Chat session + LLFloaterIMContainer* container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + if (container) + { + container->selectConversationPair(LLUUID(NULL), true); + } } //static -- cgit v1.2.3 From 799c1f241f66db6d8701ee8c4339a5cce41c3c47 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 3 Jan 2013 18:59:20 +0200 Subject: CHUI-628 FIXED Open conversation log menu option not active in conversation floater when nearby chat is selected: Determination of the availability menu item was moved to the right place --- indra/newview/llfloaterimcontainer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 61a67a1f9f..50acd4ae24 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1101,6 +1101,11 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) uuid_vec_t uuids; getParticipantUUIDs(uuids); + if ("conversation_log" == item) + { + return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); + } + //Enable Chat history item for ad-hoc and group conversations if ("can_chat_history" == item) { @@ -1127,11 +1132,6 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_vec_t& uuids) { - if ("conversation_log" == item) - { - return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); - } - // Extract the single select info bool is_single_select = (uuids.size() == 1); const LLUUID& single_id = uuids.front(); -- cgit v1.2.3 From aa6fee292d1721eac6f0f1f270844e01e06979d4 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 3 Jan 2013 14:19:04 -0800 Subject: CHUI-499: Fixed a serialization problem where the a notification's objectInfo was not being serialized/deserialized. --- indra/llui/llnotifications.cpp | 5 +++++ indra/llui/llnotifications.h | 4 +++- indra/newview/lldonotdisturbnotificationstorage.cpp | 2 +- indra/newview/llnotificationstorage.cpp | 7 +------ indra/newview/llviewermessage.cpp | 3 +++ indra/newview/llviewermessage.h | 1 + 6 files changed, 14 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index c9b4399bef..8aa0b6f110 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -517,6 +517,11 @@ LLSD LLNotification::asLLSD() p.expiry = mExpiresAt; p.priority = mPriority; + if(mResponder) + { + p.functor.responder_sd = mResponder->asLLSD(); + } + if(!mResponseFunctorName.empty()) { p.functor.name = mResponseFunctorName; diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 42dee4c3e9..2a6391f49e 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -322,11 +322,13 @@ public: Alternative<std::string> name; Alternative<LLNotificationFunctorRegistry::ResponseFunctor> function; Alternative<LLNotificationResponderPtr> responder; + Alternative<LLSD> responder_sd; Functor() : name("responseFunctor"), function("functor"), - responder("responder") + responder("responder"), + responder_sd("responder_sd") {} }; Optional<Functor> functor; diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index f4560d5668..6407a3fa0c 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -118,7 +118,7 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() } else { - LLNotificationResponderInterface* responder = createResponder(notification_params["name"], notification_params["responder"]); + LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]); if (responder == NULL) { LL_WARNS("LLDoNotDisturbNotificationStorage") << "cannot create responder for notification of type '" diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index b797775369..4c5b7cc198 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -126,13 +126,8 @@ LLResponderRegistry::LLResponderRegistry() , mBuildMap() { add("ObjectGiveItem", &create<LLOfferInfo>); - add("OwnObjectGiveItem", &create<LLOfferInfo>); add("UserGiveItem", &create<LLOfferInfo>); - - add("TeleportOffered", &create<LLOfferInfo>); - add("TeleportOffered_MaturityExceeded", &create<LLOfferInfo>); - - add("OfferFriendship", &create<LLOfferInfo>); + add("offer_info", &create<LLOfferInfo>); } LLResponderRegistry::~LLResponderRegistry() diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 04dd7c911b..d264a18597 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1361,6 +1361,8 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id, gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(blocked_id)); } +std::string LLOfferInfo::mResponderType = "offer_info"; + LLOfferInfo::LLOfferInfo() : LLNotificationResponderInterface() , mFromGroup(FALSE) @@ -1406,6 +1408,7 @@ LLOfferInfo::LLOfferInfo(const LLOfferInfo& info) LLSD LLOfferInfo::asLLSD() { LLSD sd; + sd["responder_type"] = mResponderType; sd["im_type"] = mIM; sd["from_id"] = mFromID; sd["from_group"] = mFromGroup; diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 447fdeb9c7..3237f3fbdd 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -229,6 +229,7 @@ public: void forceResponse(InventoryOfferResponse response); + static std::string mResponderType; EInstantMessage mIM; LLUUID mFromID; BOOL mFromGroup; -- cgit v1.2.3 From 0e6ff3e7021b2e72f02b22550bbb96bc3674cba4 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 3 Jan 2013 14:37:24 -0800 Subject: CHUI-654 : Fixed! Select the Nearby Chat directly when one conversation only left, don't finesse with a root UUID that might not be NULL --- indra/newview/llfloaterimcontainer.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 50acd4ae24..9fe67e99da 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1430,11 +1430,10 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c { is_widget_selected = widget->isSelected(); new_selection = mConversationsRoot->getNextFromChild(widget); - if(new_selection == NULL) + if (!new_selection) { new_selection = mConversationsRoot->getPreviousFromChild(widget); } - widget->destroyView(); } @@ -1446,14 +1445,20 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c if (change_focus) { setFocus(TRUE); - if(new_selection != NULL) + if (new_selection) { if (mConversationsWidgets.size() == 1) - new_selection = new_selection->getParentFolder(); - LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem()); - if(vmi != NULL) { - selectConversationPair(vmi->getUUID(), true); + // If only one widget is left, it has to be the Nearby Chat. Select it directly. + selectConversationPair(LLUUID(NULL), true); + } + else + { + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem()); + if (vmi) + { + selectConversationPair(vmi->getUUID(), true); + } } } } -- cgit v1.2.3 From 3d1feec7641051386733405186cfe81b68a929ca Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 3 Jan 2013 15:11:53 -0800 Subject: CHUI-656 : Fixed. getTypedInstance() will create an instance if not found. Do not use that in destructors (bad...) or in places where creation is not required. Use findTypedInstance() instead. --- indra/newview/llfloaterimsessiontab.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 76643b0235..7b34a86f24 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -84,7 +84,7 @@ LLFloaterIMSessionTab::~LLFloaterIMSessionTab() delete mRefreshTimer; // Select Nearby Chat session - LLFloaterIMContainer* container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container"); if (container) { container->selectConversationPair(LLUUID(NULL), true); @@ -329,7 +329,7 @@ void LLFloaterIMSessionTab::onFocusReceived() LLTransientDockableFloater::onFocusReceived(); - LLFloaterIMContainer* container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container"); if (container) { container->selectConversationPair(mSessionID, true); -- cgit v1.2.3 From 9d687cc0042a6972a603778359055394c1cf0850 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Fri, 4 Jan 2013 15:14:24 +0200 Subject: CHUI-637 FIXED Call requestArrange() to update widget state. --- indra/newview/llfloaterimcontainer.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 9fe67e99da..22db4dd0eb 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -678,6 +678,7 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) { widget->setOpen(false); } + widget->requestArrange(); } } } -- cgit v1.2.3 From 4d971c43518f02fe202cf437f059250061cd9756 Mon Sep 17 00:00:00 2001 From: maximbproductengine <maximbproductengine@lindenlab.com> Date: Fri, 4 Jan 2013 16:48:34 +0200 Subject: CHUI-608 (Conversations floater can be resized too small once a conversation is torn off) --- indra/newview/llfloaterimcontainer.cpp | 6 ++++++ indra/newview/llfloaterimcontainer.h | 1 + indra/newview/llfloaterimsessiontab.cpp | 5 ----- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 2019a35faa..151d901708 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -605,6 +605,12 @@ void LLFloaterIMContainer::setVisible(BOOL visible) LLMultiFloater::setVisible(visible); } +void LLFloaterIMContainer::updateResizeLimits() +{ + LLMultiFloater::updateResizeLimits(); + assignResizeLimits(); +} + void LLFloaterIMContainer::collapseMessagesPane(bool collapse) { if (mMessagesPane->isCollapsed() == collapse) diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 8daed46c7d..0cd1b6759b 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -60,6 +60,7 @@ public: /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void draw(); /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ void updateResizeLimits(); void onCloseFloater(LLUUID& id); /*virtual*/ void addFloater(LLFloater* floaterp, diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 4e79bd0ac8..f5b657fa60 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -751,11 +751,6 @@ void LLFloaterIMSessionTab::onTearOffClicked() { forceReshape(); } - LLFloaterIMContainer* container = LLFloaterIMContainer::getInstance(); - if (container) - { - container->assignResizeLimits(); - } refreshConversation(); updateGearBtn(); } -- cgit v1.2.3 From b1ba208e7fcb8dbaa2c47b70fe580094982e36dd Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Sat, 5 Jan 2013 00:09:36 +0200 Subject: CHUI-643 W.I.P. Collapsed conversations floater has huge right padding: corrected of a imcontainer's resize calculating --- indra/newview/llfloaterimcontainer.cpp | 59 ++++++++++++---------- .../skins/default/xui/en/floater_im_container.xml | 3 +- 2 files changed, 34 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index ae243d6495..69d6f1ca38 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -618,34 +618,34 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse) return; } + // Save current width of panels before collapsing/expanding right pane. + S32 conv_pane_width = mConversationsPane->getRect().getWidth(); + S32 msg_pane_width = mMessagesPane->getRect().getWidth(); + if (collapse) { // Save the messages pane width before collapsing it. - gSavedPerAccountSettings.setS32("ConversationsMessagePaneWidth", mMessagesPane->getRect().getWidth()); + gSavedPerAccountSettings.setS32("ConversationsMessagePaneWidth", msg_pane_width); // Save the order in which the panels are closed to reverse user's last action. gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", mConversationsPane->isCollapsed()); } - // Save left pane rectangle before collapsing/expanding right pane. - LLRect prevRect = mConversationsPane->getRect(); - // Show/hide the messages pane. mConversationsStack->collapsePanel(mMessagesPane, collapse); - if (!collapse) - { - // Make sure layout is updated before resizing conversation pane. - mConversationsStack->updateLayout(); - } + // Make sure layout is updated before resizing conversation pane. + mConversationsStack->updateLayout(); updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); + if (!collapse) { // Restore conversation's pane previous width after expanding messages pane. - mConversationsPane->setTargetDim(prevRect.getWidth()); + mConversationsPane->setTargetDim(conv_pane_width); } } + void LLFloaterIMContainer::collapseConversationsPane(bool collapse) { if (mConversationsPane->isCollapsed() == collapse) @@ -657,10 +657,13 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) button_panel->setVisible(!collapse); mExpandCollapseBtn->setImageOverlay(getString(collapse ? "expand_icon" : "collapse_icon")); + // Save current width of panels before collapsing/expanding right pane. + S32 conv_pane_width = mConversationsPane->getRect().getWidth(); + if (collapse) { // Save the conversations pane width before collapsing it. - gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", mConversationsPane->getRect().getWidth()); + gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", conv_pane_width); // Save the order in which the panels are closed to reverse user's last action. gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", !mMessagesPane->isCollapsed()); @@ -668,8 +671,9 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) mConversationsStack->collapsePanel(mConversationsPane, collapse); - S32 collapsed_width = mConversationsPane->getMinDim(); - updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - collapsed_width); + S32 delta_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - mConversationsPane->getMinDim(); + + updateState(collapse, delta_width); for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); widget_it != mConversationsWidgets.end(); ++widget_it) @@ -685,7 +689,7 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) widget->setOpen(false); } widget->requestArrange(); -} + } } } @@ -693,6 +697,8 @@ void LLFloaterIMContainer::updateState(bool collapse, S32 delta_width) { LLRect floater_rect = getRect(); floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); +S32 debug_var = floater_rect.getWidth(); +debug_var = debug_var + 1; // Set by_user = true so that reshaped rect is saved in user_settings. setShape(floater_rect, true); @@ -705,29 +711,28 @@ void LLFloaterIMContainer::updateState(bool collapse, S32 delta_width) setCanResize(is_left_pane_expanded || is_right_pane_expanded); setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); + assignResizeLimits(); + // force set correct size for the title after show/hide minimize button LLRect cur_rect = getRect(); LLRect force_rect = cur_rect; force_rect.mRight = cur_rect.mRight + 1; setRect(force_rect); setRect(cur_rect); - - // restore floater's resize limits (prevent collapse when left panel is expanded) - if (is_left_pane_expanded && !is_right_pane_expanded) - { - S32 expanded_min_size = mConversationsPane->getExpandedMinDim(); - setResizeLimits(expanded_min_size, expanded_min_size); - } - - assignResizeLimits(); } void LLFloaterIMContainer::assignResizeLimits() { - const LLRect& conv_rect = mConversationsPane->isCollapsed() ? LLRect() : mConversationsPane->getRect(); - S32 msg_limits = mMessagesPane->isCollapsed() ? 0 : mMessagesPane->getExpandedMinDim(); - S32 x_limits = conv_rect.getWidth() + msg_limits; - setResizeLimits(x_limits + LLPANEL_BORDER_WIDTH * 3, getMinHeight()); + bool is_conv_pane_expanded = !mConversationsPane->isCollapsed(); + bool is_msg_pane_expanded = !mMessagesPane->isCollapsed(); + + S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3); + S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH; + S32 conv_pane_current_width = is_conv_pane_expanded? mConversationsPane->getRect().getWidth() : mConversationsPane->getMinDim(); + S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0; + S32 new_min_width = conv_pane_current_width + msg_pane_min_width + summary_width_of_visible_borders; + + setResizeLimits(new_min_width, getMinHeight()); } void LLFloaterIMContainer::onAddButtonClicked() diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e7638fe669..951665552f 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -14,7 +14,8 @@ title="CONVERSATIONS" bottom="-50" right="-5" - width="450"> + width="450" + min_width="38"> <string name="collapse_icon" value="Conv_toolbar_collapse"/> -- cgit v1.2.3 From 118201943da157b6932d8c79ab3eb3d8c3c0a9a4 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 4 Jan 2013 23:54:38 +0200 Subject: CHUI-643 FIXED Collapsed conversations floater has huge right padding: prevent of a rewriting mOriginMinWidth and mOriginMinHeight to default values --- indra/llui/llmultifloater.cpp | 10 ++++------ indra/newview/llfloaterimcontainer.cpp | 15 ++++++++++++--- indra/newview/llfloaterimcontainer.h | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index 179b251cdb..59faabd482 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -37,12 +37,10 @@ // LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params) - : LLFloater(key), - mTabContainer(NULL), - mTabPos(LLTabContainer::TOP), - mAutoResize(TRUE), - mOrigMinWidth(params.min_width), - mOrigMinHeight(params.min_height) + : LLFloater(key) + , mTabContainer(NULL) + , mTabPos(LLTabContainer::TOP) + , mAutoResize(TRUE) { } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 69d6f1ca38..5624788e45 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -56,8 +56,8 @@ // // LLFloaterIMContainer // -LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed) -: LLMultiFloater(seed), +LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& params /*= getDefaultParams()*/) +: LLMultiFloater(seed, params), mExpandCollapseBtn(NULL), mConversationsRoot(NULL), mConversationsEventStream("ConversationsEvents"), @@ -153,6 +153,9 @@ void LLFloaterIMContainer::onCurrentChannelChanged(const LLUUID& session_id) BOOL LLFloaterIMContainer::postBuild() { + mOrigMinWidth = getMinWidth(); + mOrigMinHeight = getMinHeight(); + mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLFloaterIMContainer::onNewMessageReceived, this, _1)); // Do not call base postBuild to not connect to mCloseSignal to not close all floaters via Close button // mTabContainer will be initialized in LLMultiFloater::addChild() @@ -657,7 +660,7 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) button_panel->setVisible(!collapse); mExpandCollapseBtn->setImageOverlay(getString(collapse ? "expand_icon" : "collapse_icon")); - // Save current width of panels before collapsing/expanding right pane. + // Save current width of Conversation panel before collapsing/expanding right pane. S32 conv_pane_width = mConversationsPane->getRect().getWidth(); if (collapse) @@ -1408,6 +1411,12 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& current_participant_model++; } } + + if (uuid.notNull() && im_sessionp->isP2PSessionType()) + { + item->fetchAvatarName(LLIMModel::getInstance()->getOtherParticipantID(uuid)); + } + // Do that too for the conversation dialog LLFloaterIMSessionTab *conversation_floater = (uuid.isNull() ? (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")) : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(uuid))); if (conversation_floater) diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 0cd1b6759b..85d950c58b 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -53,7 +53,7 @@ class LLFloaterIMContainer , public LLIMSessionObserver { public: - LLFloaterIMContainer(const LLSD& seed); + LLFloaterIMContainer(const LLSD& seed, const Params& params = getDefaultParams()); virtual ~LLFloaterIMContainer(); /*virtual*/ BOOL postBuild(); -- cgit v1.2.3 From e59458590535d7fe571f9504fe97caa4e15701e6 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Sat, 5 Jan 2013 00:19:54 +0200 Subject: CHUI-643 FIXED Collapsed conversations floater has huge right padding: clean up; remove debug code --- indra/newview/llfloaterimcontainer.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 5624788e45..09d83e2a8f 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -700,8 +700,6 @@ void LLFloaterIMContainer::updateState(bool collapse, S32 delta_width) { LLRect floater_rect = getRect(); floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); -S32 debug_var = floater_rect.getWidth(); -debug_var = debug_var + 1; // Set by_user = true so that reshaped rect is saved in user_settings. setShape(floater_rect, true); @@ -729,6 +727,8 @@ void LLFloaterIMContainer::assignResizeLimits() bool is_conv_pane_expanded = !mConversationsPane->isCollapsed(); bool is_msg_pane_expanded = !mMessagesPane->isCollapsed(); + // With two panels visible number of borders is three, because the borders + // between the panels are merged into one S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3); S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH; S32 conv_pane_current_width = is_conv_pane_expanded? mConversationsPane->getRect().getWidth() : mConversationsPane->getMinDim(); @@ -1412,11 +1412,6 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& } } - if (uuid.notNull() && im_sessionp->isP2PSessionType()) - { - item->fetchAvatarName(LLIMModel::getInstance()->getOtherParticipantID(uuid)); - } - // Do that too for the conversation dialog LLFloaterIMSessionTab *conversation_floater = (uuid.isNull() ? (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")) : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(uuid))); if (conversation_floater) -- cgit v1.2.3 From 02ca16c1334d1409d8b14136f76305686796c359 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 4 Jan 2013 17:58:30 -0800 Subject: CHUI-499: Now when existing DND mode, stored IM's will not show a toast but instead flash the conversation line item and Chat FUI button. --- indra/llui/llnotifications.cpp | 3 +- indra/llui/llnotifications.h | 18 ++++- .../newview/lldonotdisturbnotificationstorage.cpp | 10 ++- indra/newview/llimhandler.cpp | 86 ++++++++++++---------- indra/newview/llimview.cpp | 37 ++++++++++ 5 files changed, 110 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 8aa0b6f110..9ba598995f 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -475,7 +475,8 @@ LLNotification::LLNotification(const LLSDParamAdapter<Params>& p) : mIgnored(false), mResponderObj(NULL), mId(p.id.isProvided() ? p.id : LLUUID::generateNewID()), - mOfferFromAgent(p.offer_from_agent) + mOfferFromAgent(p.offer_from_agent), + mIsDND(p.is_dnd) { if (p.functor.name.isChosen()) { diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 2a6391f49e..092a9acd7c 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -316,6 +316,7 @@ public: Optional<LLNotificationContext*> context; Optional<void*> responder; Optional<bool> offer_from_agent; + Optional<bool> is_dnd; struct Functor : public LLInitParam::ChoiceBlock<Functor> { @@ -342,7 +343,8 @@ public: form_elements("form"), substitutions("substitutions"), expiry("expiry"), - offer_from_agent("offer_from_agent", false) + offer_from_agent("offer_from_agent", false), + is_dnd("is_dnd", false) { time_stamp = LLDate::now(); responder = NULL; @@ -356,7 +358,8 @@ public: form_elements("form"), substitutions("substitutions"), expiry("expiry"), - offer_from_agent("offer_from_agent", false) + offer_from_agent("offer_from_agent", false), + is_dnd("is_dnd", false) { functor.name = _name; name = _name; @@ -383,6 +386,7 @@ private: void* mResponderObj; // TODO - refactor/remove this field LLNotificationResponderPtr mResponder; bool mOfferFromAgent; + bool mIsDND; // a reference to the template LLNotificationTemplatePtr mTemplatep; @@ -523,6 +527,16 @@ public: return mOfferFromAgent; } + bool isDND() const + { + return mIsDND; + } + + void setDND(const bool flag) + { + mIsDND = flag; + } + std::string getType() const; std::string getMessage() const; std::string getFooter() const; diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 6407a3fa0c..9bb2f27a46 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -109,15 +109,19 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() ++notification_it) { LLSD notification_params = *notification_it; - LLNotificationPtr notification(new LLNotification(notification_params)); + const LLUUID& notificationID = notification_params["id"]; + LLNotificationPtr notification = instance.find(notificationID); - const LLUUID& notificationID = notification->id(); - if (instance.find(notificationID)) + //Notification already exists in notification pipeline (same instance of app running) + if (notification) { + notification->setDND(true); instance.update(notification); } + //Notification doesn't exist (different instance since restarted app while in DND mode) else { + notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true)); LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]); if (responder == NULL) { diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index 72967eb6c7..c2b29f36e8 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -36,6 +36,8 @@ using namespace LLNotificationsUI; +extern void process_dnd_im(const LLSD& notification); + //-------------------------------------------------------------------------- LLIMHandler::LLIMHandler() : LLCommunicationNotificationHandler("IM Notifications", "notifytoast") @@ -60,44 +62,52 @@ void LLIMHandler::initChannel() //-------------------------------------------------------------------------- bool LLIMHandler::processNotification(const LLNotificationPtr& notification) { - if(mChannel.isDead()) - { - return false; - } - - // arrange a channel on a screen - if(!mChannel.get()->getVisible()) - { - initChannel(); - } - - LLSD substitutions = notification->getSubstitutions(); - - // According to comments in LLIMMgr::addMessage(), if we get message - // from ourselves, the sender id is set to null. This fixes EXT-875. - LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); - if (avatar_id.isNull()) - avatar_id = gAgentID; - - LLToastIMPanel::Params im_p; - im_p.notification = notification; - im_p.avatar_id = avatar_id; - im_p.from = substitutions["FROM"].asString(); - im_p.time = substitutions["TIME"].asString(); - im_p.message = substitutions["MESSAGE"].asString(); - im_p.session_id = substitutions["SESSION_ID"].asUUID(); - - LLToastIMPanel* im_box = new LLToastIMPanel(im_p); - - LLToast::Params p; - p.notif_id = notification->getID(); - p.session_id = im_p.session_id; - p.notification = notification; - p.panel = im_box; - p.can_be_stored = false; - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); - if(channel) - channel->addToast(p); + if(notification->isDND()) + { + LLSD data = notification->asLLSD(); //don't need this if retrieve needed data from notification getters + process_dnd_im(data); + } + else + { + if(mChannel.isDead()) + { + return false; + } + + // arrange a channel on a screen + if(!mChannel.get()->getVisible()) + { + initChannel(); + } + + LLSD substitutions = notification->getSubstitutions(); + + // According to comments in LLIMMgr::addMessage(), if we get message + // from ourselves, the sender id is set to null. This fixes EXT-875. + LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); + if (avatar_id.isNull()) + avatar_id = gAgentID; + + LLToastIMPanel::Params im_p; + im_p.notification = notification; + im_p.avatar_id = avatar_id; + im_p.from = substitutions["FROM"].asString(); + im_p.time = substitutions["TIME"].asString(); + im_p.message = substitutions["MESSAGE"].asString(); + im_p.session_id = substitutions["SESSION_ID"].asUUID(); + + LLToastIMPanel* im_box = new LLToastIMPanel(im_p); + + LLToast::Params p; + p.notif_id = notification->getID(); + p.session_id = im_p.session_id; + p.notification = notification; + p.panel = im_box; + p.can_be_stored = false; + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); + if(channel) + channel->addToast(p); + } return false; } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d736b81bb7..716e6fe7ba 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -101,6 +101,43 @@ BOOL LLSessionTimeoutTimer::tick() return TRUE; } + + +void process_dnd_im(const LLSD& notification) +{ + LLSD data = notification["substitutions"]; + LLUUID sessionID = data["SESSION_ID"].asUUID(); + + //re-create the IM session if needed + //(when coming out of DND mode upon app restart) + if(!gIMMgr->hasSession(sessionID)) + { + //reconstruct session using data from the notification + std::string name = data["FROM"]; + LLAvatarName av_name; + if (LLAvatarNameCache::get(data["FROM_ID"], &av_name)) + { + name = av_name.getDisplayName(); + } + + + LLIMModel::getInstance()->newSession(sessionID, + name, + IM_NOTHING_SPECIAL, + data["FROM_ID"], + false, + false); //will need slight refactor to retrieve whether offline message or not (assume online for now) + } + + //For now always flash conversation line item + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + im_box->flashConversationItemWidget(sessionID, true); + + //And flash toolbar button + gToolBarView->flashCommand(LLCommandId("chat"), true); +} + + static void on_avatar_name_cache_toast(const LLUUID& agent_id, const LLAvatarName& av_name, LLSD msg) -- cgit v1.2.3 From 12554bffb34895533ed11013a780bfa088756a67 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 4 Jan 2013 20:23:14 -0800 Subject: CHUI-580 : Fixed : Avoid fetching names while reacting to display name checkbox change (overkill), make display name pref disabled when usePeopleAPI is off --- indra/newview/llconversationmodel.cpp | 33 +++++++++++++++++++++++++-------- indra/newview/llconversationmodel.h | 6 ++++-- indra/newview/llfloaterimcontainer.cpp | 2 +- indra/newview/llfloaterpreference.cpp | 13 ++++++++++++- 4 files changed, 42 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index b1f45d6d64..bc5b72e029 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -434,24 +434,31 @@ void LLConversationItemParticipant::fetchAvatarName() } } -void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) +void LLConversationItemParticipant::updateAvatarName() { - menuentry_vec_t items; - menuentry_vec_t disabled_items; - - buildParticipantMenuOptions(items); - - hide_context_entries(menu, items, disabled_items); + llassert(getUUID().notNull()); + if (getUUID().notNull()) + { + LLAvatarName av_name; + if (LLAvatarNameCache::get(getUUID(),&av_name)) + { + updateAvatarName(av_name); + } + } } void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) { mAvatarNameCacheConnection.disconnect(); + updateAvatarName(av_name); +} +void LLConversationItemParticipant::updateAvatarName(const LLAvatarName& av_name) +{ mName = av_name.getUserName(); mDisplayName = av_name.getDisplayName(); mNeedsRefresh = true; - if(mParent != NULL) + if (mParent != NULL) { LLConversationItemSession* parent_session = dynamic_cast<LLConversationItemSession*>(mParent); if (parent_session != NULL) @@ -463,6 +470,16 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam } } +void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + buildParticipantMenuOptions(items); + + hide_context_entries(menu, items, disabled_items); +} + LLConversationItemSession* LLConversationItemParticipant::getParentSession() { LLConversationItemSession* parent_session = NULL; diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 743a6ba40b..6ae891203d 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -195,14 +195,16 @@ public: virtual const bool getDistanceToAgent(F64& dist) const { dist = mDistToAgent; return (dist >= 0.0); } - void fetchAvatarName(); + void fetchAvatarName(); // fetch and update the avatar name + void updateAvatarName(); // get from the cache (do *not* fetch) and update the avatar name LLConversationItemSession* getParentSession(); void dumpDebugData(); void setModeratorOptionsVisible(bool visible) { mDisplayModeratorOptions = visible; } private: - void onAvatarNameCache(const LLAvatarName& av_name); + void onAvatarNameCache(const LLAvatarName& av_name); // callback used by fetchAvatarName + void updateAvatarName(const LLAvatarName& av_name); bool mIsMuted; // default is false bool mIsModerator; // default is false diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 3c85f21188..e1288a763c 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -393,7 +393,7 @@ void LLFloaterIMContainer::processParticipantsStyleUpdate() { LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); // Get the avatar name for this participant id from the cache and update the model - participant_model->fetchAvatarName(); + participant_model->updateAvatarName(); // Next participant current_participant_model++; } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 13d8a79f8d..3d4a1c44d8 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1682,6 +1682,17 @@ LLPanelPreference::LLPanelPreference() //virtual BOOL LLPanelPreference::postBuild() { + ////////////////////// PanelGeneral /////////////////// + if (hasChild("display_names_check")) + { + BOOL use_people_api = gSavedSettings.getBOOL("UsePeopleAPI"); + LLCheckBoxCtrl* ctrl_display_name = getChild<LLCheckBoxCtrl>("display_names_check"); + ctrl_display_name->setEnabled(use_people_api); + if (!use_people_api) + { + ctrl_display_name->setValue(FALSE); + } + } ////////////////////// PanelVoice /////////////////// if (hasChild("voice_unavailable")) @@ -1732,7 +1743,7 @@ BOOL LLPanelPreference::postBuild() getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setCommitCallback(boost::bind(&showFavoritesOnLoginWarning, _1, _2)); } - // Panel Advanced + //////////////////////PanelAdvanced /////////////////// if (hasChild("modifier_combo")) { //localizing if push2talk button is set to middle mouse -- cgit v1.2.3 From 3d0ec3da5baea6bb2b9b72707a884ac7b516c4fd Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 7 Jan 2013 15:32:47 -0800 Subject: CHUI-659 : WIP : Verified (tested) and cleaned up some CHUI-101 refactoring code. --- indra/llui/llfolderviewmodel.h | 4 ++-- indra/newview/llinventoryfilter.cpp | 9 +++------ indra/newview/llpanelobjectinventory.cpp | 10 +++++----- indra/newview/lltexturectrl.cpp | 15 --------------- 4 files changed, 10 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 7019857c0f..5837052565 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -401,8 +401,8 @@ public: virtual const FilterType& getFilter() const { return mFilter; } virtual void setFilter(const FilterType& filter) { mFilter = filter; } - // TODO RN: remove this and put all filtering logic in view model - // add getStatusText and isFiltering() + // By default, we assume the content is available. If a network fetch mechanism is implemented for the model, + // this method needs to be overloaded and return the relevant fetch status. virtual bool contentsReady() { return true; } diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index c913269aad..92f2d33073 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -42,8 +42,6 @@ #include "llclipboard.h" #include "lltrans.h" -//TODO RN: fix use of static cast as much as possible - LLFastTimer::DeclareTimer FT_FILTER_CLIPBOARD("Filter Clipboard"); LLInventoryFilter::FilterOps::FilterOps(const Params& p) @@ -83,7 +81,7 @@ LLInventoryFilter::LLInventoryFilter(const Params& p) bool LLInventoryFilter::check(const LLFolderViewModelItem* item) { - const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item); + const LLFolderViewModelItemInventory* listener = dynamic_cast<const LLFolderViewModelItemInventory*>(item); // Clipboard cut items are *always* filtered so we need this value upfront const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE); @@ -122,7 +120,7 @@ bool LLInventoryFilter::check(const LLInventoryItem* item) bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const { - const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item); + const LLFolderViewModelItemInventory* listener = dynamic_cast<const LLFolderViewModelItemInventory*>(item); if (!listener) { llerrs << "Folder view event listener not found." << llendl; @@ -384,8 +382,7 @@ const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const std::string::size_type LLInventoryFilter::getStringMatchOffset(LLFolderViewModelItem* item) const { - const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item); - return mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos; + return mFilterSubString.size() ? item->getSearchableName().find(mFilterSubString) : std::string::npos; } bool LLInventoryFilter::isDefault() const diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index a2aabb50b5..527aefe821 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1555,6 +1555,10 @@ void LLPanelObjectInventory::reset() mCommitCallbackRegistrar.pushScope(); // push local callbacks + // Reset the inventory model to show all folders by default + mInventoryViewModel.getFilter().setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + + // Create a new folder view root LLRect dummy_rect(0, 1, 1, 0); LLFolderView::Params p; p.name = "task inventory"; @@ -1566,11 +1570,7 @@ void LLPanelObjectInventory::reset() p.view_model = &mInventoryViewModel; p.root = NULL; mFolders = LLUICtrlFactory::create<LLFolderView>(p); - // this ensures that we never say "searching..." or "no items found" - //TODO RN: make this happen by manipulating filter object directly - LLInventoryFilter& inventoryFilter = dynamic_cast<LLInventoryFilter&>(mFolders->getFolderViewModel()->getFilter()); - inventoryFilter.setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); - + mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); if (hasFocus()) diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 65f0290060..007eb8e33f 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -652,26 +652,11 @@ void LLFloaterTexturePicker::draw() { folder_view->setPinningSelectedItem(mSelectedItemPinned); folder_view->getViewModelItem()->dirtyFilter(); - //TODO RN: test..still works without this? - //folder_view->arrangeFromRoot(); - mSelectedItemPinned = TRUE; } } } -// static -/* -void LLFloaterTexturePicker::onSaveAnotherCopyDialog( S32 option, void* userdata ) -{ - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - if( 0 == option ) - { - self->copyToInventoryFinal(); - } -} -*/ - const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL copyable_only) { LLViewerInventoryCategory::cat_array_t cats; -- cgit v1.2.3 From d68f4ff646378070c1a92b3dc53f791454395356 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 7 Jan 2013 17:42:11 -0800 Subject: CHUI-659 : WIP : Reimplemented favorite landmark sorting to follow favorites bar index sorting. --- indra/newview/llfolderviewmodelinventory.cpp | 53 ++++++++++++---------------- 1 file changed, 23 insertions(+), 30 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 8a4b4bae84..429315e33f 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -29,6 +29,7 @@ #include "llinventorymodelbackgroundfetch.h" #include "llinventorypanel.h" #include "lltooldraganddrop.h" +#include "llfavoritesbar.h" // // class LLFolderViewModelInventory @@ -236,39 +237,31 @@ const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const { - // ignore sort order for landmarks in the Favorites folder. - // they should be always sorted as in Favorites bar. See EXT-719 - //TODO RN: fix sorting in favorites folder - //if (a->getSortGroup() == SG_ITEM - // && b->getSortGroup() == SG_ITEM - // && a->getInventoryType() == LLInventoryType::IT_LANDMARK - // && b->getInventoryType() == LLInventoryType::IT_LANDMARK) - //{ - - // static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - - // LLUUID a_uuid = a->getParentFolder()->getUUID(); - // LLUUID b_uuid = b->getParentFolder()->getUUID(); - - // if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) - // { - // // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem - // // or to LLInvFVBridge - // LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a))->getItem(); - // LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b))->getItem(); - // if (!aitem || !bitem) - // return false; - // S32 a_sort = aitem->getSortField(); - // S32 b_sort = bitem->getSortField(); - // return a_sort < b_sort; - // } - //} + // Ignore sort order for landmarks in the Favorites folder. + // In that folder, landmarks should be always sorted as in the Favorites bar. See EXT-719 + if (a->getSortGroup() == SG_ITEM + && b->getSortGroup() == SG_ITEM + && a->getInventoryType() == LLInventoryType::IT_LANDMARK + && b->getInventoryType() == LLInventoryType::IT_LANDMARK) + { + static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + // If both landmarks are in the favorite folder... + if (gInventory.isObjectDescendentOf(a->getUUID(), favorites_folder_id) && gInventory.isObjectDescendentOf(b->getUUID(), favorites_folder_id)) + { + // Get their index in that folder + S32 a_sort = LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID()); + S32 b_sort = LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID()); + // Note: since there are both in the favorite, we shouldn't get negative index value... + if (!((a_sort < 0) && (b_sort < 0))) + { + return a_sort < b_sort; + } + } + } // We sort by name if we aren't sorting by date // OR if these are folders and we are sorting folders by name. - bool by_name = (!mByDate - || (mFoldersByName - && (a->getSortGroup() != SG_ITEM))); + bool by_name = (!mByDate || (mFoldersByName && (a->getSortGroup() != SG_ITEM))); if (a->getSortGroup() != b->getSortGroup()) { -- cgit v1.2.3 From 51d6589eedc408aa7f8a81009b1be356ddc99252 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 7 Jan 2013 18:02:28 -0800 Subject: CHUI-659 : WIP : Clean up typos in my own comments --- indra/newview/llfolderviewmodelinventory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 429315e33f..d47c28678d 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -245,13 +245,13 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, && b->getInventoryType() == LLInventoryType::IT_LANDMARK) { static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - // If both landmarks are in the favorite folder... + // If both landmarks are in the Favorites folder... if (gInventory.isObjectDescendentOf(a->getUUID(), favorites_folder_id) && gInventory.isObjectDescendentOf(b->getUUID(), favorites_folder_id)) { // Get their index in that folder S32 a_sort = LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID()); S32 b_sort = LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID()); - // Note: since there are both in the favorite, we shouldn't get negative index value... + // Note: this test is a bit overkill: since they are both in the Favorites folder, we shouldn't get negative index values... if (!((a_sort < 0) && (b_sort < 0))) { return a_sort < b_sort; -- cgit v1.2.3 From d71c0ab32c744a6672e4364e3d090d317ec0647c Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 7 Jan 2013 18:30:59 -0800 Subject: CHUI-659 : WIP : Clamp down on the number of rearrange we really need. --- indra/llui/llfolderviewitem.cpp | 14 +++++++------- indra/newview/llfolderviewmodelinventory.cpp | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 1281d6bd66..6f8bdb1919 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1664,16 +1664,16 @@ void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) void LLFolderViewFolder::requestArrange() { - //if ( mLastArrangeGeneration != -1) + if ( mLastArrangeGeneration != -1) { - mLastArrangeGeneration = -1; - // flag all items up to root - if (mParentFolder) - { - mParentFolder->requestArrange(); - } + mLastArrangeGeneration = -1; + // flag all items up to root + if (mParentFolder) + { + mParentFolder->requestArrange(); } } +} void LLFolderViewFolder::toggleOpen() { diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index d47c28678d..586965e5a0 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -135,7 +135,6 @@ void LLFolderViewModelItemInventory::setPassedFilter(bool passed, S32 filter_gen if (passed_filter_before != mPrevPassedAllFilters) { - //TODO RN: ensure this still happens, but without dependency on folderview LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder(); if (parent_folder) { -- cgit v1.2.3 From 0e7e877379b4ab0d8d8b7ae3ce8c9dfb91cc9de7 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 7 Jan 2013 19:12:32 -0800 Subject: CHUI-659 : WIP : Cleanup llfolderviewitem of filter code as it all moved into llfolderviewmodel. --- indra/llui/llfolderviewitem.cpp | 53 +++-------------------------------------- 1 file changed, 3 insertions(+), 50 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 6f8bdb1919..b7165f68b7 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -267,28 +267,11 @@ void LLFolderViewItem::refresh() mIconOpen = vmi.getIconOpen(); mIconOverlay = vmi.getIconOverlay(); - if (mRoot->useLabelSuffix()) - { + if (mRoot->useLabelSuffix()) + { mLabelStyle = vmi.getLabelStyle(); mLabelSuffix = vmi.getLabelSuffix(); -} - - //TODO RN: make sure this logic still fires - //std::string searchable_label(mLabel); - //searchable_label.append(mLabelSuffix); - //LLStringUtil::toUpper(searchable_label); - - //if (mSearchableLabel.compare(searchable_label)) - //{ - // mSearchableLabel.assign(searchable_label); - // vmi.dirtyFilter(); - // // some part of label has changed, so overall width has potentially changed, and sort order too - // if (mParentFolder) - // { - // mParentFolder->requestSort(); - // mParentFolder->requestArrange(); - // } - //} + } mLabelWidthDirty = true; vmi.dirtyFilter(); @@ -1125,22 +1108,6 @@ BOOL LLFolderViewFolder::needsArrange() return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); } -//TODO RN: get height resetting working -//void LLFolderViewFolder::setPassedFilter(BOOL passed, BOOL passed_folder, S32 filter_generation) -//{ -// // if this folder is now filtered, but wasn't before -// // (it just passed) -// if (passed && !passedFilter(filter_generation)) -// { -// // reset current height, because last time we drew it -// // it might have had more visible items than now -// mCurHeight = 0.f; -// } -// -// LLFolderViewItem::setPassedFilter(passed, passed_folder, filter_generation); -//} - - // Passes selection information on to children and record selection // information if necessary. BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, @@ -1620,20 +1587,6 @@ void LLFolderViewFolder::addItem(LLFolderViewItem* item) { getViewModelItem()->addChild(item->getViewModelItem()); } - - //TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria - //// Traverse parent folders and update creation date and resort, if necessary - //LLFolderViewFolder* parentp = this; - //while (parentp) - //{ - // if (parentp->mSortFunction.isByDate()) - // { - // // parent folder doesn't have a time stamp yet, so get it from us - // parentp->requestSort(); - // } - - // parentp = parentp->getParentFolder(); - //} } // this is an internal method used for adding items to folders. -- cgit v1.2.3 From dbe1d2f0933db59493d11e9b3ab2d84ca884e28a Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Tue, 8 Jan 2013 14:38:30 +0200 Subject: CHUI-602 FIXED Return false if Selected view model item is null. --- indra/newview/llfloaterimcontainer.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 09d83e2a8f..82563b8736 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1124,16 +1124,23 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) //Enable Chat history item for ad-hoc and group conversations if ("can_chat_history" == item) { - if (getCurSelectedViewModelItem()->getType() != LLConversationItem::CONV_PARTICIPANT) + if(getCurSelectedViewModelItem()) { - return isConversationLoggingAllowed(); + if (getCurSelectedViewModelItem()->getType() != LLConversationItem::CONV_PARTICIPANT) + { + return isConversationLoggingAllowed(); + } } } // If nothing is selected(and selected item is not group chat), everything needs to be disabled if (uuids.size() <= 0) { - return getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP; + if(getCurSelectedViewModelItem()) + { + return getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP; + } + return false; } if("can_activate_group" == item) -- cgit v1.2.3 From df5378cf38b0e8325ae41be8af772e30cb815dd4 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 8 Jan 2013 19:59:27 +0200 Subject: CHUI-611 Fixed! Text in torn off message panel not wrapping correctly with size of conversation panel --- indra/newview/llfloaterimcontainer.cpp | 2 +- .../skins/default/xui/en/floater_im_container.xml | 30 ++++++---------------- 2 files changed, 9 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 82563b8736..38528f18f0 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -162,7 +162,7 @@ BOOL LLFloaterIMContainer::postBuild() setTabContainer(getChild<LLTabContainer>("im_box_tab_container")); mStubPanel = getChild<LLPanel>("stub_panel"); - mStubTextBox = getChild<LLTextBox>("stub_textbox_2"); + mStubTextBox = getChild<LLTextBox>("stub_textbox"); mStubTextBox->setURLClickedCallback(boost::bind(&LLFloaterIMContainer::returnFloaterToHost, this)); mConversationsStack = getChild<LLLayoutStack>("conversations_stack"); diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 951665552f..12c1676127 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -161,32 +161,18 @@ <text type="string" clip_partial="false" - follows="left|top" + follows="left|top|right" layout="topleft" - left="20" - right="-20" - name="stub_textbox_1" - top="30" - height="20" - valign="center" - wrap="true"> - This conversation is in a separate window. - </text> - <text - type="string" - clip_partial="false" - follows="left|top" - layout="topleft" - left="20" - right="-20" - name="stub_textbox_2" - top="60" - height="20" + left="15" + right="-15" + name="stub_textbox" + top="25" + height="40" valign="center" parse_urls="true" wrap="true"> - [secondlife:/// Bring it back.] - </text> + This conversation is in a separate window. [secondlife:/// Bring it back.] + </text> </panel> </panel_container> </layout_panel> -- cgit v1.2.3 From 974720373d608a8cbcd3cd26c125b6487b5926a2 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 8 Jan 2013 12:21:47 -0800 Subject: CHUI-660: Problem: Upon auto-existing DND mode upon startup, the notification form elements (buttonts) were added to the form. But then deserialized form elements were also being added to the form causing duplicate buttons. As a solution, only add on the deserialized form elements that exceed the amount in the template. --- indra/llui/llnotifications.cpp | 18 ++- indra/llui/llnotifications.h | 1 + indra/newview/lltoastnotifypanel.cpp | 300 +++++++++++++++++------------------ 3 files changed, 168 insertions(+), 151 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 386345177d..ebdb4d5024 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -320,6 +320,11 @@ void LLNotificationForm::addElement(const std::string& type, const std::string& mFormData.append(element); } +void LLNotificationForm::addElement(const LLSD& element) +{ + mFormData.append(element); +} + void LLNotificationForm::append(const LLSD& sub_form) { if (sub_form.isArray()) @@ -818,7 +823,18 @@ void LLNotification::init(const std::string& template_name, const LLSD& form_ele //mSubstitutions["_ARGS"] = get_all_arguments_as_text(mSubstitutions); mForm = LLNotificationFormPtr(new LLNotificationForm(*mTemplatep->mForm)); - mForm->append(form_elements); + + //Prevents appending elements(buttons) that the template already had + if(form_elements.isArray() + && mForm->getNumElements() < form_elements.size()) + { + LLSD::array_const_iterator it = form_elements.beginArray() + mForm->getNumElements();; + + for(; it != form_elements.endArray(); ++it) + { + mForm->addElement(*it); + } + } // apply substitution to form labels mForm->formatElements(mSubstitutions); diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 092a9acd7c..96e0a86b7f 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -246,6 +246,7 @@ public: bool getElementEnabled(const std::string& element_name) const; void setElementEnabled(const std::string& element_name, bool enabled); void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD(), bool enabled = true); + void addElement(const LLSD &element); void formatElements(const LLSD& substitutions); // appends form elements from another form serialized as LLSD void append(const LLSD& sub_form); diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 844d7314d9..d494d12903 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -343,156 +343,156 @@ void LLToastNotifyPanel::onClickButton(void* data) void LLToastNotifyPanel::init( LLRect rect, bool show_images ) { - deleteAllChildren(); - - mTextBox = NULL; - mInfoPanel = NULL; - mControlPanel = NULL; - mNumOptions = 0; - mNumButtons = 0; - mAddedDefaultBtn = false; - - buildFromFile( "panel_notification.xml"); - if(rect != LLRect::null) - { - this->setShape(rect); - } - mInfoPanel = getChild<LLPanel>("info_panel"); - mInfoPanel->setFollowsAll(); - - mControlPanel = getChild<LLPanel>("control_panel"); - BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); - // customize panel's attributes - // is it intended for displaying a tip? - mIsTip = mNotification->getType() == "notifytip"; - // is it a script dialog? - mIsScriptDialog = (mNotification->getName() == "ScriptDialog" || mNotification->getName() == "ScriptDialogGroup"); - // is it a caution? - // - // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the - // notify xml template specifies that it is a caution - // tip-style notification handle 'caution' differently -they display the tip in a different color - mIsCaution = mNotification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; - - // setup parameters - // get a notification message - mMessage = mNotification->getMessage(); - // init font variables - if (!sFont) -{ - sFont = LLFontGL::getFontSansSerif(); - sFontSmall = LLFontGL::getFontSansSerifSmall(); -} - // initialize - setFocusRoot(!mIsTip); - // get a form for the notification - LLNotificationFormPtr form(mNotification->getForm()); - // get number of elements - mNumOptions = form->getNumElements(); - - // customize panel's outfit - // preliminary adjust panel's layout - //move to the end - //mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); - - // adjust text options according to the notification type - // add a caution textbox at the top of a caution notification - if (mIsCaution && !mIsTip) - { - mTextBox = getChild<LLTextBox>("caution_text_box"); - } - else - { - mTextBox = getChild<LLTextEditor>("text_editor_box"); - } - - mTextBox->setMaxTextLength(MAX_LENGTH); - mTextBox->setVisible(TRUE); - mTextBox->setPlainText(!show_images); - mTextBox->setValue(mNotification->getMessage()); - - // add buttons for a script notification - if (mIsTip) - { - adjustPanelForTipNotice(); - } - else -{ - std::vector<index_button_pair_t> buttons; - buttons.reserve(mNumOptions); - S32 buttons_width = 0; - // create all buttons and accumulate they total width to reshape mControlPanel - for (S32 i = 0; i < mNumOptions; i++) - { - LLSD form_element = form->getElement(i); - if (form_element["type"].asString() != "button") - { - // not a button. - continue; - } - if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) - { - // a textbox pretending to be a button. - continue; - } - LLButton* new_button = createButton(form_element, TRUE); - buttons_width += new_button->getRect().getWidth(); - S32 index = form_element["index"].asInteger(); - buttons.push_back(index_button_pair_t(index,new_button)); -} - if (buttons.empty()) -{ - addDefaultButton(); - } - else - { - const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel - S32 button_panel_height = mControlPanel->getRect().getHeight(); - //try get an average h_pad to spread out buttons - S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); - if(h_pad < 2*HPAD) - { - /* - * Probably it is a scriptdialog toast - * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. - * In last case set default h_pad to avoid heaping of buttons - */ - S32 button_per_row = button_panel_width / BUTTON_WIDTH; - h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row - if(h_pad < 2*HPAD) // still not enough space between buttons ? - { - h_pad = 2*HPAD; - } -} - if (mIsScriptDialog) -{ - // we are using default width for script buttons so we can determinate button_rows - //to get a number of rows we divide the required width of the buttons to button_panel_width - S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); - //S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; - //reserve one row for the ignore_btn - button_rows++; - //calculate required panel height for scripdialog notification. - button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; - } - else - { - // in common case buttons can have different widths so we need to calculate button_rows according to buttons_width - //S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); - S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); - //calculate required panel height - button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + BOTTOM_PAD; -} - - // we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed - adjustPanelForScriptNotice(button_panel_width, button_panel_height); - updateButtonsLayout(buttons, h_pad); - // save buttons for later use in disableButtons() - //mButtons.assign(buttons.begin(), buttons.end()); - } - } - // adjust panel's height to the text size - snapToMessageHeight(mTextBox, MAX_LENGTH); + deleteAllChildren(); + + mTextBox = NULL; + mInfoPanel = NULL; + mControlPanel = NULL; + mNumOptions = 0; + mNumButtons = 0; + mAddedDefaultBtn = false; + + buildFromFile( "panel_notification.xml"); + if(rect != LLRect::null) + { + this->setShape(rect); + } + mInfoPanel = getChild<LLPanel>("info_panel"); + mInfoPanel->setFollowsAll(); + + mControlPanel = getChild<LLPanel>("control_panel"); + BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); + // customize panel's attributes + // is it intended for displaying a tip? + mIsTip = mNotification->getType() == "notifytip"; + // is it a script dialog? + mIsScriptDialog = (mNotification->getName() == "ScriptDialog" || mNotification->getName() == "ScriptDialogGroup"); + // is it a caution? + // + // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the + // notify xml template specifies that it is a caution + // tip-style notification handle 'caution' differently -they display the tip in a different color + mIsCaution = mNotification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; + + // setup parameters + // get a notification message + mMessage = mNotification->getMessage(); + // init font variables + if (!sFont) + { + sFont = LLFontGL::getFontSansSerif(); + sFontSmall = LLFontGL::getFontSansSerifSmall(); + } + // initialize + setFocusRoot(!mIsTip); + // get a form for the notification + LLNotificationFormPtr form(mNotification->getForm()); + // get number of elements + mNumOptions = form->getNumElements(); + + // customize panel's outfit + // preliminary adjust panel's layout + //move to the end + //mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); + + // adjust text options according to the notification type + // add a caution textbox at the top of a caution notification + if (mIsCaution && !mIsTip) + { + mTextBox = getChild<LLTextBox>("caution_text_box"); + } + else + { + mTextBox = getChild<LLTextEditor>("text_editor_box"); + } + + mTextBox->setMaxTextLength(MAX_LENGTH); + mTextBox->setVisible(TRUE); + mTextBox->setPlainText(!show_images); + mTextBox->setValue(mNotification->getMessage()); + + // add buttons for a script notification + if (mIsTip) + { + adjustPanelForTipNotice(); + } + else + { + std::vector<index_button_pair_t> buttons; + buttons.reserve(mNumOptions); + S32 buttons_width = 0; + // create all buttons and accumulate they total width to reshape mControlPanel + for (S32 i = 0; i < mNumOptions; i++) + { + LLSD form_element = form->getElement(i); + if (form_element["type"].asString() != "button") + { + // not a button. + continue; + } + if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) + { + // a textbox pretending to be a button. + continue; + } + LLButton* new_button = createButton(form_element, TRUE); + buttons_width += new_button->getRect().getWidth(); + S32 index = form_element["index"].asInteger(); + buttons.push_back(index_button_pair_t(index,new_button)); + } + if (buttons.empty()) + { + addDefaultButton(); + } + else + { + const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel + S32 button_panel_height = mControlPanel->getRect().getHeight(); + //try get an average h_pad to spread out buttons + S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); + if(h_pad < 2*HPAD) + { + /* + * Probably it is a scriptdialog toast + * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. + * In last case set default h_pad to avoid heaping of buttons + */ + S32 button_per_row = button_panel_width / BUTTON_WIDTH; + h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row + if(h_pad < 2*HPAD) // still not enough space between buttons ? + { + h_pad = 2*HPAD; + } + } + if (mIsScriptDialog) + { + // we are using default width for script buttons so we can determinate button_rows + //to get a number of rows we divide the required width of the buttons to button_panel_width + S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); + //S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; + //reserve one row for the ignore_btn + button_rows++; + //calculate required panel height for scripdialog notification. + button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; + } + else + { + // in common case buttons can have different widths so we need to calculate button_rows according to buttons_width + //S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); + S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); + //calculate required panel height + button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + BOTTOM_PAD; + } + + // we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed + adjustPanelForScriptNotice(button_panel_width, button_panel_height); + updateButtonsLayout(buttons, h_pad); + // save buttons for later use in disableButtons() + //mButtons.assign(buttons.begin(), buttons.end()); + } + } + // adjust panel's height to the text size + snapToMessageHeight(mTextBox, MAX_LENGTH); } -- cgit v1.2.3 From 856969285e027def5acba6c252dc65a242349d4f Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Thu, 10 Jan 2013 14:56:33 +0200 Subject: CHUI-658 FIXED Don't highlight whole content of the folder after right clicking if it is flashing. --- indra/llui/llfolderviewitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 42e5a6debf..ad18adddd5 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -736,7 +736,7 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo getRect().getWidth() - 2, 0, focusOutlineColor, FALSE); - if (showContent) + if (showContent && !isFlashing()) { gl_rect_2d(FOCUS_LEFT, focus_bottom + 1, -- cgit v1.2.3 From def252341a8c1675405404a6588749d06fa40791 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Tue, 8 Jan 2013 23:37:29 +0200 Subject: CHUI-612 FIXED Blank conversation names showing in conversation list --- indra/newview/llconversationmodel.cpp | 129 +++++++++++++++++++++------------ indra/newview/llconversationmodel.h | 20 +++-- indra/newview/llfloaterimcontainer.cpp | 9 ++- 3 files changed, 102 insertions(+), 56 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 0243fb1c97..a8da4908ce 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -47,7 +47,8 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& u mNeedsRefresh(true), mConvType(CONV_UNKNOWN), mLastActiveTime(0.0), - mDisplayModeratorOptions(false) + mDisplayModeratorOptions(false), + mAvatarNameCacheConnection() { } @@ -58,7 +59,8 @@ LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInte mNeedsRefresh(true), mConvType(CONV_UNKNOWN), mLastActiveTime(0.0), - mDisplayModeratorOptions(false) + mDisplayModeratorOptions(false), + mAvatarNameCacheConnection() { } @@ -69,10 +71,21 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod mNeedsRefresh(true), mConvType(CONV_UNKNOWN), mLastActiveTime(0.0), - mDisplayModeratorOptions(false) + mDisplayModeratorOptions(false), + mAvatarNameCacheConnection() { } +LLConversationItem::~LLConversationItem() +{ + // Disconnect any previous avatar name cache connection to ensure + // that the callback method is not called after destruction + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } +} + void LLConversationItem::postEvent(const std::string& event_type, LLConversationItemSession* session, LLConversationItemParticipant* participant) { LLUUID session_id = (session ? session->getUUID() : LLUUID()); @@ -142,6 +155,37 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32 } } +// method does subscription to changes in avatar name cache for current session/participant conversation item. +void LLConversationItem::fetchAvatarName(bool isParticipant /*= true*/) +{ + LLUUID item_id = getUUID(); + + // item should not be null for participants + if (isParticipant) + { + llassert(item_id.notNull()); + } + + // disconnect any previous avatar name cache connection + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + + // exclude nearby chat item + if (item_id.notNull()) + { + // for P2P session item, override it as item of called agent + if (CONV_SESSION_1_ON_1 == getType()) + { + item_id = LLIMModel::getInstance()->getOtherParticipantID(item_id); + } + + // subscribe on avatar name cache changes for participant and session items + mAvatarNameCacheConnection = LLAvatarNameCache::get(item_id, boost::bind(&LLConversationItem::onAvatarNameCache, this, _2)); + } +} + // // LLConversationItemSession // @@ -169,11 +213,11 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa addChild(participant); mIsLoaded = true; mNeedsRefresh = true; - updateParticipantName(participant); + updateName(participant); postEvent("add_participant", this, participant); } -void LLConversationItemSession::updateParticipantName(LLConversationItemParticipant* participant) +void LLConversationItemSession::updateName(LLConversationItemParticipant* participant) { EConversationType conversation_type = getType(); // We modify the session name only in the case of an ad-hoc session or P2P session, exit otherwise (nothing to do) @@ -181,11 +225,13 @@ void LLConversationItemSession::updateParticipantName(LLConversationItemParticip { return; } + // Avoid changing the default name if no participant present yet if (mChildren.size() == 0) { return; } + uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string if (conversation_type == CONV_SESSION_AD_HOC) { @@ -210,12 +256,14 @@ void LLConversationItemSession::updateParticipantName(LLConversationItemParticip } else if (conversation_type == CONV_SESSION_1_ON_1) { - // In the case of a P2P conversersation, we need to grab the name of the other participant in the session instance itself + // In the case of a P2P conversation, we need to grab the name of the other participant in the session instance itself // as we do not create participants for such a session. - LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(mUUID); - LLUUID participantID = conversationFloater->getOtherParticipantUUID(); - temp_uuids.push_back(participantID); + if (gAgentID != participant->getUUID()) + { + temp_uuids.push_back(participant->getUUID()); + } } + if (temp_uuids.size() != 0) { std::string new_session_name; @@ -229,7 +277,7 @@ void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* { removeChild(participant); mNeedsRefresh = true; - updateParticipantName(participant); + updateName(participant); postEvent("remove_participant", this, participant); } @@ -393,6 +441,18 @@ void LLConversationItemSession::dumpDebugData(bool dump_children) } } +// should be invoked only for P2P sessions +void LLConversationItemSession::onAvatarNameCache(const LLAvatarName& av_name) +{ + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + + renameItem(av_name.getDisplayName()); + postEvent("update_session", this, NULL); +} + // // LLConversationItemParticipant // @@ -401,8 +461,7 @@ LLConversationItemParticipant::LLConversationItemParticipant(std::string display LLConversationItem(display_name,uuid,root_view_model), mIsMuted(false), mIsModerator(false), - mDistToAgent(-1.0), - mAvatarNameCacheConnection() + mDistToAgent(-1.0) { mDisplayName = display_name; mConvType = CONV_PARTICIPANT; @@ -412,38 +471,12 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, LLConversationItem(uuid,root_view_model), mIsMuted(false), mIsModerator(false), - mDistToAgent(-1.0), - mAvatarNameCacheConnection() + mDistToAgent(-1.0) { mConvType = CONV_PARTICIPANT; } -LLConversationItemParticipant::~LLConversationItemParticipant() -{ - // Disconnect any previous avatar name cache connection to ensure - // that the callback method is not called after destruction - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } -} - -void LLConversationItemParticipant::fetchAvatarName() -{ - // Request the avatar name from the cache - llassert(getUUID().notNull()); - if (getUUID().notNull()) - { - // Disconnect any previous avatar name cache connection - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } - mAvatarNameCacheConnection = LLAvatarNameCache::get(getUUID(), boost::bind(&LLConversationItemParticipant::onAvatarNameCache, this, _2)); - } -} - -void LLConversationItemParticipant::updateAvatarName() +void LLConversationItemParticipant::updateName() { llassert(getUUID().notNull()); if (getUUID().notNull()) @@ -451,29 +484,33 @@ void LLConversationItemParticipant::updateAvatarName() LLAvatarName av_name; if (LLAvatarNameCache::get(getUUID(),&av_name)) { - updateAvatarName(av_name); + updateName(av_name); } } } void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) { - mAvatarNameCacheConnection.disconnect(); - updateAvatarName(av_name); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + + updateName(av_name); } -void LLConversationItemParticipant::updateAvatarName(const LLAvatarName& av_name) +void LLConversationItemParticipant::updateName(const LLAvatarName& av_name) { mName = av_name.getUserName(); mDisplayName = av_name.getDisplayName(); - mNeedsRefresh = true; + renameItem(mDisplayName); if (mParent != NULL) { LLConversationItemSession* parent_session = dynamic_cast<LLConversationItemSession*>(mParent); if (parent_session != NULL) { parent_session->requestSort(); - parent_session->updateParticipantName(this); + parent_session->updateName(this); postEvent("update_participant", parent_session, this); } } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 01b3850f5e..6aaea041e4 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -64,7 +64,7 @@ public: LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItem(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItem(LLFolderViewModelInterface& root_view_model); - virtual ~LLConversationItem() {} + virtual ~LLConversationItem(); // Stub those things we won't really be using in this conversation context virtual const std::string& getName() const { return mName; } @@ -132,27 +132,31 @@ public: void buildParticipantMenuOptions(menuentry_vec_t& items, U32 flags); + void fetchAvatarName(bool isParticipant = true); // fetch and update the avatar name + protected: + virtual void onAvatarNameCache(const LLAvatarName& av_name) {} + std::string mName; // Name of the session or the participant LLUUID mUUID; // UUID of the session or the participant EConversationType mConvType; // Type of conversation item bool mNeedsRefresh; // Flag signaling to the view that something changed for this item F64 mLastActiveTime; bool mDisplayModeratorOptions; -}; + boost::signals2::connection mAvatarNameCacheConnection; +}; class LLConversationItemSession : public LLConversationItem { public: LLConversationItemSession(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); - virtual ~LLConversationItemSession() {} /*virtual*/ bool hasChildren() const; LLPointer<LLUIImage> getIcon() const { return NULL; } void setSessionID(const LLUUID& session_id) { mUUID = session_id; mNeedsRefresh = true; } void addParticipant(LLConversationItemParticipant* participant); - void updateParticipantName(LLConversationItemParticipant* participant); + void updateName(LLConversationItemParticipant* participant); void removeParticipant(LLConversationItemParticipant* participant); void removeParticipant(const LLUUID& participant_id); void clearParticipants(); @@ -172,6 +176,8 @@ public: void dumpDebugData(bool dump_children = false); private: + /*virtual*/ void onAvatarNameCache(const LLAvatarName& av_name); + bool mIsLoaded; // true if at least one participant has been added to the session, false otherwise }; @@ -180,7 +186,6 @@ class LLConversationItemParticipant : public LLConversationItem public: LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); - virtual ~LLConversationItemParticipant(); virtual const std::string& getDisplayName() const { return mDisplayName; } @@ -195,8 +200,7 @@ public: virtual const bool getDistanceToAgent(F64& dist) const { dist = mDistToAgent; return (dist >= 0.0); } - void fetchAvatarName(); // fetch and update the avatar name - void updateAvatarName(); // get from the cache (do *not* fetch) and update the avatar name + void updateName(); // get from the cache (do *not* fetch) and update the avatar name LLConversationItemSession* getParentSession(); void dumpDebugData(); @@ -204,7 +208,7 @@ public: private: void onAvatarNameCache(const LLAvatarName& av_name); // callback used by fetchAvatarName - void updateAvatarName(const LLAvatarName& av_name); + void updateName(const LLAvatarName& av_name); bool mIsMuted; // default is false bool mIsModerator; // default is false diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 38528f18f0..a599fb51e1 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -380,7 +380,7 @@ void LLFloaterIMContainer::processParticipantsStyleUpdate() { LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); // Get the avatar name for this participant id from the cache and update the model - participant_model->updateAvatarName(); + participant_model->updateName(); // Next participant current_participant_model++; } @@ -1390,7 +1390,7 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& return NULL; } item->renameItem(display_name); - item->updateParticipantName(NULL); + item->updateName(NULL); mConversationsItems[uuid] = item; @@ -1419,6 +1419,11 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& } } + if (uuid.notNull() && im_sessionp->isP2PSessionType()) + { + item->fetchAvatarName(false); + } + // Do that too for the conversation dialog LLFloaterIMSessionTab *conversation_floater = (uuid.isNull() ? (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")) : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(uuid))); if (conversation_floater) -- cgit v1.2.3 From b5172de28fd6bb8a833cf93180d2d43dd9d4a073 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 8 Jan 2013 17:06:49 -0800 Subject: CHUI-660: Post code review changes --- indra/llui/llnotifications.cpp | 51 +++++++++++++--------- indra/llui/llnotifications.h | 4 +- .../newview/lldonotdisturbnotificationstorage.cpp | 2 +- 3 files changed, 34 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index ebdb4d5024..a5492b46f7 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -279,6 +279,18 @@ bool LLNotificationForm::hasElement(const std::string& element_name) const return false; } +void LLNotificationForm::getElements(LLSD& elements, S32 offset) +{ + //Finds elements that the template did not add + LLSD::array_const_iterator it = mFormData.beginArray() + offset; + + //Keeps track of only the dynamic elements + for(; it != mFormData.endArray(); ++it) + { + elements.append(*it); + } +} + bool LLNotificationForm::getElementEnabled(const std::string& element_name) const { for (LLSD::array_const_iterator it = mFormData.beginArray(); @@ -320,11 +332,6 @@ void LLNotificationForm::addElement(const std::string& type, const std::string& mFormData.append(element); } -void LLNotificationForm::addElement(const LLSD& element) -{ - mFormData.append(element); -} - void LLNotificationForm::append(const LLSD& sub_form) { if (sub_form.isArray()) @@ -508,21 +515,36 @@ LLNotification::LLNotification(const LLSDParamAdapter<Params>& p) : } -LLSD LLNotification::asLLSD() +LLSD LLNotification::asLLSD(bool excludeTemplateElements) { LLParamSDParser parser; Params p; p.id = mId; p.name = mTemplatep->mName; - p.form_elements = getForm()->asLLSD(); - p.substitutions = mSubstitutions; p.payload = mPayload; p.time_stamp = mTimestamp; p.expiry = mExpiresAt; p.priority = mPriority; + LLNotificationFormPtr templateForm = mTemplatep->mForm; + LLSD formElements = mForm->asLLSD(); + + //All form elements (dynamic or not) + if(!excludeTemplateElements) + { + p.form_elements = formElements; + } + //Only dynamic form elements (exclude template elements) + else if(templateForm->getNumElements() < formElements.size()) + { + LLSD dynamicElements; + //Offset to dynamic elements and store them + mForm->getElements(dynamicElements, templateForm->getNumElements()); + p.form_elements = dynamicElements; + } + if(mResponder) { p.functor.responder_sd = mResponder->asLLSD(); @@ -823,18 +845,7 @@ void LLNotification::init(const std::string& template_name, const LLSD& form_ele //mSubstitutions["_ARGS"] = get_all_arguments_as_text(mSubstitutions); mForm = LLNotificationFormPtr(new LLNotificationForm(*mTemplatep->mForm)); - - //Prevents appending elements(buttons) that the template already had - if(form_elements.isArray() - && mForm->getNumElements() < form_elements.size()) - { - LLSD::array_const_iterator it = form_elements.beginArray() + mForm->getNumElements();; - - for(; it != form_elements.endArray(); ++it) - { - mForm->addElement(*it); - } - } + mForm->append(form_elements); // apply substitution to form labels mForm->formatElements(mSubstitutions); diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 96e0a86b7f..236c2a42d1 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -242,11 +242,11 @@ public: S32 getNumElements() { return mFormData.size(); } LLSD getElement(S32 index) { return mFormData.get(index); } LLSD getElement(const std::string& element_name); + void getElements(LLSD& elements, S32 offset = 0); bool hasElement(const std::string& element_name) const; bool getElementEnabled(const std::string& element_name) const; void setElementEnabled(const std::string& element_name, bool enabled); void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD(), bool enabled = true); - void addElement(const LLSD &element); void formatElements(const LLSD& substitutions); // appends form elements from another form serialized as LLSD void append(const LLSD& sub_form); @@ -457,7 +457,7 @@ public: // ["time"] = time at which notification was generated; // ["expiry"] = time at which notification expires; // ["responseFunctor"] = name of registered functor that handles responses to notification; - LLSD asLLSD(); + LLSD asLLSD(bool excludeTemplateElements = false); const LLNotificationFormPtr getForm(); void updateForm(const LLNotificationFormPtr& form); diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 9bb2f27a46..ac41a3804f 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -77,7 +77,7 @@ void LLDoNotDisturbNotificationStorage::saveNotifications() if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && !notificationPtr->isExpired()) { - data.append(notificationPtr->asLLSD()); + data.append(notificationPtr->asLLSD(true)); } } -- cgit v1.2.3 From 4ef1181cdcb03a08fbce8d774cd85ef914bef8f3 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 8 Jan 2013 21:46:00 -0800 Subject: CHUI-659 : Fixed : Reimplemented open selection on hitting return the right way --- indra/llui/llfolderview.cpp | 86 -------------------------------------- indra/llui/llfolderview.h | 4 -- indra/llui/llfolderviewmodel.h | 2 +- indra/newview/llinventorypanel.cpp | 20 ++++++++- indra/newview/llinventorypanel.h | 1 + 5 files changed, 20 insertions(+), 93 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 7ae79d94fe..324142f6c3 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -275,17 +275,6 @@ BOOL LLFolderView::canFocusChildren() const void LLFolderView::addFolder( LLFolderViewFolder* folder) { LLFolderViewFolder::addFolder(folder); - - // TODO RN: enforce sort order of My Inventory followed by Library - //mFolders.remove(folder); - //if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) - //{ - // mFolders.push_back(folder); - //} - //else - //{ - // mFolders.insert(mFolders.begin(), folder); - //} } void LLFolderView::closeAllFolders() @@ -793,76 +782,6 @@ void LLFolderView::removeSelectedItems() } } -// TODO RN: abstract -// open the selected item. -void LLFolderView::openSelectedItems( void ) -{ - //TODO RN: get working again - //if(getVisible() && getEnabled()) - //{ - // if (mSelectedItems.size() == 1) - // { - // mSelectedItems.front()->openItem(); - // } - // else - // { - // LLMultiPreview* multi_previewp = new LLMultiPreview(); - // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - // selected_items_t::iterator item_it; - // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - // { - // // IT_{OBJECT,ATTACHMENT} creates LLProperties - // // floaters; others create LLPreviews. Put - // // each one in the right type of container. - // LLFolderViewModelItemInventory* listener = static_cast<LLFolderViewModelItemInventory*>((*item_it)->getViewModelItem()); - // bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); - // if (is_prop) - // LLFloater::setFloaterHost(multi_propertiesp); - // else - // LLFloater::setFloaterHost(multi_previewp); - // listener->openItem(); - // } - - // LLFloater::setFloaterHost(NULL); - // // *NOTE: LLMulti* will safely auto-delete when open'd - // // without any children. - // multi_previewp->openFloater(LLSD()); - // multi_propertiesp->openFloater(LLSD()); - // } - //} - } - -void LLFolderView::propertiesSelectedItems( void ) -{ - //TODO RN: get working again - //if(getVisible() && getEnabled()) - //{ - // if (mSelectedItems.size() == 1) - // { - // LLFolderViewItem* folder_item = mSelectedItems.front(); - // if(!folder_item) return; - // folder_item->getViewModelItem()->showProperties(); - // } - // else - // { - // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - // LLFloater::setFloaterHost(multi_propertiesp); - - // selected_items_t::iterator item_it; - // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - // { - // (*item_it)->getViewModelItem()->showProperties(); - // } - - // LLFloater::setFloaterHost(NULL); - // multi_propertiesp->openFloater(LLSD()); - // } - //} - } - - void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) { if ((mAutoOpenItems.check() == item) || @@ -1151,11 +1070,6 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) mSearchString.clear(); handled = TRUE; } - else - { - LLFolderView::openSelectedItems(); - handled = TRUE; - } } break; diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 2ee7417240..a6e0a3b4c0 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -163,10 +163,6 @@ public: // Deletion functionality void removeSelectedItems(); - // Open the selected item - void openSelectedItems( void ); - void propertiesSelectedItems( void ); - void autoOpenItem(LLFolderViewFolder* item); void closeAutoOpenedFolders(); BOOL autoOpenTest(LLFolderViewFolder* item); diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 5837052565..1b61212c0e 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -127,7 +127,7 @@ public: virtual bool startDrag(std::vector<LLFolderViewModelItem*>& items) = 0; }; -// This is am abstract base class that users of the folderview classes +// This is an abstract base class that users of the folderview classes // would use to bridge the folder view with the underlying data class LLFolderViewModelItem : public LLRefCount { diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 81e7f166e1..25dc365467 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -684,8 +684,9 @@ void LLInventoryPanel::initializeViews() } else { - buildNewViews(gInventory.getRootFolderID()); - buildNewViews(gInventory.getLibraryRootFolderID()); + // Default case: always add "My Inventory" first, "Library" second + buildNewViews(gInventory.getRootFolderID()); // My Inventory + buildNewViews(gInventory.getLibraryRootFolderID()); // Library } gIdleCallbacks.addFunction(idle, this); @@ -1354,6 +1355,21 @@ void LLInventoryPanel::doToSelected(const LLSD& userdata) return; } +BOOL LLInventoryPanel::handleKeyHere( KEY key, MASK mask ) +{ + BOOL handled = FALSE; + switch (key) + { + case KEY_RETURN: + // Open selected items if enter key hit on the inventory panel + if (mask == MASK_NONE) + { + LLInventoryAction::doToSelected(mInventory, mFolderRoot, "open"); + handled = TRUE; + } + } + return handled; +} /************************************************************************/ /* Recent Inventory Panel related class */ diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 9639086c11..6eb85fbad2 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -143,6 +143,7 @@ public: // LLView methods void draw(); + /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); BOOL handleHover(S32 x, S32 y, MASK mask); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, -- cgit v1.2.3 From 3cf2d8e9eac215024bc216958b0920e61aa25de1 Mon Sep 17 00:00:00 2001 From: maximbproductengine <maximbproductengine@lindenlab.com> Date: Wed, 9 Jan 2013 10:41:09 +0200 Subject: CHUI-665 (Change "Open conversation log" to "Conversation log..." in communication floater view/sort menu) --- indra/newview/skins/default/xui/en/menu_participant_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml index 33d7bd7c01..2f2bafb95d 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_view.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -76,7 +76,7 @@ parameter="privacy_preferences" /> </menu_item_call> <menu_item_check - label="Open conversation log" + label="Conversation log..." name="Conversation" visible="true"> <menu_item_check.on_check -- cgit v1.2.3 From bb05a29374b2c9691937ccb15cdbff466fd775f1 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Wed, 9 Jan 2013 15:08:58 +0200 Subject: CHUI-638 FIXED Don't force button and widget to flash if the object is muted. --- indra/newview/llimview.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 0011f54175..0326235d37 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -225,12 +225,17 @@ void on_new_message(const LLSD& msg) //User is not focused on conversation containing the message if(session_floater_not_focused) { - im_box->flashConversationItemWidget(session_id, true); - + if(!LLMuteList::getInstance()->isMuted(participant_id)) + { + im_box->flashConversationItemWidget(session_id, true); + } //The conversation floater isn't focused/open if(conversation_floater_not_focused) { - gToolBarView->flashCommand(LLCommandId("chat"), true); + if(!LLMuteList::getInstance()->isMuted(participant_id)) + { + gToolBarView->flashCommand(LLCommandId("chat"), true); + } //Show IM toasts (upper right toasts) // Skip toasting for system messages and for nearby chat -- cgit v1.2.3 From 9d70bc259a02a0f6dcc6cff1c95a34353e0f1e59 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 9 Jan 2013 12:45:34 -0800 Subject: CHUI-652 : Fixed : Skip the bogus fetching test when adding objects to object content. --- indra/newview/llviewerobject.cpp | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 2fe6cd578b..52f73d6c43 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2869,23 +2869,6 @@ void LLViewerObject::updateInventory( U8 key, bool is_new) { - LLMemType mt(LLMemType::MTYPE_OBJECT); - - std::list<LLUUID>::iterator begin = mPendingInventoryItemsIDs.begin(); - std::list<LLUUID>::iterator end = mPendingInventoryItemsIDs.end(); - - bool is_fetching = std::find(begin, end, item->getAssetUUID()) != end; - bool is_fetched = getInventoryItemByAsset(item->getAssetUUID()) != NULL; - - if (is_fetched || is_fetching) - { - return; - } - else - { - mPendingInventoryItemsIDs.push_back(item->getAssetUUID()); - } - // This slices the object into what we're concerned about on the // viewer. The simulator will take the permissions and transfer // ownership. -- cgit v1.2.3 From 6a30c4c3c54f3d70d1a10fb76e7c81cd5e36a524 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 9 Jan 2013 13:30:14 -0800 Subject: CHUI-669: Upon DND mode exit, no longer flash IM messages that were stored during DND mode. --- indra/newview/llimview.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 0326235d37..a3c338831c 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -129,11 +129,7 @@ void process_dnd_im(const LLSD& notification) false); //will need slight refactor to retrieve whether offline message or not (assume online for now) } - //For now always flash conversation line item - LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); - im_box->flashConversationItemWidget(sessionID, true); - - //And flash toolbar button + //Flash toolbar button for now, eventually the user's preference will be taken into account gToolBarView->flashCommand(LLCommandId("chat"), true); } -- cgit v1.2.3 From 41d5f820ea1859493b7f14d9d81b145a6a3b38b6 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 9 Jan 2013 14:30:10 -0800 Subject: CHUI-670: Prevent flashing of 'Chat' FUI button while in DND mode and receive IM. --- indra/newview/llimview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index a3c338831c..067f0d1993 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -228,7 +228,8 @@ void on_new_message(const LLSD& msg) //The conversation floater isn't focused/open if(conversation_floater_not_focused) { - if(!LLMuteList::getInstance()->isMuted(participant_id)) + if(!LLMuteList::getInstance()->isMuted(participant_id) + && !gAgent.isDoNotDisturb()) { gToolBarView->flashCommand(LLCommandId("chat"), true); } -- cgit v1.2.3 From 60eaa8875df45f023c3bf0fb82863b05cb5a090f Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 9 Jan 2013 19:10:41 -0800 Subject: CHUI-652 : Fixed : Maintain multi selection consistent when click and drag an already selected item (drag multi select was broken) --- indra/llui/llfolderviewitem.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index b7165f68b7..42e5a6debf 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -506,13 +506,10 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) } make_ui_sound("UISndClick"); } - //Just re-select the item since it is clicked without ctrl or shift - else if(!(mask & (MASK_CONTROL | MASK_SHIFT))) - { - getRoot()->setSelection(this, FALSE); - } else { + // If selected, we reserve the decision of deselecting/reselecting to the mouse up moment. + // This is necessary so we maintain selection consistent when starting a drag. mSelectPending = TRUE; } -- cgit v1.2.3 From be3cfd872be89f30012d66a4b64071e4fe2568cf Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 9 Jan 2013 20:20:32 -0800 Subject: CHUI-649 : WIP : Cleanup code to make it readable --- indra/llui/llfolderviewitem.cpp | 8 ++++---- indra/newview/llinventorybridge.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 42e5a6debf..6d3b883b09 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -409,7 +409,7 @@ void LLFolderViewItem::selectItem(void) BOOL LLFolderViewItem::isMovable() { return getViewModelItem()->isItemMovable(); - } +} BOOL LLFolderViewItem::isRemovable() { @@ -438,19 +438,19 @@ BOOL LLFolderViewItem::remove() return FALSE; } return getViewModelItem()->removeItem(); - } +} // Build an appropriate context menu for the item. void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) { getViewModelItem()->buildContextMenu(menu, flags); - } +} void LLFolderViewItem::openItem( void ) { if (mAllowOpen) { - getViewModelItem()->openItem(); + getViewModelItem()->openItem(); } } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index cb6290368c..837870ae27 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -511,8 +511,10 @@ BOOL LLInvFVBridge::isClipboardPasteable() const // Each item must be copyable to be pastable LLItemBridge item_br(mInventoryPanel.get(), mRoot, item_id); if (!item_br.isItemCopyable()) - return FALSE; - } + { + return FALSE; + } + } return TRUE; } -- cgit v1.2.3 From bad4eda43677d26b88c86f4381c6a0f7436f0daf Mon Sep 17 00:00:00 2001 From: maximbproductengine <maximbproductengine@lindenlab.com> Date: Thu, 10 Jan 2013 13:41:47 +0200 Subject: CHUI-663 (Right click menus on participants inactive in conversation floater for torn off conversation) --- indra/newview/llfloaterimcontainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 82563b8736..a21cbf2bb2 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -906,7 +906,7 @@ const LLConversationItem * LLFloaterIMContainer::getCurSelectedViewModelItem() mConversationsRoot->getCurSelectedItem()->getViewModelItem()) { LLFloaterIMSessionTab *selected_session_floater = LLFloaterIMSessionTab::getConversation(mSelectedSession); - if (selected_session_floater && !selected_session_floater->getHost()) + if (selected_session_floater && !selected_session_floater->getHost() && selected_session_floater->getCurSelectedViewModelItem()) { conversation_item = selected_session_floater->getCurSelectedViewModelItem(); } -- cgit v1.2.3 From b5b44ddf175e46379aa20b79b0abedab6bc05e2e Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 10 Jan 2013 11:10:41 -0800 Subject: CHUI-649 : Fixed : Added the contextual menu to in build content tab --- indra/newview/llinventorypanel.cpp | 4 ++-- indra/newview/llpanelobjectinventory.cpp | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 25dc365467..c4918f0a31 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -181,7 +181,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id ) LLAssetType::AT_CATEGORY, LLInventoryType::IT_CATEGORY, this, - &mInventoryViewModel, + &mInventoryViewModel, NULL, root_id); p.view_model = &mInventoryViewModel; @@ -218,7 +218,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) mFolderRoot = createFolderRoot(root_id); addItemID(root_id, mFolderRoot); -} + } mCommitCallbackRegistrar.popScope(); mFolderRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 527aefe821..7555ac7b2c 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1569,6 +1569,8 @@ void LLPanelObjectInventory::reset() p.folder_indentation = -14; // subtract space normally reserved for folder expanders p.view_model = &mInventoryViewModel; p.root = NULL; + p.options_menu = "menu_inventory.xml"; + mFolders = LLUICtrlFactory::create<LLFolderView>(p); mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); -- cgit v1.2.3 From 2e3113863022a21d2145cc23992d6afab9c6fbcd Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 10 Jan 2013 20:19:26 -0800 Subject: CHUI-672 : Fixed : LLMultiFloater members need to be initialized in constructor. --- indra/llui/llmultifloater.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index 59faabd482..179b251cdb 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -37,10 +37,12 @@ // LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params) - : LLFloater(key) - , mTabContainer(NULL) - , mTabPos(LLTabContainer::TOP) - , mAutoResize(TRUE) + : LLFloater(key), + mTabContainer(NULL), + mTabPos(LLTabContainer::TOP), + mAutoResize(TRUE), + mOrigMinWidth(params.min_width), + mOrigMinHeight(params.min_height) { } -- cgit v1.2.3 From 16082462a4d355509338ed28e396c8c81a20712a Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Fri, 11 Jan 2013 15:32:05 +0200 Subject: CHUI-650 FIXED Set focus to floater when bringToFront() is called(even if it's already in front). --- indra/llui/llfloater.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 8f9be5285d..e0e830f742 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2394,6 +2394,7 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) { if (mFrontChild == child) { + child->setFocus(true); return; } -- cgit v1.2.3 From 88639dd862be6558f0777e99c571dcd807efa4ba Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 11 Jan 2013 17:28:43 -0800 Subject: CHUI-650 : Revert : revert the change as it creates infinite recursive calls --- indra/llui/llfloater.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index e0e830f742..8f9be5285d 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2394,7 +2394,6 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) { if (mFrontChild == child) { - child->setFocus(true); return; } -- cgit v1.2.3 From 23ffb7db1bb065b5afbdcb94eab57720d604ae8d Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Sat, 12 Jan 2013 01:51:43 +0200 Subject: CHUI-618 ADD FIX User sees no indication of offline messages received with conversation log preference turned off: changed in accordance with a new requirements (open conv. floater instead flashing) --- indra/newview/llimview.cpp | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 067f0d1993..da811535e5 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -129,8 +129,14 @@ void process_dnd_im(const LLSD& notification) false); //will need slight refactor to retrieve whether offline message or not (assume online for now) } - //Flash toolbar button for now, eventually the user's preference will be taken into account - gToolBarView->flashCommand(LLCommandId("chat"), true); + // open conversation floater + LLFloaterIMContainer* container_floater = + LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + if (container_floater && !(container_floater->isFrontmost())) + { + container_floater->openFloater(); + container_floater->setFrontmost(TRUE); + } } @@ -2529,25 +2535,6 @@ void LLIMMgr::addMessage( new_session_id = computeSessionID(dialog, other_participant_id); } - // Open conversation log if offline messages are present and user allows a Call Log - if (is_offline_msg) - { - if (gSavedSettings.getBOOL("KeepConversationLogTranscripts")) - { - LLFloaterConversationLog* floater_log = - LLFloaterReg::getTypedInstance<LLFloaterConversationLog>("conversation"); - if (floater_log && !(floater_log->isFrontmost())) - { - floater_log->openFloater(); - floater_log->setFrontmost(TRUE); - } - } - else - { - gToolBarView->flashCommand(LLCommandId("chat"), true); - } - } - //*NOTE session_name is empty in case of incoming P2P sessions std::string fixed_session_name = from; bool name_is_setted = false; @@ -2614,6 +2601,19 @@ void LLIMMgr::addMessage( { LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg); } + + // Open conversation floater if offline messages are present + if (is_offline_msg) + { + LLFloaterIMContainer* container_floater = + LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + if (container_floater && !(container_floater->isFrontmost())) + { + container_floater->openFloater(); + container_floater->setFrontmost(TRUE); + } + } + } void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args) -- cgit v1.2.3 From 69497e645bbefe85d83e85bb353e5fb719263877 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 11 Jan 2013 18:20:29 -0800 Subject: CHUI-668: Not fully complete but as of this commit, have functionality to use the user's most intrusive chat notification upon exiting from DND mode with IM's. Also if in DND mode, clicking on a conversation line item or floater, will flush the DND notifications system of storing that conversation. This way upon existing DND mode already responded conversations won't be notified to the user. --- indra/newview/llcommunicationchannel.cpp | 8 +++- indra/newview/llcommunicationchannel.h | 1 + .../newview/lldonotdisturbnotificationstorage.cpp | 53 ++++++++++++++++++++++ indra/newview/lldonotdisturbnotificationstorage.h | 1 + indra/newview/llfloaterimcontainer.cpp | 10 ++++ indra/newview/llfloaterpreference.cpp | 30 ++++++++++++ indra/newview/llfloaterpreference.h | 1 + indra/newview/llimview.cpp | 42 +++++++++++++++-- 8 files changed, 142 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llcommunicationchannel.cpp b/indra/newview/llcommunicationchannel.cpp index 4b0a70ffd8..a99047c163 100644 --- a/indra/newview/llcommunicationchannel.cpp +++ b/indra/newview/llcommunicationchannel.cpp @@ -67,12 +67,18 @@ void LLCommunicationChannel::clearHistory() mHistory.clear(); } +void LLCommunicationChannel::removeItem(history_list_t::const_iterator itemToRemove) +{ + mHistory.erase(itemToRemove); +} + void LLCommunicationChannel::onFilterFail(LLNotificationPtr pNotificationPtr) { std::string notificationType = pNotificationPtr->getType(); if ((notificationType == "groupnotify") || (notificationType == "offer") - || (notificationType == "notifytoast")) + || (notificationType == "notifytoast") + && !pNotificationPtr->isCancelled()) { mHistory.insert(std::make_pair<LLDate, LLNotificationPtr>(pNotificationPtr->getDate(), pNotificationPtr)); } diff --git a/indra/newview/llcommunicationchannel.h b/indra/newview/llcommunicationchannel.h index 0e15e1cd15..c07933118d 100644 --- a/indra/newview/llcommunicationchannel.h +++ b/indra/newview/llcommunicationchannel.h @@ -48,6 +48,7 @@ public: history_list_t::const_iterator endHistory() const; void clearHistory(); + void removeItem(history_list_t::const_iterator itemToRemove); protected: virtual void onFilterFail(LLNotificationPtr pNotificationPtr); diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index ac41a3804f..764da25b08 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -41,6 +41,8 @@ #include "llsingleton.h" #include "lluuid.h" +extern void useMostItrusiveIMNotification(); + LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() : LLSingleton<LLDoNotDisturbNotificationStorage>() , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")) @@ -103,15 +105,22 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() } LLNotifications& instance = LLNotifications::instance(); + bool imToastExists = false; for (LLSD::array_const_iterator notification_it = data.beginArray(); notification_it != data.endArray(); ++notification_it) { LLSD notification_params = *notification_it; + const std::string notificationName = notification_params["name"].asString(); const LLUUID& notificationID = notification_params["id"]; LLNotificationPtr notification = instance.find(notificationID); + if(notificationName == "IMToast") + { + imToastExists = true; + } + //Notification already exists in notification pipeline (same instance of app running) if (notification) { @@ -138,6 +147,11 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() } } + if(imToastExists) + { + useMostItrusiveIMNotification(); + } + // Clear the communication channel history and rewrite the save file to empty it as well LLNotificationChannelPtr channelPtr = getCommunicationChannel(); LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get()); @@ -154,6 +168,45 @@ LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChan return channelPtr; } +void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& session_id) +{ + LLNotifications& instance = LLNotifications::instance(); + LLNotificationChannelPtr channelPtr = getCommunicationChannel(); + LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get()); + LLNotificationPtr notification; + LLSD substitutions; + LLUUID notificationSessionID; + LLCommunicationChannel::history_list_t::const_iterator it; + std::vector<LLCommunicationChannel::history_list_t::const_iterator> itemsToRemove; + + //Find notification with the matching session id + for (it = commChannel->beginHistory(); + it != commChannel->endHistory(); + ++it) + { + notification = it->second; + substitutions = notification->getSubstitutions(); + notificationSessionID = substitutions["SESSION_ID"].asUUID(); + + if(session_id == notificationSessionID) + { + itemsToRemove.push_back(it); + } + } + + //Remove the notification + while(itemsToRemove.size()) + { + it = itemsToRemove.back(); + notification = it->second; + commChannel->removeItem(it); + //instance.cancel triggers onChannelChanged to be called within LLNotificationChannelBase::updateItem (which save changes to the .xml file) + //but this means that saveNotifications write a file each time as well, BAD! Will find a way to prevent this. + instance.cancel(notification); + itemsToRemove.pop_back(); + } +} + bool LLDoNotDisturbNotificationStorage::onChannelChanged(const LLSD& pPayload) { diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h index 60bcd89ec3..8edb8569b4 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.h +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -45,6 +45,7 @@ public: void saveNotifications(); void loadNotifications(); + void removeIMNotification(const LLUUID& session_id); protected: diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a17b89af0d..376144951d 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -39,6 +39,7 @@ #include "llavatariconctrl.h" #include "llavatarnamecache.h" #include "llcallbacklist.h" +#include "lldonotdisturbnotificationstorage.h" #include "llgroupactions.h" #include "llgroupiconctrl.h" #include "llflashtimer.h" @@ -1291,6 +1292,10 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool if (widget && widget->getParentFolder()) { widget->getParentFolder()->setSelection(widget, FALSE, FALSE); + if(gAgent.isDoNotDisturb()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); + } } } @@ -1312,6 +1317,11 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool // Switch to the conversation floater that is being selected selectFloater(session_floater); } + + if(gAgent.isDoNotDisturb()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); + } } // Set the focus on the selected floater diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 3d4a1c44d8..9c836489f3 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1624,6 +1624,36 @@ void LLFloaterPreference::selectChatPanel() selectPanel("chat"); } +S32 LLFloaterPreference::getHighestNotificationIndex() //change this name +{ + static const S32 comboBoxNamesLength = 5; + static std::string comboBoxNames[comboBoxNamesLength] = {"NearbyChatOptions", + "FriendIMOptions", + "NonFriendIMOptions", + "ConferenceIMOptions", + "GroupChatOptions"}; + S32 selectedIndex; + S32 priorityindex = 3; + LLComboBox * comboBox; + + for(S32 i = 0; i < comboBoxNamesLength; ++i) + { + comboBox = getChild<LLComboBox>(comboBoxNames[i]); + + if(comboBox) + { + selectedIndex = comboBox->getCurrentIndex(); + + if(selectedIndex < priorityindex) + { + priorityindex = selectedIndex; + } + } + } + + return priorityindex; +} + //------------------------------Updater--------------------------------------- static bool handleBandwidthChanged(const LLSD& newvalue) diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 37a531e99e..3d5d49294e 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -86,6 +86,7 @@ public: void saveAvatarProperties( void ); void selectPrivacyPanel(); void selectChatPanel(); + S32 getHighestNotificationIndex(); protected: void onBtnOK(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 067f0d1993..e513d2e6d1 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -52,6 +52,7 @@ #include "llchat.h" #include "llfloaterimsession.h" #include "llfloaterimcontainer.h" +#include "llfloaterpreference.h" #include "llgroupiconctrl.h" #include "llmd5.h" #include "llmutelist.h" @@ -128,11 +129,46 @@ void process_dnd_im(const LLSD& notification) false, false); //will need slight refactor to retrieve whether offline message or not (assume online for now) } - - //Flash toolbar button for now, eventually the user's preference will be taken into account - gToolBarView->flashCommand(LLCommandId("chat"), true); } +void useMostItrusiveIMNotification() +{ + LLFloaterPreference * instance = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + + //conv. floater is closed + bool conversation_floater_is_closed = + !( im_box + && im_box->isInVisibleChain() + && !im_box->isMinimized()); + + //conversation floater not focused (visible or not) + bool conversation_floater_not_focused = + conversation_floater_is_closed || !im_box->hasFocus(); + + switch(instance->getHighestNotificationIndex()) + { + //Highest priority to lowest (cases correspond to options in drop down box inside Preferences->Chat) + + //open conversation floater + case 0: + LLFloaterReg::showInstance("im_container"); + break; + //pop up message + case 1: + //flash toolbar button + case 2: + if(conversation_floater_not_focused) + { + gToolBarView->flashCommand(LLCommandId("chat"), true); + } + break; + } + } + +} static void on_avatar_name_cache_toast(const LLUUID& agent_id, const LLAvatarName& av_name, -- cgit v1.2.3 From e42755dd16195244a6743fc3970f24fec08f03b9 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 11 Jan 2013 19:43:12 -0800 Subject: CHUI-668: Now when exiting DND mode, the user's most intrusive notification will be used to notify that user (if received IM's during DND mode). Nearby chat messages/settings are ignored. --- indra/newview/llfloaterpreference.cpp | 11 +++---- indra/newview/llimview.cpp | 59 ++++++++++++++++++++++------------- 2 files changed, 43 insertions(+), 27 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 9c836489f3..4c74d3a8ef 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1626,12 +1626,11 @@ void LLFloaterPreference::selectChatPanel() S32 LLFloaterPreference::getHighestNotificationIndex() //change this name { - static const S32 comboBoxNamesLength = 5; - static std::string comboBoxNames[comboBoxNamesLength] = {"NearbyChatOptions", - "FriendIMOptions", - "NonFriendIMOptions", - "ConferenceIMOptions", - "GroupChatOptions"}; + static const S32 comboBoxNamesLength = 4; + static std::string comboBoxNames[comboBoxNamesLength] = {"FriendIMOptions", + "NonFriendIMOptions", + "ConferenceIMOptions", + "GroupChatOptions"}; S32 selectedIndex; S32 priorityindex = 3; LLComboBox * comboBox; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index e513d2e6d1..b29c1484cc 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -134,36 +134,32 @@ void process_dnd_im(const LLSD& notification) void useMostItrusiveIMNotification() { LLFloaterPreference * instance = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences"); - if (instance) - { - LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); - //conv. floater is closed - bool conversation_floater_is_closed = - !( im_box - && im_box->isInVisibleChain() - && !im_box->isMinimized()); + //conv. floater is closed + bool conversation_floater_is_closed = + !( im_box + && im_box->isInVisibleChain() + && !im_box->isMinimized()); - //conversation floater not focused (visible or not) - bool conversation_floater_not_focused = - conversation_floater_is_closed || !im_box->hasFocus(); + //conversation floater not focused (visible or not) + bool conversation_floater_not_focused = + conversation_floater_is_closed || !im_box->hasFocus(); + //Only notify user of stored DND IM messages when conversation floater isn't focused + if (instance && conversation_floater_not_focused) + { switch(instance->getHighestNotificationIndex()) { - //Highest priority to lowest (cases correspond to options in drop down box inside Preferences->Chat) - //open conversation floater case 0: - LLFloaterReg::showInstance("im_container"); + LLFloaterReg::showInstance("im_container"); break; //pop up message case 1: //flash toolbar button case 2: - if(conversation_floater_not_focused) - { - gToolBarView->flashCommand(LLCommandId("chat"), true); - } + gToolBarView->flashCommand(LLCommandId("chat"), true); break; } } @@ -284,13 +280,22 @@ void on_new_message(const LLSD& msg) { if (conversation_floater_not_focused) { - if(session_floater_not_focused) + if(session_floater_not_focused && !gAgent.isDoNotDisturb()) { //User is not focused on conversation containing the message gToolBarView->flashCommand(LLCommandId("chat"), true); } im_box->flashConversationItemWidget(session_id, true); + + //If a DND message, allow notification to be stored so upon DND exit + //useMostItrusiveIMNotification will be called to notify user a message exists + if(session_id.notNull() + && participant_id.notNull() + && gAgent.isDoNotDisturb()) + { + LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); + } } } @@ -302,8 +307,20 @@ void on_new_message(const LLSD& msg) //Flash line item im_box->flashConversationItemWidget(session_id, true); - //Surface conversations floater - LLFloaterReg::showInstance("im_container"); + if(!gAgent.isDoNotDisturb()) + { + //Surface conversations floater + LLFloaterReg::showInstance("im_container"); + } + + //If in DND mode, allow notification to be stored so upon DND exit + //useMostItrusiveIMNotification will be called to notify user a message exists + if(session_id.notNull() + && participant_id.notNull() + && gAgent.isDoNotDisturb()) + { + LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); + } } } } -- cgit v1.2.3 From e44677ee79a38741d641fae74ba661b7e6b59794 Mon Sep 17 00:00:00 2001 From: maximbproductengine <maximbproductengine@lindenlab.com> Date: Mon, 14 Jan 2013 21:48:37 +0200 Subject: CHUI-662 (Multi select across conversations can result in (???) (???) in the conversation list) --- indra/newview/llfloaterimcontainer.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a17b89af0d..f825e253d4 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -893,7 +893,18 @@ void LLFloaterIMContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids) for (; it != it_end; ++it) { conversationItem = static_cast<LLConversationItem *>((*it)->getViewModelItem()); - selected_uuids.push_back(conversationItem->getUUID()); + + //When a one-on-one conversation exists, retrieve the participant id from the conversation floater + if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + { + LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(conversationItem->getUUID()); + LLUUID participant_id = conversation_floaterp->getOtherParticipantUUID(); + selected_uuids.push_back(participant_id); + } + else + { + selected_uuids.push_back(conversationItem->getUUID()); + } } } @@ -929,17 +940,7 @@ void LLFloaterIMContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) return; } - if (conversation_item->getType() == LLConversationItem::CONV_PARTICIPANT) - { - getSelectedUUIDs(selected_uuids); - } - //When a one-on-one conversation exists, retrieve the participant id from the conversation floater - else if(conversation_item->getType() == LLConversationItem::CONV_SESSION_1_ON_1) - { - LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(conversation_item->getUUID()); - LLUUID participant_id = conversation_floaterp->getOtherParticipantUUID(); - selected_uuids.push_back(participant_id); - } + getSelectedUUIDs(selected_uuids); } void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec_t& selectedIDS) -- cgit v1.2.3 From cefcdd445b6bad0e2382d848cd73b20a1a51cc01 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 14 Jan 2013 15:26:59 -0800 Subject: CHUI-458 : WIP : Allow change of the general conversations panel when the selected conversation needs it (e.g. P2P is typing) --- indra/newview/llfloaterimcontainer.cpp | 6 ++++++ indra/newview/llfloaterimcontainer.h | 1 + indra/newview/llfloaterimsession.cpp | 2 +- indra/newview/llfloaterimsession.h | 2 ++ 4 files changed, 10 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index f825e253d4..cf81a2b046 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -238,6 +238,9 @@ BOOL LLFloaterIMContainer::postBuild() // Init the sort order now that the root had been created setSortOrder(LLConversationSort(gSavedSettings.getU32("ConversationSortOrder"))); + // Keep the xml set title around for when we have to overwrite it + mGeneralTitle = getTitle(); + mInitialized = true; // Add callbacks: @@ -515,6 +518,9 @@ void LLFloaterIMContainer::draw() current_participant_model++; } + // is P2P? Test if we can change the title + LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(current_session->getUUID()); + setTitle(conversation_floaterp && conversation_floaterp->hasSpecialTitle() ? conversation_floaterp->getSpecialTitle() : mGeneralTitle); } LLFloater::draw(); diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 85d950c58b..06af6c7b51 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -169,6 +169,7 @@ private: bool mInitialized; LLUUID mSelectedSession; + std::string mGeneralTitle; // Conversation list implementation public: diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index d36b138c21..931ee0dc66 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -705,7 +705,7 @@ BOOL LLFloaterIMSession::getVisible() // getVisible() returns TRUE when Tabbed IM window is minimized. visible = is_active && !im_container->isMinimized() && im_container->getVisible(); - } + } } else { diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index 6a2f4b29eb..7239481e56 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -132,6 +132,8 @@ public: static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); static floater_showed_signal_t sIMFloaterShowedSignal; + bool hasSpecialTitle() { return mOtherTyping; } + std::string getSpecialTitle() { return getTitle(); } private: /*virtual*/ void refresh(); -- cgit v1.2.3 From 0e90e94a4d5cbac2d186f0056821a51078e8d1bd Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 14 Jan 2013 17:23:06 -0800 Subject: CHUI-668: The user's most intrusive notification is not used anymore when coming out of DND mode with IMs. Adjusted code to just open the converseation floater (which was changed also in a prior fix by PE). --- indra/newview/lldonotdisturbnotificationstorage.cpp | 13 +++++++++++++ indra/newview/llimview.cpp | 19 +++---------------- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 5cc0ab2081..12ff308a77 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -33,6 +33,7 @@ #include "lldir.h" #include "llerror.h" #include "llfasttimer_class.h" +#include "llfloaterreg.h" #include "llnotifications.h" #include "llnotificationhandler.h" #include "llnotificationstorage.h" @@ -103,6 +104,7 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() } LLNotifications& instance = LLNotifications::instance(); + bool imToastExists = false; for (LLSD::array_const_iterator notification_it = data.beginArray(); notification_it != data.endArray(); @@ -110,8 +112,14 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() { LLSD notification_params = *notification_it; const LLUUID& notificationID = notification_params["id"]; + std::string notificationName = notification_params["name"]; LLNotificationPtr notification = instance.find(notificationID); + if(notificationName == "IMToast") + { + imToastExists = true; + } + //Notification already exists in notification pipeline (same instance of app running) if (notification) { @@ -138,6 +146,11 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() } } + if(imToastExists) + { + LLFloaterReg::showInstance("im_container"); + } + // Clear the communication channel history and rewrite the save file to empty it as well LLNotificationChannelPtr channelPtr = getCommunicationChannel(); LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get()); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 32b4afcfef..ff171fc0f8 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -128,18 +128,11 @@ void process_dnd_im(const LLSD& notification) false, false); //will need slight refactor to retrieve whether offline message or not (assume online for now) } - - // open conversation floater - LLFloaterIMContainer* container_floater = - LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); - if (container_floater && !(container_floater->isFrontmost())) - { - container_floater->openFloater(); - container_floater->setFrontmost(TRUE); - } } + + static void on_avatar_name_cache_toast(const LLUUID& agent_id, const LLAvatarName& av_name, LLSD msg) @@ -2626,13 +2619,7 @@ void LLIMMgr::addMessage( // Open conversation floater if offline messages are present if (is_offline_msg) { - LLFloaterIMContainer* container_floater = - LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); - if (container_floater && !(container_floater->isFrontmost())) - { - container_floater->openFloater(); - container_floater->setFrontmost(TRUE); - } + LLFloaterReg::showInstance("im_container"); } } -- cgit v1.2.3 From b7f4916b3e4af149d6212a701c556915e23e7c0a Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Tue, 15 Jan 2013 02:48:52 +0000 Subject: CHUI-679 FIX Crash when script floater appears in CHUI viewer LLPostponedNotification now inherits from LLMortician so it can postpone its deletion. This prevents a crash when looking up an avatar name in the case where the name already exists in the cache. --- indra/llui/llnotifications.cpp | 3 ++- indra/llui/llnotifications.h | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index a5492b46f7..ea52bee184 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1852,6 +1852,7 @@ void LLPostponedNotification::fetchAvatarName(const LLUUID& id) { mAvatarNameCacheConnection.disconnect(); } + mAvatarNameCacheConnection = LLAvatarNameCache::get(id, boost::bind(&LLPostponedNotification::onAvatarNameCache, this, _1, _2)); } } @@ -1860,7 +1861,7 @@ void LLPostponedNotification::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) { mAvatarNameCacheConnection.disconnect(); - + std::string name = av_name.getCompleteName(); // from PE merge - we should figure out if this is the right thing to do diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 236c2a42d1..e02c58de44 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -92,6 +92,7 @@ #include "llevents.h" #include "llfunctorregistry.h" #include "llinitparam.h" +#include "llmortician.h" #include "llnotificationptr.h" #include "llpointer.h" #include "llrefcount.h" @@ -981,7 +982,7 @@ private: * 1 create class derived from LLPostponedNotification; * 2 call LLPostponedNotification::add method; */ -class LLPostponedNotification +class LLPostponedNotification : public LLMortician { public: /** @@ -1014,7 +1015,7 @@ private: void cleanup() { - delete this; + die(); } protected: -- cgit v1.2.3 From a49d3b14254fa5cfac3900e86b2287a016eaf9cc Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Tue, 15 Jan 2013 14:07:55 +0200 Subject: CHUI-567 FIXED "Translate chat", "Translation settings..." menu items are added. --- indra/newview/app_settings/settings_per_account.xml | 13 ++++++++++++- indra/newview/llfloaterimsessiontab.cpp | 20 ++++++++++++++++++++ indra/newview/llfloaterimsessiontab.h | 4 ++++ indra/newview/llfloatertranslationsettings.cpp | 18 +++++++++++++----- indra/newview/llfloatertranslationsettings.h | 1 + .../default/xui/en/menu_im_session_showmodes.xml | 20 ++++++++++++++++++-- 6 files changed, 68 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 4ff494fbfb..6864328339 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -270,7 +270,18 @@ <key>Value</key> <integer>0</integer> </map> - <key>ShowFavoritesOnLogin</key> + <key>TranslatingEnabled</key> + <map> + <key>Comment</key> + <string>Translation prefs are set</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowFavoritesOnLogin</key> <map> <key>Comment</key> <string>Determines whether favorites of last logged in user will be saved on exit from viewer and shown on login screen</string> diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index d4eb03f95d..06a79836db 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -72,6 +72,12 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2)); + mEnableCallbackRegistrar.add("Translating.Enabled", + boost::bind(&LLFloaterIMSessionTab::isTranslatingEnabled, this, _2)); + mEnableCallbackRegistrar.add("Translating.On", + boost::bind(&LLFloaterIMSessionTab::isTranslationOn, this, _2)); + mCommitCallbackRegistrar.add("Translating.Toggle", + boost::bind(&LLFloaterIMSessionTab::toggleTranslation, this, _2)); // Right click menu handling mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem, this, _2)); @@ -552,6 +558,10 @@ void LLFloaterIMSessionTab::onIMSessionMenuItemClicked(const LLSD& userdata) LLFloaterIMSessionTab::processChatHistoryStyleUpdate(); } +void LLFloaterIMSessionTab::toggleTranslation(const LLSD& userdata) +{ + gSavedSettings.setBOOL("TranslateChat", !gSavedSettings.getBOOL("TranslateChat")); +} bool LLFloaterIMSessionTab::onIMCompactExpandedMenuItemCheck(const LLSD& userdata) { @@ -576,6 +586,16 @@ bool LLFloaterIMSessionTab::onIMShowModesMenuItemEnable(const LLSD& userdata) return (plain_text && (is_not_names || mIsP2PChat)); } +bool LLFloaterIMSessionTab::isTranslatingEnabled(const LLSD& userdata) +{ + return gSavedPerAccountSettings.getBOOL("TranslatingEnabled"); +} + +bool LLFloaterIMSessionTab::isTranslationOn(const LLSD& userdata) +{ + return gSavedSettings.getBOOL("TranslateChat"); +} + void LLFloaterIMSessionTab::hideOrShowTitle() { const LLFloater::Params& default_params = LLFloater::getDefaultParams(); diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 0fa99a46be..05da0f98bc 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -109,8 +109,12 @@ protected: // bool onIMShowModesMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemEnable(const LLSD& userdata); + bool isTranslatingEnabled(const LLSD& userdata); + bool isTranslationOn(const LLSD& userdata); static void onSlide(LLFloaterIMSessionTab *self); + void toggleTranslation(const LLSD& userdata); + // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 6a9236ce0c..33f2c35239 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -225,11 +225,10 @@ void LLFloaterTranslationSettings::updateControlsEnabledState() mGoogleVerifyBtn->setEnabled(on && google_selected && !mGoogleKeyVerified && !getEnteredGoogleKey().empty()); - mOKBtn->setEnabled( - !on || ( - (bing_selected && mBingKeyVerified) || - (google_selected && mGoogleKeyVerified) - )); + bool service_verified = (bing_selected && mBingKeyVerified) || (google_selected && mGoogleKeyVerified); + gSavedPerAccountSettings.setBOOL("TranslatingEnabled", service_verified); + + mOKBtn->setEnabled(!on || service_verified); } void LLFloaterTranslationSettings::verifyKey(int service, const std::string& key, bool alert) @@ -285,7 +284,16 @@ void LLFloaterTranslationSettings::onBtnGoogleVerify() verifyKey(LLTranslate::SERVICE_GOOGLE, key); } } +void LLFloaterTranslationSettings::onClose(bool app_quitting) +{ + std::string service = gSavedSettings.getString("TranslationService"); + bool bing_selected = service == "bing"; + bool google_selected = service == "google"; + + bool service_verified = (bing_selected && mBingKeyVerified) || (google_selected && mGoogleKeyVerified); + gSavedPerAccountSettings.setBOOL("TranslatingEnabled", service_verified); +} void LLFloaterTranslationSettings::onBtnOK() { gSavedSettings.setBOOL("TranslateChat", mMachineTranslationCB->getValue().asBoolean()); diff --git a/indra/newview/llfloatertranslationsettings.h b/indra/newview/llfloatertranslationsettings.h index 9b47ad72ed..b9bfd6265a 100644 --- a/indra/newview/llfloatertranslationsettings.h +++ b/indra/newview/llfloatertranslationsettings.h @@ -44,6 +44,7 @@ public: void setBingVerified(bool ok, bool alert); void setGoogleVerified(bool ok, bool alert); + void onClose(bool app_quitting); private: std::string getSelectedService() const; diff --git a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml index 483f24afd0..f2a8b39b04 100644 --- a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml +++ b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml @@ -44,7 +44,23 @@ parameter="IMShowNamesForP2PConv" /> <menu_item_check.on_enable function="IMSession.Menu.ShowModes.Enable" - parameter="IMShowNamesForP2PConv" /> - + parameter="IMShowNamesForP2PConv" /> </menu_item_check> + <menu_item_separator layout="topleft" /> + <menu_item_check name="Translate_chat" label="Translate chat"> + <menu_item_check.on_click + function="Translating.Toggle" /> + <menu_item_check.on_check + function="Translating.On" /> + <menu_item_check.on_enable + function="Translating.Enabled" /> + </menu_item_check> + <menu_item_check name="Translation_settings" label="Translation settings..."> + <menu_item_check.on_check + function="Floater.Visible" + parameter="prefs_translation" /> + <menu_item_check.on_click + function="Floater.Toggle" + parameter="prefs_translation" /> + </menu_item_check> </toggleable_menu> -- cgit v1.2.3 From 235a3477364c6747d7724a090ca61adbcbeac272 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 15 Jan 2013 14:13:36 -0800 Subject: CHUI-458 : Fixed : Tidy up the title overwrite by the selected conversation --- indra/newview/llfloaterimcontainer.cpp | 6 +++--- indra/newview/llfloaterimsession.cpp | 2 ++ indra/newview/llfloaterimsession.h | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index cf81a2b046..8264a90325 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -505,10 +505,10 @@ void LLFloaterIMContainer::draw() collapseMessagesPane(true); } - //Update moderator options visibility const LLConversationItem *current_session = getCurSelectedViewModelItem(); if (current_session) { + // Update moderator options visibility LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = current_session->getChildrenBegin(); LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = current_session->getChildrenEnd(); while (current_participant_model != end_participant_model) @@ -518,9 +518,9 @@ void LLFloaterIMContainer::draw() current_participant_model++; } - // is P2P? Test if we can change the title + // Update floater's title as required by the currently selected session or use the default title LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(current_session->getUUID()); - setTitle(conversation_floaterp && conversation_floaterp->hasSpecialTitle() ? conversation_floaterp->getSpecialTitle() : mGeneralTitle); + setTitle(conversation_floaterp && conversation_floaterp->needsTitleOverwrite() ? conversation_floaterp->getTitle() : mGeneralTitle); } LLFloater::draw(); diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 931ee0dc66..a09dc1914f 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -70,6 +70,7 @@ LLFloaterIMSession::LLFloaterIMSession(const LLUUID& session_id) mShouldSendTypingState(false), mMeTyping(false), mOtherTyping(false), + mSessionNameUpdatedForTyping(false), mTypingTimer(), mTypingTimeoutTimer(), mPositioned(false), @@ -556,6 +557,7 @@ void LLFloaterIMSession::updateSessionName(const std::string& name) LLFloaterIMSessionTab::updateSessionName(name); mTypingStart.setArg("[NAME]", name); setTitle (mOtherTyping ? mTypingStart.getString() : name); + mSessionNameUpdatedForTyping = mOtherTyping; } } diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index 7239481e56..2049cedfd7 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -132,8 +132,7 @@ public: static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); static floater_showed_signal_t sIMFloaterShowedSignal; - bool hasSpecialTitle() { return mOtherTyping; } - std::string getSpecialTitle() { return getTitle(); } + bool needsTitleOverwrite() { return mSessionNameUpdatedForTyping && mOtherTyping; } private: /*virtual*/ void refresh(); @@ -184,6 +183,7 @@ private: bool mShouldSendTypingState; LLFrameTimer mTypingTimer; LLFrameTimer mTypingTimeoutTimer; + bool mSessionNameUpdatedForTyping; bool mSessionInitialized; LLSD mQueuedMsgsForInit; -- cgit v1.2.3 From de9e2c38126682e5c6215151e3389380a93b8bc0 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 15 Jan 2013 20:36:48 -0800 Subject: CHUI-668: Code review changes --- indra/newview/llagent.cpp | 2 +- indra/newview/llcommunicationchannel.cpp | 32 +++++- indra/newview/llcommunicationchannel.h | 8 +- .../newview/lldonotdisturbnotificationstorage.cpp | 108 +++++++++++++++++---- indra/newview/lldonotdisturbnotificationstorage.h | 21 +++- 5 files changed, 146 insertions(+), 25 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index d28af3eff9..094d502078 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1397,7 +1397,7 @@ void LLAgent::setDoNotDisturb(bool pIsDoNotDisturb) LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(pIsDoNotDisturb); if (isDoNotDisturbSwitchedOff) { - LLDoNotDisturbNotificationStorage::getInstance()->loadNotifications(); + LLDoNotDisturbNotificationStorage::getInstance()->updateNotifications(); } } diff --git a/indra/newview/llcommunicationchannel.cpp b/indra/newview/llcommunicationchannel.cpp index a99047c163..0821510645 100644 --- a/indra/newview/llcommunicationchannel.cpp +++ b/indra/newview/llcommunicationchannel.cpp @@ -52,6 +52,11 @@ bool LLCommunicationChannel::filterByDoNotDisturbStatus(LLNotificationPtr) return !gAgent.isDoNotDisturb(); } +S32 LLCommunicationChannel::getHistorySize() const +{ + return mHistory.size(); +} + LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::beginHistory() const { return mHistory.begin(); @@ -62,14 +67,37 @@ LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::e return mHistory.end(); } +LLCommunicationChannel::history_list_t::iterator LLCommunicationChannel::beginHistory() +{ + return mHistory.begin(); +} + +LLCommunicationChannel::history_list_t::iterator LLCommunicationChannel::endHistory() +{ + return mHistory.end(); +} + void LLCommunicationChannel::clearHistory() { mHistory.clear(); } -void LLCommunicationChannel::removeItem(history_list_t::const_iterator itemToRemove) +void LLCommunicationChannel::removeItemFromHistory(LLNotificationPtr p) +{ + //Find the notification and removes it from mHistory + for(history_list_t::iterator it = beginHistory(); it != endHistory(); ++it) + { + if(it->second == p) + { + mHistory.erase(it); + break; + } + } +} + +void LLCommunicationChannel::onDelete(LLNotificationPtr p) { - mHistory.erase(itemToRemove); + removeItemFromHistory(p); } void LLCommunicationChannel::onFilterFail(LLNotificationPtr pNotificationPtr) diff --git a/indra/newview/llcommunicationchannel.h b/indra/newview/llcommunicationchannel.h index c07933118d..0d8f7f4387 100644 --- a/indra/newview/llcommunicationchannel.h +++ b/indra/newview/llcommunicationchannel.h @@ -44,13 +44,17 @@ public: static bool filterByDoNotDisturbStatus(LLNotificationPtr); typedef std::multimap<LLDate, LLNotificationPtr> history_list_t; + S32 getHistorySize() const; history_list_t::const_iterator beginHistory() const; history_list_t::const_iterator endHistory() const; - + history_list_t::iterator beginHistory(); + history_list_t::iterator endHistory(); + void clearHistory(); - void removeItem(history_list_t::const_iterator itemToRemove); + void removeItemFromHistory(LLNotificationPtr p); protected: + virtual void onDelete(LLNotificationPtr p); virtual void onFilterFail(LLNotificationPtr pNotificationPtr); private: diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 12ff308a77..42b455c1ce 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -42,9 +42,34 @@ #include "llsingleton.h" #include "lluuid.h" +static const F32 DND_TIMER = 3.0; + +LLDoNotDisturbNotificationStorageTimer::LLDoNotDisturbNotificationStorageTimer() : LLEventTimer(DND_TIMER) +{ + mEventTimer.start(); +} + +LLDoNotDisturbNotificationStorageTimer::~LLDoNotDisturbNotificationStorageTimer() +{ + mEventTimer.stop(); +} + +BOOL LLDoNotDisturbNotificationStorageTimer::tick() +{ + LLDoNotDisturbNotificationStorage * doNotDisturbNotificationStorage = LLDoNotDisturbNotificationStorage::getInstance(); + + if(doNotDisturbNotificationStorage + && doNotDisturbNotificationStorage->getDirty()) + { + doNotDisturbNotificationStorage->saveNotifications(); + } + return FALSE; +} + LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() : LLSingleton<LLDoNotDisturbNotificationStorage>() , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")) + , mDirty(false) { } @@ -57,6 +82,16 @@ void LLDoNotDisturbNotificationStorage::initialize() getCommunicationChannel()->connectFailedFilter(boost::bind(&LLDoNotDisturbNotificationStorage::onChannelChanged, this, _1)); } +bool LLDoNotDisturbNotificationStorage::getDirty() +{ + return mDirty; +} + +void LLDoNotDisturbNotificationStorage::resetDirty() +{ + mDirty = false; +} + static LLFastTimer::DeclareTimer FTM_SAVE_DND_NOTIFICATIONS("Save DND Notifications"); void LLDoNotDisturbNotificationStorage::saveNotifications() @@ -83,6 +118,8 @@ void LLDoNotDisturbNotificationStorage::saveNotifications() } writeNotifications(output); + + resetDirty(); } static LLFastTimer::DeclareTimer FTM_LOAD_DND_NOTIFICATIONS("Load DND Notifications"); @@ -120,15 +157,7 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() imToastExists = true; } - //Notification already exists in notification pipeline (same instance of app running) - if (notification) - { - notification->setDND(true); - instance.update(notification); - } - //Notification doesn't exist (different instance since restarted app while in DND mode) - else - { + //New notification needs to be added notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true)); LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]); if (responder == NULL) @@ -144,21 +173,58 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() instance.add(notification); } - } if(imToastExists) { LLFloaterReg::showInstance("im_container"); } - // Clear the communication channel history and rewrite the save file to empty it as well + //writes out empty .xml file (since LLCommunicationChannel::mHistory is empty) + saveNotifications(); +} + +void LLDoNotDisturbNotificationStorage::updateNotifications() +{ + LLNotificationChannelPtr channelPtr = getCommunicationChannel(); LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get()); llassert(commChannel != NULL); + + LLNotifications& instance = LLNotifications::instance(); + bool imToastExists = false; + + for (LLCommunicationChannel::history_list_t::const_iterator it = commChannel->beginHistory(); + it != commChannel->endHistory(); + ++it) + { + LLNotificationPtr notification = it->second; + std::string notificationName = notification->getName(); + + if(notificationName == "IMToast") + { + imToastExists = true; + } + + //Notification already exists in notification pipeline (same instance of app running) + if (notification) + { + notification->setDND(true); + instance.update(notification); + } + } + + if(imToastExists) + { + LLFloaterReg::showInstance("im_container"); + } + + //When exit DND mode, write empty notifications file + if(commChannel->getHistorySize()) + { commChannel->clearHistory(); - saveNotifications(); } +} LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChannel() const { @@ -175,8 +241,8 @@ void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& sessi LLNotificationPtr notification; LLSD substitutions; LLUUID notificationSessionID; - LLCommunicationChannel::history_list_t::const_iterator it; - std::vector<LLCommunicationChannel::history_list_t::const_iterator> itemsToRemove; + LLCommunicationChannel::history_list_t::iterator it; + std::vector<LLCommunicationChannel::history_list_t::iterator> itemsToRemove; //Find notification with the matching session id for (it = commChannel->beginHistory(); @@ -193,17 +259,21 @@ void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& sessi } } - //Remove the notification + + //Remove the notifications + if(itemsToRemove.size()) + { while(itemsToRemove.size()) { it = itemsToRemove.back(); notification = it->second; - commChannel->removeItem(it); - //instance.cancel triggers onChannelChanged to be called within LLNotificationChannelBase::updateItem (which save changes to the .xml file) - //but this means that saveNotifications write a file each time as well, BAD! Will find a way to prevent this. + commChannel->removeItemFromHistory(notification); instance.cancel(notification); itemsToRemove.pop_back(); } + //Trigger saving of notifications to xml once all have been removed + saveNotifications(); + } } @@ -211,7 +281,7 @@ bool LLDoNotDisturbNotificationStorage::onChannelChanged(const LLSD& pPayload) { if (pPayload["sigtype"].asString() != "load") { - saveNotifications(); + mDirty = true; } return false; diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h index 8edb8569b4..fd03b71357 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.h +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -28,12 +28,26 @@ #define LL_LLDONOTDISTURBNOTIFICATIONSTORAGE_H #include "llerror.h" +#include "lleventtimer.h" #include "llnotifications.h" #include "llnotificationstorage.h" #include "llsingleton.h" class LLSD; +class LLDoNotDisturbNotificationStorageTimer : public LLEventTimer +{ +public: + LLDoNotDisturbNotificationStorageTimer(); + ~LLDoNotDisturbNotificationStorageTimer(); + +public: + void startTimer(); + void stopTimer(); + bool isRunning(); + BOOL tick(); +}; + class LLDoNotDisturbNotificationStorage : public LLSingleton<LLDoNotDisturbNotificationStorage>, public LLNotificationStorage { LOG_CLASS(LLDoNotDisturbNotificationStorage); @@ -42,14 +56,19 @@ public: ~LLDoNotDisturbNotificationStorage(); void initialize(); - + bool getDirty(); + void resetDirty(); void saveNotifications(); void loadNotifications(); + void updateNotifications(); void removeIMNotification(const LLUUID& session_id); protected: private: + bool mDirty; + LLDoNotDisturbNotificationStorageTimer mTimer; + LLNotificationChannelPtr getCommunicationChannel() const; bool onChannelChanged(const LLSD& pPayload); }; -- cgit v1.2.3 From b0774ec9147ddc2c2e5e93e5a74c929c802c32af Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Wed, 16 Jan 2013 17:37:13 +0200 Subject: CHUI-650 (Floaters not returning to active transparency after becoming inactive) - Checking is added(comparing to previous fix) to avoid crash. --- indra/llui/llfloater.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 8f9be5285d..d2aae11191 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -655,7 +655,7 @@ void LLFloater::openFloater(const LLSD& key) { llinfos << "Opening floater " << getName() << llendl; mKey = key; // in case we need to open ourselves again - + if (getSoundFlags() != SILENT // don't play open sound for hosted (tabbed) windows && !getHost() @@ -2394,6 +2394,11 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) { if (mFrontChild == child) { + + if (give_focus && !gFocusMgr.childHasKeyboardFocus(child)) + { + child->setFocus(TRUE); + } return; } -- cgit v1.2.3 From 8c3d3d4b07f12e3462af7745016536389ab7cf73 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 16 Jan 2013 16:40:59 +0200 Subject: CHUI-618 ADD FIX User sees no indication of offline messages received with conversation log preference turned off: forced flashing of conversation's item when offline message is present --- indra/newview/llimview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index ff171fc0f8..d0a8dfc0c8 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2620,8 +2620,9 @@ void LLIMMgr::addMessage( if (is_offline_msg) { LLFloaterReg::showInstance("im_container"); + LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")-> + flashConversationItemWidget(session_id, true); } - } void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args) -- cgit v1.2.3 From f43f51406b024ed2423e068114ae818bac5c6df5 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 16 Jan 2013 14:53:23 -0800 Subject: CHUI-683 : Default sort order for Blocked was wrong, unrecognized value was not tested. --- indra/newview/app_settings/settings.xml | 2 +- indra/newview/llpanelblockedlist.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 126df69519..fd4d1df894 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10215,7 +10215,7 @@ <key>Type</key> <string>U32</string> <key>Value</key> - <integer>2</integer> + <integer>0</integer> </map> <key>CallLogSortOrder</key> <map> diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index df1ccdd9fc..115114bb53 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -89,6 +89,9 @@ BOOL LLPanelBlockedList::postBuild() case E_SORT_BY_TYPE: mBlockedList->sortByType(); break; + default: + llwarns << "Unrecognized sort order for blocked list" << llendl; + break; } // Use the context menu of the Block list for the Block tab gear menu. -- cgit v1.2.3 From 5083517c7cd6b91b8920ab0f698600abed955280 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Thu, 17 Jan 2013 01:57:19 +0000 Subject: CHUI-292 FIX Extra space in object chiclet toasts in CHUI viewer compared with release viewer In LLToastNotifyPanel, moved mInfoPanel->SetFollowsAll() immediately before call to snapToMessageHeight() as was previously the case in release viewer --- indra/newview/lltoastnotifypanel.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index d494d12903..268b68b539 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -356,9 +356,8 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) if(rect != LLRect::null) { this->setShape(rect); - } + } mInfoPanel = getChild<LLPanel>("info_panel"); - mInfoPanel->setFollowsAll(); mControlPanel = getChild<LLPanel>("control_panel"); BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); @@ -453,10 +452,10 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) if(h_pad < 2*HPAD) { /* - * Probably it is a scriptdialog toast - * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. - * In last case set default h_pad to avoid heaping of buttons - */ + * Probably it is a scriptdialog toast + * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. + * In last case set default h_pad to avoid heaping of buttons + */ S32 button_per_row = button_panel_width / BUTTON_WIDTH; h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row if(h_pad < 2*HPAD) // still not enough space between buttons ? @@ -491,10 +490,10 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) //mButtons.assign(buttons.begin(), buttons.end()); } } + // adjust panel's height to the text size + mInfoPanel->setFollowsAll(); snapToMessageHeight(mTextBox, MAX_LENGTH); - - } -- cgit v1.2.3 From 90adfec715eb93663b424a2ac28a70e965247df4 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 16 Jan 2013 19:22:36 -0800 Subject: CHUI-682 : WIP : Instrument the menu display (or lack thereof). --- indra/newview/llpaneloutfitedit.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'indra') diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index d690a18477..c11539353a 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -155,6 +155,8 @@ class LLPanelOutfitEditGearMenu public: static LLToggleableMenu* create() { + llinfos << "Merov debug : Create wearable gear menu" << llendl; + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("Wearable.Create", boost::bind(onCreate, _2)); @@ -169,6 +171,12 @@ public: return menu; } + + static void pressed(LLToggleableMenu* menu) + { + menu->toggleVisibility(); + llinfos << "Merov debug : The button is pressed! Show the menu!!!" << llendl; + } private: static void onCreate(const LLSD& param) @@ -189,6 +197,8 @@ private: LLView* menu_clothes = gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE); LLView* menu_bp = gMenuHolder->getChildView("COF.Geear.New_Body_Parts", FALSE); + llinfos << "Merov debug : Populate wearable gear menu" << llendl; + for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i) { LLWearableType::EType type = (LLWearableType::EType) i; @@ -197,6 +207,7 @@ private: LLMenuItemCallGL::Params p; p.name = type_name; p.label = LLTrans::getString(LLWearableType::getTypeDefaultNewName(type)); + llinfos << "Merov debug : menu label = " << LLTrans::getString(LLWearableType::getTypeDefaultNewName(type)) << llendl; p.on_click.function_name = "Wearable.Create"; p.on_click.parameter = LLSD(type_name); @@ -204,6 +215,8 @@ private: menu_clothes : menu_bp; LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent); } + + llinfos << "Merov debug : clothes size = " << menu_clothes->getChildCount() << ", body part size = " << menu_bp->getChildCount() << llendl; } }; @@ -564,6 +577,7 @@ BOOL LLPanelOutfitEdit::postBuild() mWearablesGearMenuBtn->setMenu(mAddWearablesGearMenu); mGearMenu = LLPanelOutfitEditGearMenu::create(); + mGearMenuBtn->setMouseDownCallback(boost::bind(&LLPanelOutfitEditGearMenu::pressed, mGearMenu)); mGearMenuBtn->setMenu(mGearMenu); mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this)); -- cgit v1.2.3 From 7ec0d837dd2f364a775757b808351fa81c2468a8 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Thu, 17 Jan 2013 19:05:22 +0200 Subject: CHUI-631 (Next conversation in list should be selected in Conversations floater after closing a conversation) Don't force selecting nearby chat after closing conversation --- indra/newview/llfloaterimsessiontab.cpp | 7 ------- 1 file changed, 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 06a79836db..bc5b8c334d 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -88,13 +88,6 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) LLFloaterIMSessionTab::~LLFloaterIMSessionTab() { delete mRefreshTimer; - - // Select Nearby Chat session - LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container"); - if (container) - { - container->selectConversationPair(LLUUID(NULL), true); - } } //static -- cgit v1.2.3 From aabfce7d9f14ff18ea073708d79c6f62118b3453 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 17 Jan 2013 21:40:49 -0800 Subject: CHUI-682 : Fixed : Added LLMenuGL as a possible child of a toggle or contextual menu (for dynamic submenus). --- indra/llui/llmenugl.cpp | 28 +++++++++++++++++++++------- indra/newview/llpaneloutfitedit.cpp | 14 -------------- 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 93dc13475b..7dcc39950b 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1751,16 +1751,18 @@ void LLMenuGL::setCanTearOff(BOOL tear_off) bool LLMenuGL::addChild(LLView* view, S32 tab_group) { - if (LLMenuGL* menup = dynamic_cast<LLMenuGL*>(view)) + LLMenuGL* menup = dynamic_cast<LLMenuGL*>(view); + if (menup) { - appendMenu(menup); - return true; + return appendMenu(menup); } - else if (LLMenuItemGL* itemp = dynamic_cast<LLMenuItemGL*>(view)) + + LLMenuItemGL* itemp = dynamic_cast<LLMenuItemGL*>(view); + if (itemp) { - append(itemp); - return true; + return append(itemp); } + return false; } @@ -1771,16 +1773,28 @@ bool LLMenuGL::addContextChild(LLView* view, S32 tab_group) { LLContextMenu* context = dynamic_cast<LLContextMenu*>(view); if (context) + { return appendContextSubMenu(context); + } LLMenuItemSeparatorGL* separator = dynamic_cast<LLMenuItemSeparatorGL*>(view); if (separator) + { return append(separator); + } LLMenuItemGL* item = dynamic_cast<LLMenuItemGL*>(view); if (item) + { return append(item); - + } + + LLMenuGL* menup = dynamic_cast<LLMenuGL*>(view); + if (menup) + { + return appendMenu(menup); + } + return false; } diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index c11539353a..f5db98f831 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -155,8 +155,6 @@ class LLPanelOutfitEditGearMenu public: static LLToggleableMenu* create() { - llinfos << "Merov debug : Create wearable gear menu" << llendl; - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("Wearable.Create", boost::bind(onCreate, _2)); @@ -172,12 +170,6 @@ public: return menu; } - static void pressed(LLToggleableMenu* menu) - { - menu->toggleVisibility(); - llinfos << "Merov debug : The button is pressed! Show the menu!!!" << llendl; - } - private: static void onCreate(const LLSD& param) { @@ -197,8 +189,6 @@ private: LLView* menu_clothes = gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE); LLView* menu_bp = gMenuHolder->getChildView("COF.Geear.New_Body_Parts", FALSE); - llinfos << "Merov debug : Populate wearable gear menu" << llendl; - for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i) { LLWearableType::EType type = (LLWearableType::EType) i; @@ -207,7 +197,6 @@ private: LLMenuItemCallGL::Params p; p.name = type_name; p.label = LLTrans::getString(LLWearableType::getTypeDefaultNewName(type)); - llinfos << "Merov debug : menu label = " << LLTrans::getString(LLWearableType::getTypeDefaultNewName(type)) << llendl; p.on_click.function_name = "Wearable.Create"; p.on_click.parameter = LLSD(type_name); @@ -215,8 +204,6 @@ private: menu_clothes : menu_bp; LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent); } - - llinfos << "Merov debug : clothes size = " << menu_clothes->getChildCount() << ", body part size = " << menu_bp->getChildCount() << llendl; } }; @@ -577,7 +564,6 @@ BOOL LLPanelOutfitEdit::postBuild() mWearablesGearMenuBtn->setMenu(mAddWearablesGearMenu); mGearMenu = LLPanelOutfitEditGearMenu::create(); - mGearMenuBtn->setMouseDownCallback(boost::bind(&LLPanelOutfitEditGearMenu::pressed, mGearMenu)); mGearMenuBtn->setMenu(mGearMenu); mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this)); -- cgit v1.2.3 From 3938f99b5ede5b87315fa18ca24d2deece28b34d Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Fri, 18 Jan 2013 14:18:51 +0200 Subject: CHUI-681 FIXED Clear flash state only for selected widget --- indra/newview/llconversationview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 903dd2a407..126c73c283 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -246,7 +246,7 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) if(result && getRoot()->getCurSelectedItem() == this) { LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); - im_container->clearAllFlashStates(); + im_container->flashConversationItemWidget(session_id,false); im_container->selectConversationPair(session_id, false); im_container->collapseMessagesPane(false); } -- cgit v1.2.3 From be7835eec6b6cae12656fede44fc2cda1729e20d Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 17 Jan 2013 16:25:21 +0200 Subject: CHUI-625 Participant drop down icon not visible when conversation is highlighted orange: redraw the arrow slightly later --- indra/newview/llconversationview.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 126c73c283..16dd0e4565 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -202,14 +202,6 @@ void LLConversationViewSession::draw() const LLFolderViewItem::Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); - // we don't draw the open folder arrow in minimized mode - if (mHasArrow && !mCollapsedMode) - { - // update the rotation angle of open folder arrow - updateLabelRotation(); - drawOpenFolderArrow(default_params, sFgColor); - } - // Indicate that flash can start (moot operation if already started, done or not flashing) startFlashing(); @@ -232,6 +224,14 @@ void LLConversationViewSession::draw() (*iit)->setVisible(draw_children); } + // we don't draw the open folder arrow in minimized mode + if (mHasArrow && !mCollapsedMode) + { + // update the rotation angle of open folder arrow + updateLabelRotation(); + drawOpenFolderArrow(default_params, sFgColor); + } + LLView::draw(); } -- cgit v1.2.3 From fdf774f51fd24bb62d1e1fc580bd04df4547b9f8 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 17 Jan 2013 13:52:51 -0800 Subject: CHUI-685 Problem: The notifications .xml file was cleared upon exit because removeIMNotification was being called and deleting inventory offers becaus they did not have a session id. Resolution: Now check to make sure that removeIMNotification only removes IMs (IMToast). --- .../newview/lldonotdisturbnotificationstorage.cpp | 62 ++++++++++++---------- indra/newview/lldonotdisturbnotificationstorage.h | 3 -- indra/newview/llfloaterimcontainer.cpp | 16 +++--- 3 files changed, 40 insertions(+), 41 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 42b455c1ce..5bea7d41f6 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -43,15 +43,16 @@ #include "lluuid.h" static const F32 DND_TIMER = 3.0; +const std::string toastName = "IMToast"; LLDoNotDisturbNotificationStorageTimer::LLDoNotDisturbNotificationStorageTimer() : LLEventTimer(DND_TIMER) { - mEventTimer.start(); + //mEventTimer.start(); } LLDoNotDisturbNotificationStorageTimer::~LLDoNotDisturbNotificationStorageTimer() { - mEventTimer.stop(); + //mEventTimer.stop(); } BOOL LLDoNotDisturbNotificationStorageTimer::tick() @@ -152,27 +153,27 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() std::string notificationName = notification_params["name"]; LLNotificationPtr notification = instance.find(notificationID); - if(notificationName == "IMToast") + if(notificationName == toastName) { imToastExists = true; } //New notification needs to be added - notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true)); - LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]); - if (responder == NULL) - { - LL_WARNS("LLDoNotDisturbNotificationStorage") << "cannot create responder for notification of type '" - << notification->getType() << "'" << LL_ENDL; - } - else - { - LLNotificationResponderPtr responderPtr(responder); - notification->setResponseFunctor(responderPtr); - } - - instance.add(notification); + notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true)); + LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]); + if (responder == NULL) + { + LL_WARNS("LLDoNotDisturbNotificationStorage") << "cannot create responder for notification of type '" + << notification->getType() << "'" << LL_ENDL; + } + else + { + LLNotificationResponderPtr responderPtr(responder); + notification->setResponseFunctor(responderPtr); } + + instance.add(notification); + } if(imToastExists) { @@ -200,7 +201,7 @@ void LLDoNotDisturbNotificationStorage::updateNotifications() LLNotificationPtr notification = it->second; std::string notificationName = notification->getName(); - if(notificationName == "IMToast") + if(notificationName == toastName) { imToastExists = true; } @@ -221,9 +222,9 @@ void LLDoNotDisturbNotificationStorage::updateNotifications() //When exit DND mode, write empty notifications file if(commChannel->getHistorySize()) { - commChannel->clearHistory(); - saveNotifications(); -} + commChannel->clearHistory(); + saveNotifications(); + } } LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChannel() const @@ -241,6 +242,7 @@ void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& sessi LLNotificationPtr notification; LLSD substitutions; LLUUID notificationSessionID; + std::string notificationName; LLCommunicationChannel::history_list_t::iterator it; std::vector<LLCommunicationChannel::history_list_t::iterator> itemsToRemove; @@ -252,8 +254,10 @@ void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& sessi notification = it->second; substitutions = notification->getSubstitutions(); notificationSessionID = substitutions["SESSION_ID"].asUUID(); + notificationName = notification->getName(); - if(session_id == notificationSessionID) + if(notificationName == toastName + && session_id == notificationSessionID) { itemsToRemove.push_back(it); } @@ -263,14 +267,14 @@ void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& sessi //Remove the notifications if(itemsToRemove.size()) { - while(itemsToRemove.size()) - { - it = itemsToRemove.back(); - notification = it->second; + while(itemsToRemove.size()) + { + it = itemsToRemove.back(); + notification = it->second; commChannel->removeItemFromHistory(notification); - instance.cancel(notification); - itemsToRemove.pop_back(); - } + instance.cancel(notification); + itemsToRemove.pop_back(); + } //Trigger saving of notifications to xml once all have been removed saveNotifications(); } diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h index fd03b71357..fd7cc7ee82 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.h +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -42,9 +42,6 @@ public: ~LLDoNotDisturbNotificationStorageTimer(); public: - void startTimer(); - void stopTimer(); - bool isRunning(); BOOL tick(); }; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index cc23449449..8f290ae7c1 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1299,11 +1299,14 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool if (widget && widget->getParentFolder()) { widget->getParentFolder()->setSelection(widget, FALSE, FALSE); - if(gAgent.isDoNotDisturb()) - { - LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); - } } + + //When in DND mode, remove stored IM notifications + //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal + if(gAgent.isDoNotDisturb() && session_id.notNull()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); + } } /* floater processing */ @@ -1324,11 +1327,6 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool // Switch to the conversation floater that is being selected selectFloater(session_floater); } - - if(gAgent.isDoNotDisturb()) - { - LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); - } } // Set the focus on the selected floater -- cgit v1.2.3 From 6a134c92d82746a2bfbf011e53aa04bdec67655f Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Fri, 18 Jan 2013 00:05:51 +0200 Subject: CHUI-661 User cannot select multiple p2p conversation names in list to start conference chat --- indra/newview/llfloaterimcontainer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 8264a90325..ac5ecc4b80 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1290,9 +1290,9 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool { BOOL handled = TRUE; LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); - + /* widget processing */ - if (select_widget) + if (select_widget && mConversationsRoot->getSelectedCount() <= 1) { LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); if (widget && widget->getParentFolder()) -- cgit v1.2.3 From 68adda3627b0583e01796b229e1c1f920f28ff37 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 17 Jan 2013 14:12:48 -0800 Subject: CHUI-685 removing some commented out code --- indra/newview/lldonotdisturbnotificationstorage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 5bea7d41f6..824ff67972 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -47,12 +47,12 @@ const std::string toastName = "IMToast"; LLDoNotDisturbNotificationStorageTimer::LLDoNotDisturbNotificationStorageTimer() : LLEventTimer(DND_TIMER) { - //mEventTimer.start(); + } LLDoNotDisturbNotificationStorageTimer::~LLDoNotDisturbNotificationStorageTimer() { - //mEventTimer.stop(); + } BOOL LLDoNotDisturbNotificationStorageTimer::tick() -- cgit v1.2.3 From 6c79873d8dcb08c891ecd04f5706e69fe3a75b7d Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 17 Jan 2013 15:14:02 -0800 Subject: CHUI-680: Adjusted LLResponderRegistry to be derived from LLRegistrySingleton instead of LLResponderRegistry making its over version. --- indra/newview/llnotificationstorage.cpp | 93 ++++++++++++--------------------- 1 file changed, 33 insertions(+), 60 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index 4c5b7cc198..b6184f09bf 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -38,30 +38,43 @@ #include "llsd.h" #include "llsdserialize.h" #include "llsingleton.h" -#include "llviewermessage.h" +#include "llregistry.h" +#include "llviewermessage.h" +typedef boost::function<LLNotificationResponderInterface * (const LLSD& pParams)> responder_constructor_t; -class LLResponderRegistry : public LLSingleton<LLResponderRegistry> +class LLResponderRegistry : public LLRegistrySingleton<std::string, responder_constructor_t, LLResponderRegistry> { -public: - LLResponderRegistry(); - ~LLResponderRegistry(); - - LLNotificationResponderInterface* createResponder(const std::string& pNotificationName, const LLSD& pParams); - -protected: - -private: - template<typename RESPONDER_TYPE> static LLNotificationResponderInterface* create(const LLSD& pParams); - - typedef boost::function<LLNotificationResponderInterface* (const LLSD& params)> responder_constructor_t; - - void add(const std::string& pNotificationName, const responder_constructor_t& pConstructor); - - typedef std::map<std::string, responder_constructor_t> build_map_t; - build_map_t mBuildMap; + public: + template<typename RESPONDER_TYPE> static LLNotificationResponderInterface * create(const LLSD& pParams); + LLNotificationResponderInterface * createResponder(const std::string& pNotificationName, const LLSD& pParams); }; +template<typename RESPONDER_TYPE> LLNotificationResponderInterface * LLResponderRegistry::create(const LLSD& pParams) +{ + RESPONDER_TYPE* responder = new RESPONDER_TYPE(); + responder->fromLLSD(pParams); + return responder; +} + + +LLNotificationResponderInterface * LLResponderRegistry::createResponder(const std::string& pNotificationName, const LLSD& pParams) +{ + responder_constructor_t * factoryFunc = (LLResponderRegistry::getValue(pNotificationName)); + + if(factoryFunc) + { + return (*factoryFunc)(pParams); + } + + return NULL; +} + +LLResponderRegistry::StaticRegistrar sRegisterObjectGiveItem("ObjectGiveItem", &LLResponderRegistry::create<LLOfferInfo>); +LLResponderRegistry::StaticRegistrar sRegisterUserGiveItem("UserGiveItem", &LLResponderRegistry::create<LLOfferInfo>); +LLResponderRegistry::StaticRegistrar sRegisterOfferInfo("offer_info", &LLResponderRegistry::create<LLOfferInfo>); + + LLNotificationStorage::LLNotificationStorage(std::string pFileName) : mFileName(pFileName) { @@ -116,47 +129,7 @@ bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const return didFileRead; } -LLNotificationResponderInterface* LLNotificationStorage::createResponder(const std::string& pNotificationName, const LLSD& pParams) const +LLNotificationResponderInterface * LLNotificationStorage::createResponder(const std::string& pNotificationName, const LLSD& pParams) const { return LLResponderRegistry::getInstance()->createResponder(pNotificationName, pParams); } - -LLResponderRegistry::LLResponderRegistry() - : LLSingleton<LLResponderRegistry>() - , mBuildMap() -{ - add("ObjectGiveItem", &create<LLOfferInfo>); - add("UserGiveItem", &create<LLOfferInfo>); - add("offer_info", &create<LLOfferInfo>); -} - -LLResponderRegistry::~LLResponderRegistry() -{ -} - -LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& pNotificationName, const LLSD& pParams) -{ - build_map_t::const_iterator it = mBuildMap.find(pNotificationName); - if(mBuildMap.end() == it) - { - return NULL; - } - responder_constructor_t ctr = it->second; - return ctr(pParams); -} - -template<typename RESPONDER_TYPE> LLNotificationResponderInterface* LLResponderRegistry::create(const LLSD& pParams) -{ - RESPONDER_TYPE* responder = new RESPONDER_TYPE(); - responder->fromLLSD(pParams); - return responder; -} - -void LLResponderRegistry::add(const std::string& pNotificationName, const responder_constructor_t& pConstructor) -{ - if (mBuildMap.find(pNotificationName) != mBuildMap.end()) - { - LL_ERRS("LLResponderRegistry") << "Responder is already registered : " << pNotificationName << LL_ENDL; - } - mBuildMap.insert(std::make_pair<std::string, responder_constructor_t>(pNotificationName, pConstructor)); -} -- cgit v1.2.3 From d0235ad1789d05524065307f4514a76d55f4e847 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 17 Jan 2013 16:06:08 -0800 Subject: CHUI-604: Problem: DND response was inside of the responder for the inventory offer. Resolution: DND response is now sent upon receiving an offer notification from an agent. --- indra/newview/llviewermessage.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index db81e057de..9878f9bc81 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1618,12 +1618,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& { opener = discard_agent_offer; } - - - if (gAgent.isDoNotDisturb() && (!mFromGroup && !mFromObject)) - { - send_do_not_disturb_message(gMessageSystem, mFromID); - } if (modified_form != NULL) { @@ -1991,6 +1985,11 @@ void inventory_offer_handler(LLOfferInfo* info) // In viewer 2 we're now auto receiving inventory offers and messaging as such (not sending reject messages). info->send_auto_receive_response(); + if (gAgent.isDoNotDisturb()) + { + send_do_not_disturb_message(gMessageSystem, info->mFromID); + } + // Inform user that there is a script floater via toast system { payload["give_inventory_notification"] = TRUE; -- cgit v1.2.3 From 1780e78884c1b111f4a48bea578e28b370fbe45c Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Fri, 18 Jan 2013 02:05:09 +0000 Subject: CHUI-688 FIX Viewer crash when blocked user sends friend request Added a check for notification_ptr being null in friendship_offer_callback --- indra/newview/llviewermessage.cpp | 132 ++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 64 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index db81e057de..4bff0222bd 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -189,70 +189,74 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) const LLSD& payload = notification["payload"]; LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); - // add friend to recent people list - LLRecentPeople::instance().add(payload["from_id"]); - - switch(option) - { - case 0: - { - // accept - LLAvatarTracker::formFriendship(payload["from_id"]); - - const LLUUID fid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); - - // This will also trigger an onlinenotification if the user is online - msg->newMessageFast(_PREHASH_AcceptFriendship); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_TransactionBlock); - msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); - msg->nextBlockFast(_PREHASH_FolderData); - msg->addUUIDFast(_PREHASH_FolderID, fid); - msg->sendReliable(LLHost(payload["sender"].asString())); - - LLSD payload = notification["payload"]; - LLNotificationsUtil::add("FriendshipAcceptedByMe", - notification["substitutions"], payload); - break; - } - case 1: // Decline - { - LLSD payload = notification["payload"]; - LLNotificationsUtil::add("FriendshipDeclinedByMe", - notification["substitutions"], payload); - } - // fall-through - case 2: // Send IM - decline and start IM session - { - // decline - // We no longer notify other viewers, but we DO still send - // the rejection to the simulator to delete the pending userop. - msg->newMessageFast(_PREHASH_DeclineFriendship); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_TransactionBlock); - msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); - msg->sendReliable(LLHost(payload["sender"].asString())); - - // start IM session - if(2 == option) - { - LLAvatarActions::startIM(payload["from_id"].asUUID()); - } - } - default: - // close button probably, possibly timed out - break; - } - - LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); - modified_form->setElementEnabled("Accept", false); - modified_form->setElementEnabled("Decline", false); - notification_ptr->updateForm(modified_form); - notification_ptr->repost(); + // this will be skipped if the user offering friendship is blocked + if (notification_ptr) + { + // add friend to recent people list + LLRecentPeople::instance().add(payload["from_id"]); + + switch(option) + { + case 0: + { + // accept + LLAvatarTracker::formFriendship(payload["from_id"]); + + const LLUUID fid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); + + // This will also trigger an onlinenotification if the user is online + msg->newMessageFast(_PREHASH_AcceptFriendship); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_TransactionBlock); + msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); + msg->nextBlockFast(_PREHASH_FolderData); + msg->addUUIDFast(_PREHASH_FolderID, fid); + msg->sendReliable(LLHost(payload["sender"].asString())); + + LLSD payload = notification["payload"]; + LLNotificationsUtil::add("FriendshipAcceptedByMe", + notification["substitutions"], payload); + break; + } + case 1: // Decline + { + LLSD payload = notification["payload"]; + LLNotificationsUtil::add("FriendshipDeclinedByMe", + notification["substitutions"], payload); + } + // fall-through + case 2: // Send IM - decline and start IM session + { + // decline + // We no longer notify other viewers, but we DO still send + // the rejection to the simulator to delete the pending userop. + msg->newMessageFast(_PREHASH_DeclineFriendship); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_TransactionBlock); + msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); + msg->sendReliable(LLHost(payload["sender"].asString())); + + // start IM session + if(2 == option) + { + LLAvatarActions::startIM(payload["from_id"].asUUID()); + } + } + default: + // close button probably, possibly timed out + break; + } + + LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); + modified_form->setElementEnabled("Accept", false); + modified_form->setElementEnabled("Decline", false); + notification_ptr->updateForm(modified_form); + notification_ptr->repost(); + } return false; } -- cgit v1.2.3 From 5eef65e99476b716985eeccfbbcdafdfb664cb1a Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Fri, 18 Jan 2013 03:52:42 +0200 Subject: CHUI-379 FIXED Restore Voice Morphing menu --- indra/llui/llmenugl.cpp | 53 ++++++++++- indra/llui/llmenugl.h | 6 ++ indra/newview/llviewermenu.cpp | 16 +++- indra/newview/llvoicevivox.cpp | 100 +++++++++++++++++++++ indra/newview/llvoicevivox.h | 3 + .../skins/default/xui/en/floater_voice_effect.xml | 3 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 39 +++++--- 7 files changed, 207 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 7dcc39950b..2ea25648df 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -2461,6 +2461,56 @@ void LLMenuGL::empty( void ) deleteAllChildren(); } +// erase group of items from menu +void LLMenuGL::erase( S32 begin, S32 end, bool arrange/* = true*/) +{ + S32 items = mItems.size(); + + if ( items == 0 || begin >= end || begin < 0 || end > items ) + { + return; + } + + item_list_t::const_iterator start_position = mItems.begin(); + std::advance(start_position, begin); + + item_list_t::const_iterator end_position = mItems.begin(); + std::advance(end_position, end); + + for (item_list_t::const_iterator position_iter = start_position; position_iter != end_position; position_iter++) + { + LLUICtrl::removeChild(*position_iter); + } + + mItems.erase(start_position, end_position); + + if (arrange) + { + needsArrange(); + } +} + +// add new item at position +void LLMenuGL::insert( S32 position, LLView * ctrl, bool arrange /*= true*/ ) +{ + LLMenuItemGL * item = dynamic_cast<LLMenuItemGL *>(ctrl); + + if (NULL == item || position < 0 || position >= mItems.size()) + { + return; + } + + item_list_t::const_iterator position_iter = mItems.begin(); + std::advance(position_iter, position); + mItems.insert(position_iter, item); + LLUICtrl::addChild(item); + + if (arrange) + { + needsArrange(); + } +} + // Adjust rectangle of the menu void LLMenuGL::setLeftAndBottom(S32 left, S32 bottom) { @@ -2502,7 +2552,8 @@ BOOL LLMenuGL::append( LLMenuItemGL* item ) // add a separator to this menu BOOL LLMenuGL::addSeparator() { - LLMenuItemGL* separator = new LLMenuItemSeparatorGL(); + LLMenuItemSeparatorGL::Params p; + LLMenuItemGL* separator = LLUICtrlFactory::create<LLMenuItemSeparatorGL>(p); return addChild(separator); } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 3e03232e92..c57e0f0267 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -478,6 +478,12 @@ public: // remove all items on the menu void empty( void ); + // erase group of items from menu + void erase( S32 begin, S32 end, bool arrange = true ); + + // add new item at position + void insert( S32 begin, LLView * ctrl, bool arrange = true ); + void setItemLastSelected(LLMenuItemGL* item); // must be in menu U32 getItemCount(); // number of menu items LLMenuItemGL* getItem(S32 number); // 0 = first item diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index a0aa639ac6..8b45c44ed0 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -108,6 +108,7 @@ #include "llviewerparcelmgr.h" #include "llviewerstats.h" #include "llvoavatarself.h" +#include "llvoicevivox.h" #include "llworldmap.h" #include "pipeline.h" #include "llviewerjoystick.h" @@ -8152,6 +8153,11 @@ public: } }; +void handle_voice_morphing_subscribe() +{ + LLWeb::loadURLExternal(LLTrans::getString("voice_morphing_url")); +} + class LLToggleUIHints : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -8337,7 +8343,15 @@ void initialize_menus() // Me > Movement view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying"); - + + // Communicate > Voice morphing > Subscribe... + commit.add("Communicate.VoiceMorphing.Subscribe", boost::bind(&handle_voice_morphing_subscribe)); + LLVivoxVoiceClient * voice_clientp = LLVivoxVoiceClient::getInstance(); + enable.add("Communicate.VoiceMorphing.NoVoiceMorphing.Check" + , boost::bind(&LLVivoxVoiceClient::onCheckVoiceEffect, voice_clientp, "NoVoiceMorphing")); + commit.add("Communicate.VoiceMorphing.NoVoiceMorphing.Click" + , boost::bind(&LLVivoxVoiceClient::onClickVoiceEffect, voice_clientp, "NoVoiceMorphing")); + // World menu view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun"); view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark"); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 5e121bbcee..f3342b7ff1 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -34,6 +34,7 @@ #include "llvoavatarself.h" #include "llbufferstream.h" #include "llfile.h" +#include "llmenugl.h" #ifdef LL_STANDALONE # include "expat.h" #else @@ -70,6 +71,9 @@ #define USE_SESSION_GROUPS 0 +extern LLMenuBarGL* gMenuBarView; +extern void handle_voice_morphing_subscribe(); + const F32 VOLUME_SCALE_VIVOX = 0.01f; const F32 SPEAKING_TIMEOUT = 1.f; @@ -6739,10 +6743,106 @@ void LLVivoxVoiceClient::removeObserver(LLVoiceEffectObserver* observer) mVoiceFontObservers.erase(observer); } +// method checks the item in VoiceMorphing menu for appropriate current voice font +bool LLVivoxVoiceClient::onCheckVoiceEffect(const std::string& voice_effect_name) +{ + LLVoiceEffectInterface * effect_interfacep = LLVoiceClient::instance().getVoiceEffectInterface(); + if (NULL != effect_interfacep) + { + const LLUUID& currect_voice_effect_id = effect_interfacep->getVoiceEffect(); + + if (currect_voice_effect_id.isNull()) + { + if (voice_effect_name == "NoVoiceMorphing") + { + return true; + } + } + else + { + const LLSD& voice_effect_props = effect_interfacep->getVoiceEffectProperties(currect_voice_effect_id); + if (voice_effect_props["name"].asString() == voice_effect_name) + { + return true; + } + } + } + + return false; +} + +// method changes voice font for selected VoiceMorphing menu item +void LLVivoxVoiceClient::onClickVoiceEffect(const std::string& voice_effect_name) +{ + LLVoiceEffectInterface * effect_interfacep = LLVoiceClient::instance().getVoiceEffectInterface(); + if (NULL != effect_interfacep) + { + if (voice_effect_name == "NoVoiceMorphing") + { + effect_interfacep->setVoiceEffect(LLUUID()); + return; + } + const voice_effect_list_t& effect_list = effect_interfacep->getVoiceEffectList(); + if (!effect_list.empty()) + { + for (voice_effect_list_t::const_iterator it = effect_list.begin(); it != effect_list.end(); ++it) + { + if (voice_effect_name == it->first) + { + effect_interfacep->setVoiceEffect(it->second); + return; + } + } + } + } +} + +// it updates VoiceMorphing menu items in accordance with purchased properties +void LLVivoxVoiceClient::updateVoiceMorphingMenu() +{ + if (mVoiceFontListDirty) + { + LLVoiceEffectInterface * effect_interfacep = LLVoiceClient::instance().getVoiceEffectInterface(); + if (effect_interfacep) + { + const voice_effect_list_t& effect_list = effect_interfacep->getVoiceEffectList(); + if (!effect_list.empty()) + { + LLMenuGL * voice_morphing_menup = gMenuBarView->findChildMenuByName("VoiceMorphing", TRUE); + + if (NULL != voice_morphing_menup) + { + S32 items = voice_morphing_menup->getItemCount(); + if (items > 0) + { + voice_morphing_menup->erase(1, items - 3, false); + + S32 pos = 1; + for (voice_effect_list_t::const_iterator it = effect_list.begin(); it != effect_list.end(); ++it) + { + LLMenuItemCheckGL::Params p; + p.name = it->first; + p.label = it->first; + p.on_check.function(boost::bind(&LLVivoxVoiceClient::onCheckVoiceEffect, this, it->first)); + p.on_click.function(boost::bind(&LLVivoxVoiceClient::onClickVoiceEffect, this, it->first)); + LLMenuItemCheckGL * voice_effect_itemp = LLUICtrlFactory::create<LLMenuItemCheckGL>(p); + voice_morphing_menup->insert(pos++, voice_effect_itemp, false); + } + + voice_morphing_menup->needsArrange(); + } + } + } + } + } +} + void LLVivoxVoiceClient::notifyVoiceFontObservers() { LL_DEBUGS("Voice") << "Notifying voice effect observers. Lists changed: " << mVoiceFontListDirty << LL_ENDL; + updateVoiceMorphingMenu(); + for (voice_font_observer_set_t::iterator it = mVoiceFontObservers.begin(); it != mVoiceFontObservers.end(); ) diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index 69f33df94b..574027de42 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -246,6 +246,8 @@ public: //@} + bool onCheckVoiceEffect(const std::string& voice_effect_name); + void onClickVoiceEffect(const std::string& voice_effect_name); protected: ////////////////////// @@ -854,6 +856,7 @@ private: void accountGetTemplateFontsSendMessage(); void sessionSetVoiceFontSendMessage(sessionState *session); + void updateVoiceMorphingMenu(); void notifyVoiceFontObservers(); typedef enum e_voice_font_type diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml index 35cb2670d0..146c3d7e30 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_effect.xml @@ -5,12 +5,13 @@ height="500" name="voice_effects" help_topic="voice_effects" - title="VOICE MORPHING" + title="VOICE MORPHING PREVIEW" background_visible="true" label="Places" layout="topleft" min_height="360" min_width="200" + save_rect="true" width="300"> <string name="no_voice_effect"> (No Voice Morph) diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 8d5e3f0b5d..10fd8138d2 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -268,17 +268,36 @@ parameter="conversation" /> </menu_item_check> <menu_item_separator/> - <menu_item_check - label="Voice morphing..." - name="ShowVoice" + <menu + label="Voice morphing" + name="VoiceMorphing" visibility_control="VoiceMorphingEnabled"> - <menu_item_check.on_check - function="Floater.Visible" - parameter="voice_effect" /> - <menu_item_check.on_click - function="Floater.Toggle" - parameter="voice_effect" /> - </menu_item_check> + <menu_item_check + label="No voice morphing" + name="NoVoiceMorphing"> + <menu_item_check.on_check + function="Communicate.VoiceMorphing.NoVoiceMorphing.Check" /> + <menu_item_check.on_click + function="Communicate.VoiceMorphing.NoVoiceMorphing.Click" /> + </menu_item_check> + <menu_item_separator/> + <menu_item_check + label="Preview..." + name="Preview"> + <menu_item_check.on_check + function="Floater.Visible" + parameter="voice_effect" /> + <menu_item_check.on_click + function="Floater.Toggle" + parameter="voice_effect" /> + </menu_item_check> + <menu_item_call + label="Subscribe..." + name="Subscribe"> + <menu_item_call.on_click + function="Communicate.VoiceMorphing.Subscribe" /> + </menu_item_call> + </menu> <menu_item_check label="Gestures..." name="Gestures" -- cgit v1.2.3 From 52018b79bdd715dbb7bd42792447566347b641d5 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Sun, 20 Jan 2013 14:16:53 -0800 Subject: CHUI-379 : Fix Mac and Linux build failures --- indra/llui/llmenugl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 2ea25648df..27f6ac5b80 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -2471,13 +2471,13 @@ void LLMenuGL::erase( S32 begin, S32 end, bool arrange/* = true*/) return; } - item_list_t::const_iterator start_position = mItems.begin(); + item_list_t::iterator start_position = mItems.begin(); std::advance(start_position, begin); - item_list_t::const_iterator end_position = mItems.begin(); + item_list_t::iterator end_position = mItems.begin(); std::advance(end_position, end); - for (item_list_t::const_iterator position_iter = start_position; position_iter != end_position; position_iter++) + for (item_list_t::iterator position_iter = start_position; position_iter != end_position; position_iter++) { LLUICtrl::removeChild(*position_iter); } @@ -2500,7 +2500,7 @@ void LLMenuGL::insert( S32 position, LLView * ctrl, bool arrange /*= true*/ ) return; } - item_list_t::const_iterator position_iter = mItems.begin(); + item_list_t::iterator position_iter = mItems.begin(); std::advance(position_iter, position); mItems.insert(position_iter, item); LLUICtrl::addChild(item); -- cgit v1.2.3 From 824457f98c93a2f48f402740982a410b9fbc3487 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Mon, 21 Jan 2013 14:10:12 +0200 Subject: CHUI-567 FIXED Menu items are moved to Participant view menu --- indra/newview/llfloaterimcontainer.cpp | 13 ++++++++++++- indra/newview/llfloaterimsessiontab.cpp | 21 --------------------- indra/newview/llfloaterimsessiontab.h | 4 ---- .../default/xui/en/menu_im_session_showmodes.xml | 19 +------------------ .../skins/default/xui/en/menu_participant_view.xml | 20 ++++++++++++++++++++ 5 files changed, 33 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 8f290ae7c1..f73db6b166 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -813,6 +813,10 @@ void LLFloaterIMContainer::onCustomAction(const LLSD& userdata) floater_prefp->selectPrivacyPanel(); } } + if ("Translating.Toggle" == command) + { + gSavedSettings.setBOOL("TranslateChat", !gSavedSettings.getBOOL("TranslateChat")); + } } BOOL LLFloaterIMContainer::isActionChecked(const LLSD& userdata) @@ -843,7 +847,14 @@ BOOL LLFloaterIMContainer::isActionChecked(const LLSD& userdata) { return (order.getSortOrderParticipants() == LLConversationFilter::SO_DISTANCE); } - + if ("Translating.Enabled" == command) + { + return gSavedPerAccountSettings.getBOOL("TranslatingEnabled"); + } + if ("Translating.On" == command) + { + return gSavedSettings.getBOOL("TranslateChat"); + } return FALSE; } diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index bc5b8c334d..0cdfde3975 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -72,12 +72,6 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2)); - mEnableCallbackRegistrar.add("Translating.Enabled", - boost::bind(&LLFloaterIMSessionTab::isTranslatingEnabled, this, _2)); - mEnableCallbackRegistrar.add("Translating.On", - boost::bind(&LLFloaterIMSessionTab::isTranslationOn, this, _2)); - mCommitCallbackRegistrar.add("Translating.Toggle", - boost::bind(&LLFloaterIMSessionTab::toggleTranslation, this, _2)); // Right click menu handling mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem, this, _2)); @@ -551,11 +545,6 @@ void LLFloaterIMSessionTab::onIMSessionMenuItemClicked(const LLSD& userdata) LLFloaterIMSessionTab::processChatHistoryStyleUpdate(); } -void LLFloaterIMSessionTab::toggleTranslation(const LLSD& userdata) -{ - gSavedSettings.setBOOL("TranslateChat", !gSavedSettings.getBOOL("TranslateChat")); -} - bool LLFloaterIMSessionTab::onIMCompactExpandedMenuItemCheck(const LLSD& userdata) { std::string item = userdata.asString(); @@ -579,16 +568,6 @@ bool LLFloaterIMSessionTab::onIMShowModesMenuItemEnable(const LLSD& userdata) return (plain_text && (is_not_names || mIsP2PChat)); } -bool LLFloaterIMSessionTab::isTranslatingEnabled(const LLSD& userdata) -{ - return gSavedPerAccountSettings.getBOOL("TranslatingEnabled"); -} - -bool LLFloaterIMSessionTab::isTranslationOn(const LLSD& userdata) -{ - return gSavedSettings.getBOOL("TranslateChat"); -} - void LLFloaterIMSessionTab::hideOrShowTitle() { const LLFloater::Params& default_params = LLFloater::getDefaultParams(); diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 05da0f98bc..0fa99a46be 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -109,12 +109,8 @@ protected: // bool onIMShowModesMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemEnable(const LLSD& userdata); - bool isTranslatingEnabled(const LLSD& userdata); - bool isTranslationOn(const LLSD& userdata); static void onSlide(LLFloaterIMSessionTab *self); - void toggleTranslation(const LLSD& userdata); - // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); diff --git a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml index f2a8b39b04..b0adca0e0e 100644 --- a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml +++ b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml @@ -45,22 +45,5 @@ <menu_item_check.on_enable function="IMSession.Menu.ShowModes.Enable" parameter="IMShowNamesForP2PConv" /> - </menu_item_check> - <menu_item_separator layout="topleft" /> - <menu_item_check name="Translate_chat" label="Translate chat"> - <menu_item_check.on_click - function="Translating.Toggle" /> - <menu_item_check.on_check - function="Translating.On" /> - <menu_item_check.on_enable - function="Translating.Enabled" /> - </menu_item_check> - <menu_item_check name="Translation_settings" label="Translation settings..."> - <menu_item_check.on_check - function="Floater.Visible" - parameter="prefs_translation" /> - <menu_item_check.on_click - function="Floater.Toggle" - parameter="prefs_translation" /> - </menu_item_check> + </menu_item_check> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml index 2f2bafb95d..7ea87ee05c 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_view.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -89,4 +89,24 @@ function="Avatar.EnableItem" parameter="conversation_log" /> </menu_item_check> + <menu_item_separator layout="topleft" /> + <menu_item_check name="Translate_chat" label="Translate Nearby chat"> + <menu_item_check.on_click + function="IMFloaterContainer.Action" + parameter="Translating.Toggle" /> + <menu_item_check.on_check + function="IMFloaterContainer.Check" + parameter="Translating.On" /> + <menu_item_check.on_enable + function="IMFloaterContainer.Check" + parameter="Translating.Enabled" /> + </menu_item_check> + <menu_item_check name="Translation_settings" label="Translation settings..."> + <menu_item_check.on_check + function="Floater.Visible" + parameter="prefs_translation" /> + <menu_item_check.on_click + function="Floater.Toggle" + parameter="prefs_translation" /> + </menu_item_check> </toggleable_menu> -- cgit v1.2.3 From dc19930f1586dcc879a8e9c1653be8f1b47e4795 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 21 Jan 2013 18:24:59 +0200 Subject: CHUI-655, CHUI-648 ADD FIX Conversation is not opened while first click on message from object; "Nearby Chat" dialog does not open while first attempt when pressing Ctrl+H keyboard shortcut : Fixed forced change visibility. --- indra/newview/llfloaterimcontainer.cpp | 4 +++- indra/newview/llfloaterimsessiontab.cpp | 11 +++++++---- indra/newview/llfloaterimsessiontab.h | 1 + 3 files changed, 11 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index f73db6b166..565063a0ea 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -431,7 +431,9 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event) return false; } LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); - LLFloaterIMSessionTab *conversation_floater = (session_id.isNull() ? (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")) : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(session_id))); + LLFloaterIMSessionTab *conversation_floater = (session_id.isNull() ? + (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")) + : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(session_id))); if (type == "remove_participant") { diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 0cdfde3975..37404ab716 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -60,6 +60,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) , mInputEditorTopPad(0) , mRefreshTimer(new LLTimer()) , mIsHostAttached(false) + , mHasVisibleBeenInitialized(false) { setAutoFocus(FALSE); mSession = LLIMModel::getInstance()->findIMSession(mSessionID); @@ -120,12 +121,14 @@ LLFloaterIMSessionTab* LLFloaterIMSessionTab::getConversation(const LLUUID& uuid void LLFloaterIMSessionTab::setVisible(BOOL visible) { - LLTransientDockableFloater::setVisible(visible); - - if(visible) + if(visible && !mHasVisibleBeenInitialized) { - LLFloaterIMSessionTab::addToHost(mSessionID); + mHasVisibleBeenInitialized = true; + LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->setVisible(true); + LLFloaterIMSessionTab::addToHost(mSessionID); } + + LLTransientDockableFloater::setVisible(visible); } /*virtual*/ diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 0fa99a46be..beaffc14a6 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -182,6 +182,7 @@ private: bool checkIfTornOff(); bool mIsHostAttached; + bool mHasVisibleBeenInitialized; LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. }; -- cgit v1.2.3 From 9e6677ffc29b779f7b47228cf96c5bcdc867669c Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Tue, 22 Jan 2013 17:53:18 +0200 Subject: CHUI-692 FIXED Arrow keys will move avatar while IM container, nearby chat or IM session floater is in focus. --- indra/newview/llviewerwindow.cpp | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 2d5634a41d..36ddf26c82 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2503,22 +2503,14 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) return TRUE; } - LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); + LLFloater* focused_floaterp = gFloaterView->getFocusedFloater(); + std::string focusedFloaterName = (focused_floaterp ? focused_floaterp->getInstanceName() : ""); - // Traverses up the hierarchy if( keyboard_focus ) { - if (nearby_chat) - { - LLChatEntry* chat_editor = nearby_chat->getChatBox(); - - // arrow keys move avatar while chatting hack - if (chat_editor && chat_editor->hasFocus()) + if ((focusedFloaterName == "nearby_chat") || (focusedFloaterName == "im_container") || (focusedFloaterName == "impanel")) { - // If text field is empty, there's no point in trying to move - // cursor with arrow keys, so allow movement - if (chat_editor->getText().empty() - || gSavedSettings.getBOOL("ArrowKeysAlwaysMove")) + if (gSavedSettings.getBOOL("ArrowKeysAlwaysMove")) { // let Control-Up and Control-Down through for chat line history, if (!(key == KEY_UP && mask == MASK_CONTROL) @@ -2540,7 +2532,6 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) break; } } - } } } @@ -2575,6 +2566,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) { // Initialize nearby chat if it's missing + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); if (!nearby_chat) { LLSD name("im_container"); -- cgit v1.2.3 From 651f230500646dfcd695a9caa0650f81fa29b9bf Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Wed, 23 Jan 2013 10:23:16 +0200 Subject: CHUI-678 (Voice indicators not shown for participants in torn off conference conversations) --- indra/newview/llconversationview.cpp | 32 ++++++++++++++++++++++++++-- indra/newview/llconversationview.h | 4 ++++ indra/newview/llspeakingindicatormanager.cpp | 13 ++--------- 3 files changed, 36 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 903dd2a407..bdd5dfc51a 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -82,6 +82,7 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes mVoiceClientObserver(NULL), mCollapsedMode(false), mHasArrow(true), + mIsInActiveVoiceChannel(false), mFlashStateOn(false), mFlashStarted(false) { @@ -178,6 +179,7 @@ BOOL LLConversationViewSession::postBuild() LLIconCtrl* icon = mItemPanel->getChild<LLIconCtrl>("nearby_chat_icon"); icon->setVisible(true); mSpeakingIndicator->setSpeakerId(gAgentID, LLUUID::null, true); + mIsInActiveVoiceChannel = true; if(LLVoiceClient::instanceExists()) { LLNearbyVoiceClientStatusObserver* mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this); @@ -232,6 +234,8 @@ void LLConversationViewSession::draw() (*iit)->setVisible(draw_children); } + refresh(); + LLView::draw(); } @@ -351,6 +355,25 @@ void LLConversationViewSession::refresh() // Update all speaking indicators LLSpeakingIndicatorManager::updateSpeakingIndicators(); + + // we should show indicator for specified voice session only if this is current channel. EXT-5562. + if (!mIsInActiveVoiceChannel) + { + if (mSpeakingIndicator) + { + mSpeakingIndicator->setVisible(false); + } + LLConversationViewParticipant* participant = NULL; + items_t::const_iterator iter; + for (iter = getItemsBegin(); iter != getItemsEnd(); iter++) + { + participant = dynamic_cast<LLConversationViewParticipant*>(*iter); + if (participant) + { + participant->hideSpeakingIndicator(); + } + } + } // Do the regular upstream refresh LLFolderViewFolder::refresh(); @@ -362,8 +385,8 @@ void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& sessi if (vmi) { - bool is_active = vmi->getUUID() == session_id; - mCallIconLayoutPanel->setVisible(is_active); + mIsInActiveVoiceChannel = vmi->getUUID() == session_id; + mCallIconLayoutPanel->setVisible(mIsInActiveVoiceChannel); } } @@ -623,5 +646,10 @@ LLView* LLConversationViewParticipant::getItemChildView(EAvatarListItemChildInde return child_view; } +void LLConversationViewParticipant::hideSpeakingIndicator() +{ + mSpeakingIndicator->setVisible(false); +} + // EOF diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 5f6acfb9ab..f2fa2fb042 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -102,6 +102,8 @@ private: bool mCollapsedMode; bool mHasArrow; + bool mIsInActiveVoiceChannel; + LLVoiceClientStatusObserver* mVoiceClientObserver; boost::signals2::connection mActiveVoiceChannelConnection; @@ -137,6 +139,8 @@ public: /*virtual*/ S32 getLabelXPos(); + void hideSpeakingIndicator(); + protected: friend class LLUICtrlFactory; LLConversationViewParticipant( const Params& p ); diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 76da7d1aee..07e9371124 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -237,18 +237,9 @@ void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& spea { was_found = true; LLSpeakingIndicator* indicator = (*it_indicator).second; + was_switched_on = was_switched_on || switch_on; - BOOL switch_current_on = switch_on; - - // we should show indicator for specified voice session only if this is current channel. EXT-5562. - if (switch_current_on) - { - switch_current_on = indicator->getTargetSessionID() == session_id; - LL_DEBUGS("SpeakingIndicator") << "Session: " << session_id << ", target: " << indicator->getTargetSessionID() << ", the same? = " << switch_current_on << LL_ENDL; - } - was_switched_on = was_switched_on || switch_current_on; - - indicator->switchIndicator(switch_current_on); + indicator->switchIndicator(switch_on); } if (was_found) -- cgit v1.2.3 From e6000d5930dd646bb15951336670bab4950515d8 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Wed, 23 Jan 2013 14:32:18 +0200 Subject: CHUI-424 FIXED Args for appendMessage() are added to respect Compact/Expanded mode --- indra/newview/llfloaterconversationpreview.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index c93181c0a1..48e0caa0ce 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -152,7 +152,13 @@ void LLFloaterConversationPreview::showHistory() chat.mSourceType = LLFloaterIMNearbyChat::isWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT; } - mChatHistory->appendMessage(chat); + LLSD chat_args; + chat_args["use_plain_text_chat_history"] = + gSavedSettings.getBOOL("PlainTextChatHistory"); + chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); + chat_args["show_names_for_p2p_conv"] = gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + + mChatHistory->appendMessage(chat,chat_args); } } -- cgit v1.2.3 From d0204ab367f5ceb5eab89e2273b897975acbfe5a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 23 Jan 2013 09:51:17 -0800 Subject: CHUI-687: Problem: User sees inventory offer notifications for deleted items when logging in from do not disturb mode. Resolution: If an item that is deletes has a DND notification saved, then remove that notification so that it doesn't appear onec the user exists DND mode. --- indra/llui/llfolderview.cpp | 6 +++++- indra/llui/llfolderview.h | 3 ++- .../newview/lldonotdisturbnotificationstorage.cpp | 22 +++++++++++++--------- indra/newview/lldonotdisturbnotificationstorage.h | 6 +++++- indra/newview/llfloaterimcontainer.cpp | 2 +- indra/newview/llimview.cpp | 2 +- indra/newview/llinventoryfunctions.cpp | 22 ++++++++++++++++++++++ indra/newview/llinventoryfunctions.h | 1 + 8 files changed, 50 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 324142f6c3..7c1ca017d7 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -399,6 +399,10 @@ LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) return NULL; } +LLFolderView::selected_items_t& LLFolderView::getSelectedItems( void ) +{ + return mSelectedItems; +} // Record the selected item and pass it down the hierachy. BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, @@ -752,8 +756,8 @@ void LLFolderView::removeSelectedItems() { // change selection on successful delete setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel->hasFocus()); - } } + } arrangeAll(); } else if (count > 1) diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index a6e0a3b4c0..05b2abb9d3 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -101,6 +101,7 @@ public: }; friend class LLFolderViewScrollContainer; + typedef std::deque<LLFolderViewItem*> selected_items_t; LLFolderView(const Params&); virtual ~LLFolderView( void ); @@ -138,6 +139,7 @@ public: // Get the last selected item virtual LLFolderViewItem* getCurSelectedItem( void ); + selected_items_t& getSelectedItems( void ); // Record the selected item and pass it down the hierarchy. virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, @@ -261,7 +263,6 @@ protected: protected: LLHandle<LLView> mPopupMenuHandle; - typedef std::deque<LLFolderViewItem*> selected_items_t; selected_items_t mSelectedItems; BOOL mKeyboardSelection; BOOL mAllowMultiSelect; diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 824ff67972..abceb5c10d 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -43,7 +43,8 @@ #include "lluuid.h" static const F32 DND_TIMER = 3.0; -const std::string toastName = "IMToast"; +const char * LLDoNotDisturbNotificationStorage::toastName = "IMToast"; +const char * LLDoNotDisturbNotificationStorage::offerName = "UserGiveItem"; LLDoNotDisturbNotificationStorageTimer::LLDoNotDisturbNotificationStorageTimer() : LLEventTimer(DND_TIMER) { @@ -72,6 +73,8 @@ LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")) , mDirty(false) { + nameToPayloadParameterMap[toastName] = "SESSION_ID"; + nameToPayloadParameterMap[offerName] = "object_id"; } LLDoNotDisturbNotificationStorage::~LLDoNotDisturbNotificationStorage() @@ -234,15 +237,16 @@ LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChan return channelPtr; } -void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& session_id) +void LLDoNotDisturbNotificationStorage::removeNotification(const char * name, const LLUUID& id) { LLNotifications& instance = LLNotifications::instance(); LLNotificationChannelPtr channelPtr = getCommunicationChannel(); LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get()); LLNotificationPtr notification; - LLSD substitutions; - LLUUID notificationSessionID; + LLSD payload; + LLUUID notificationObjectID; std::string notificationName; + std::string payloadVariable = nameToPayloadParameterMap[name]; LLCommunicationChannel::history_list_t::iterator it; std::vector<LLCommunicationChannel::history_list_t::iterator> itemsToRemove; @@ -252,18 +256,18 @@ void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& sessi ++it) { notification = it->second; - substitutions = notification->getSubstitutions(); - notificationSessionID = substitutions["SESSION_ID"].asUUID(); + payload = notification->getPayload(); + notificationObjectID = payload[payloadVariable].asUUID(); notificationName = notification->getName(); - if(notificationName == toastName - && session_id == notificationSessionID) + if(notificationName == name + && id == notificationObjectID) { itemsToRemove.push_back(it); } } - + //Remove the notifications if(itemsToRemove.size()) { diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h index fd7cc7ee82..6e68b0d1be 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.h +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -49,6 +49,9 @@ class LLDoNotDisturbNotificationStorage : public LLSingleton<LLDoNotDisturbNotif { LOG_CLASS(LLDoNotDisturbNotificationStorage); public: + static const char * toastName; + static const char * offerName; + LLDoNotDisturbNotificationStorage(); ~LLDoNotDisturbNotificationStorage(); @@ -58,7 +61,7 @@ public: void saveNotifications(); void loadNotifications(); void updateNotifications(); - void removeIMNotification(const LLUUID& session_id); + void removeNotification(const char * name, const LLUUID& id); protected: @@ -68,6 +71,7 @@ private: LLNotificationChannelPtr getCommunicationChannel() const; bool onChannelChanged(const LLSD& pPayload); + std::map<std::string, std::string> nameToPayloadParameterMap; }; #endif // LL_LLDONOTDISTURBNOTIFICATIONSTORAGE_H diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index f73db6b166..6e9f7a380f 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1316,7 +1316,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal if(gAgent.isDoNotDisturb() && session_id.notNull()) { - LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); + LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, session_id); } } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d0a8dfc0c8..cb03c1d234 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -144,7 +144,7 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id, args["FROM"] = av_name.getCompleteName(); args["FROM_ID"] = msg["from_id"]; args["SESSION_ID"] = msg["session_id"]; - LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); + LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); } void on_new_message(const LLSD& msg) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 6474d56414..7f9474ae70 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -46,6 +46,7 @@ #include "llappearancemgr.h" #include "llappviewer.h" #include "llclipboard.h" +#include "lldonotdisturbnotificationstorage.h" #include "llfloaterinventory.h" #include "llfloatersidepanelcontainer.h" #include "llfocusmgr.h" @@ -1132,11 +1133,32 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root } } +void LLInventoryAction::removeItemFromDND(LLFolderView* root) +{ + //Get selected items + LLFolderView::selected_items_t selectedItems = root->getSelectedItems(); + LLFolderViewModelItemInventory * viewModel = NULL; + + //If user is in DND and deletes item, make sure the notification is not displayed by removing the notification + //from DND history and .xml file. Once this is done, upon exit of DND mode the item deleted will not show a notification. + for(LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) + { + viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*it)->getViewModelItem()); + + if(viewModel && viewModel->getUUID().notNull()) + { + //Will remove the item offer notification + LLDoNotDisturbNotificationStorage::instance().removeNotification(LLDoNotDisturbNotificationStorage::offerName, viewModel->getUUID()); + } + } +} + void LLInventoryAction::onItemsRemovalConfirmation( const LLSD& notification, const LLSD& response, LLFolderView* root ) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { + removeItemFromDND(root); root->removeSelectedItems(); } } diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 11fc17ce9b..f1066a4dc9 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -433,6 +433,7 @@ struct LLInventoryAction static void doToSelected(class LLInventoryModel* model, class LLFolderView* root, const std::string& action); static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLFolderView* root); + static void removeItemFromDND(LLFolderView* root); }; -- cgit v1.2.3 From 6bb1c88db2b329665d547eb86d083a062732a8dd Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 23 Jan 2013 10:13:20 -0800 Subject: CHUI-480 : Fixed : Fetch group membership when starting group chat and populate speakers list --- indra/newview/llspeakers.cpp | 51 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 88f29d7587..a90d9111cb 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -31,6 +31,7 @@ #include "llagent.h" #include "llappviewer.h" #include "llimview.h" +#include "llgroupmgr.h" #include "llsdutil.h" #include "lluicolortable.h" #include "llviewerobjectlist.h" @@ -321,7 +322,11 @@ LLSpeakerMgr::~LLSpeakerMgr() LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type) { - if (id.isNull()) return NULL; + LLUUID session_id = getSessionID(); + if (id.isNull() || (id == session_id)) + { + return NULL; + } LLPointer<LLSpeaker> speakerp; if (mSpeakers.find(id) == mSpeakers.end()) @@ -527,22 +532,52 @@ void LLSpeakerMgr::updateSpeakerList() LLUUID session_id = getSessionID(); if ((mSpeakers.size() == 0) && (!session_id.isNull())) { - // If the list is empty, we update it with whatever was used to initiate the call so that it doesn't stay empty too long. + // If the list is empty, we update it with whatever we have locally so that it doesn't stay empty too long. // *TODO: Fix the server side code that sometimes forgets to send back the list of agents after a chat started // (IOW, fix why we get no ChatterBoxSessionAgentListUpdates message after the initial ChatterBoxSessionStartReply) LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); - for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it) + if (session->isGroupSessionType()) + { + // For groups, we need to hit the group manager + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id); + if (!gdatap) + { + // Request the data the first time around + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(session_id); + } + else if (gdatap->isMemberDataComplete() && !gdatap->mMembers.empty()) + { + LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin(); + while (member_it != gdatap->mMembers.end()) + { + LLGroupMemberData* member = member_it->second; + // Add only the members who are online + if (member->getOnlineStatus() == "Online") + { + setSpeaker(member_it->first, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + } + ++member_it; + } + // Always add the current agent (it has to be there no matter what...) + setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + } + } + else { - // Add buddies if they are on line, add any other avatar. - if (!LLAvatarTracker::instance().isBuddy(*it) || LLAvatarTracker::instance().isBuddyOnline(*it)) + // For all other types (ad-hoc, P2P, avaline), we use the initial targets list + for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it) { - setSpeaker(*it, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + // Add buddies if they are on line, add any other avatar. + if (!LLAvatarTracker::instance().isBuddy(*it) || LLAvatarTracker::instance().isBuddyOnline(*it)) + { + setSpeaker(*it, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + } } + // Always add the current agent (it has to be there no matter what...) + setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } } } - // Finally, always add the current agent (it has to be there no matter what...) - setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp) -- cgit v1.2.3 From 0911dafd81b8360235eb6f6b85fac7153a5d4a02 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 23 Jan 2013 11:39:33 -0800 Subject: CHUI-687: post code review changes. Now upon deletion of an item, DND mode must be enabled in order to remove a notification from the DND history. --- .../newview/lldonotdisturbnotificationstorage.cpp | 2 +- indra/newview/llinventoryfunctions.cpp | 27 +++++++++++++--------- 2 files changed, 17 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index abceb5c10d..15c42e8285 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -260,7 +260,7 @@ void LLDoNotDisturbNotificationStorage::removeNotification(const char * name, co notificationObjectID = payload[payloadVariable].asUUID(); notificationName = notification->getName(); - if(notificationName == name + if((notificationName == name) && id == notificationObjectID) { itemsToRemove.push_back(it); diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 7f9474ae70..ad0a730dd1 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1135,20 +1135,23 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root void LLInventoryAction::removeItemFromDND(LLFolderView* root) { - //Get selected items - LLFolderView::selected_items_t selectedItems = root->getSelectedItems(); - LLFolderViewModelItemInventory * viewModel = NULL; - - //If user is in DND and deletes item, make sure the notification is not displayed by removing the notification - //from DND history and .xml file. Once this is done, upon exit of DND mode the item deleted will not show a notification. - for(LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) + if(gAgent.isDoNotDisturb()) { - viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*it)->getViewModelItem()); + //Get selected items + LLFolderView::selected_items_t selectedItems = root->getSelectedItems(); + LLFolderViewModelItemInventory * viewModel = NULL; - if(viewModel && viewModel->getUUID().notNull()) + //If user is in DND and deletes item, make sure the notification is not displayed by removing the notification + //from DND history and .xml file. Once this is done, upon exit of DND mode the item deleted will not show a notification. + for(LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) { - //Will remove the item offer notification - LLDoNotDisturbNotificationStorage::instance().removeNotification(LLDoNotDisturbNotificationStorage::offerName, viewModel->getUUID()); + viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*it)->getViewModelItem()); + + if(viewModel && viewModel->getUUID().notNull()) + { + //Will remove the item offer notification + LLDoNotDisturbNotificationStorage::instance().removeNotification(LLDoNotDisturbNotificationStorage::offerName, viewModel->getUUID()); + } } } } @@ -1158,6 +1161,8 @@ void LLInventoryAction::onItemsRemovalConfirmation( const LLSD& notification, co S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { + //Need to remove item from DND before item is removed from root folder view + //because once removed from root folder view the item is no longer a selected item removeItemFromDND(root); root->removeSelectedItems(); } -- cgit v1.2.3 From 46a74c4e01e19c07b5ee966ebe9882c4209dc89c Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 23 Jan 2013 17:45:25 -0800 Subject: CHUI-480 : Fixed : Flagged when local update is made and prevent doing it multiple times, allow group to graw by 1 (me) then the rest (prevent having group remaining hidden). --- indra/newview/llspeakers.cpp | 34 +++++++++++++++++++++------------- indra/newview/llspeakers.h | 1 + 2 files changed, 22 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index a90d9111cb..a2d8874cea 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -306,9 +306,10 @@ private: // LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) : - mVoiceChannel(channelp) -, mVoiceModerated(false) -, mModerateModeHandledFirstTime(false) + mVoiceChannel(channelp), + mVoiceModerated(false), + mModerateModeHandledFirstTime(false), + mSpeakerListUpdated(false) { static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0); @@ -530,15 +531,16 @@ void LLSpeakerMgr::updateSpeakerList() { // If not, check if the list is empty, except if it's Nearby Chat (session_id NULL). LLUUID session_id = getSessionID(); - if ((mSpeakers.size() == 0) && (!session_id.isNull())) + if (!session_id.isNull() && !mSpeakerListUpdated) { // If the list is empty, we update it with whatever we have locally so that it doesn't stay empty too long. - // *TODO: Fix the server side code that sometimes forgets to send back the list of agents after a chat started + // *TODO: Fix the server side code that sometimes forgets to send back the list of participants after a chat started. // (IOW, fix why we get no ChatterBoxSessionAgentListUpdates message after the initial ChatterBoxSessionStartReply) LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); - if (session->isGroupSessionType()) + if (session->isGroupSessionType() && (mSpeakers.size() <= 1)) { - // For groups, we need to hit the group manager + // For groups, we need to hit the group manager. + // Note: The session uuid and the group uuid are actually one and the same. If that was to change, this will fail. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id); if (!gdatap) { @@ -547,6 +549,7 @@ void LLSpeakerMgr::updateSpeakerList() } else if (gdatap->isMemberDataComplete() && !gdatap->mMembers.empty()) { + // Add group members when we get the complete list (note: can take a while before we get that list) LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin(); while (member_it != gdatap->mMembers.end()) { @@ -558,13 +561,12 @@ void LLSpeakerMgr::updateSpeakerList() } ++member_it; } - // Always add the current agent (it has to be there no matter what...) - setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + mSpeakerListUpdated = true; } } - else + else if (mSpeakers.size() == 0) { - // For all other types (ad-hoc, P2P, avaline), we use the initial targets list + // For all other session type (ad-hoc, P2P, avaline), we use the initial participants targets list for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it) { // Add buddies if they are on line, add any other avatar. @@ -573,11 +575,17 @@ void LLSpeakerMgr::updateSpeakerList() setSpeaker(*it, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } } - // Always add the current agent (it has to be there no matter what...) - setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + mSpeakerListUpdated = true; + } + else + { + // The list has been updated the normal way (i.e. by a ChatterBoxSessionAgentListUpdates received from the server) + mSpeakerListUpdated = true; } } } + // Always add the current agent (it has to be there...). Will do nothing if already there. + setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp) diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 7d518fe07b..5f5095097e 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -263,6 +263,7 @@ protected: typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t; speaker_map_t mSpeakers; + bool mSpeakerListUpdated; speaker_list_t mSpeakersSorted; LLFrameTimer mSpeechTimer; -- cgit v1.2.3 From a6c4d127dd6ad66f9953344387e100bcff000ce5 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Fri, 25 Jan 2013 14:33:44 +0200 Subject: CHUI-697 FIXED We don't need to update form for Inventory offer notification --- indra/newview/llviewermessage.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index d235ba5f96..8489e92d15 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1649,12 +1649,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& delete this; } - if (notification_ptr != NULL) - { - notification_ptr->updateForm(modified_form); - notification_ptr->repost(); - } - return false; } -- cgit v1.2.3 From daa9db305a5ae2c0c5b0c2425d6482de6dee7b2c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 23 Jan 2013 19:47:01 +0200 Subject: CHUI-695 Viewer crashes after attempt to accept a friendship in IM: remove an infinity loop of reshape() --- indra/newview/lltoastnotifypanel.cpp | 6 ++---- indra/newview/lltoastpanel.cpp | 4 +++- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 268b68b539..0aab514531 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -537,11 +537,9 @@ LLIMToastNotifyPanel::~LLIMToastNotifyPanel() } void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) - { - LLToastPanel::reshape(width, height, called_from_parent); - +{ snapToMessageHeight(mTextBox, MAX_LENGTH); - } +} void LLIMToastNotifyPanel::compactButtons() { diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index 187aee207c..54d3912136 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -81,7 +81,9 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount) S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); heightDelta = newTextHeight - oldTextHeight; - S32 new_panel_height = llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT); + S32 new_panel_height = llmin( + llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT), + maxTextHeight); //reshape the panel with new height if (new_panel_height != getRect().getHeight()) -- cgit v1.2.3 From 977d318ac8ccb756bb90a8572f01bc6825b5d0a3 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Wed, 23 Jan 2013 20:22:28 +0000 Subject: CHUI-291 FIX New auto-replace feature does not work with chui text input boxes in conversation floater Moved autoreplace hooks from LLLineEditor to LLTextEditor, and modified LLAutoReplace accordingly --- indra/llui/lllineeditor.cpp | 9 +----- indra/llui/lllineeditor.h | 3 -- indra/llui/lltexteditor.cpp | 10 ++++++- indra/llui/lltexteditor.h | 5 ++++ indra/newview/llautoreplace.cpp | 50 ++++++++++++-------------------- indra/newview/llautoreplace.h | 51 +++++++++++++++------------------ indra/newview/llfloaterimnearbychat.cpp | 2 ++ indra/newview/llfloaterimsession.cpp | 6 ---- 8 files changed, 58 insertions(+), 78 deletions(-) (limited to 'indra') diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 48d49af588..2e64be89fa 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -157,8 +157,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mHighlightColor(p.highlight_color()), mPreeditBgColor(p.preedit_bg_color()), mGLFont(p.font), - mContextMenuHandle(), - mAutoreplaceCallback() + mContextMenuHandle() { llassert( mMaxLengthBytes > 0 ); @@ -971,12 +970,6 @@ void LLLineEditor::addChar(const llwchar uni_char) LLUI::reportBadKeystroke(); } - if (!mReadOnly && mAutoreplaceCallback != NULL) - { - // call callback - mAutoreplaceCallback(mText, mCursorPos); - } - getWindow()->hideCursorUntilMouseMove(); } diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 71dd53f608..40f931ecc1 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -189,9 +189,6 @@ public: virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text ); virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); - typedef boost::function<void(LLUIString&, S32&)> autoreplace_callback_t; - autoreplace_callback_t mAutoreplaceCallback; - void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } void setLabel(const LLStringExplicit &new_label) { mLabel = new_label; } const std::string& getLabel() { return mLabel.getString(); } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index d42d6473ed..d297e54f2f 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -246,7 +246,8 @@ LLTextEditor::Params::Params() } LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : - LLTextBase(p), + LLTextBase(p), + mAutoreplaceCallback(), mBaseDocIsPristine(TRUE), mPristineCmd( NULL ), mLastCmd( NULL ), @@ -1097,7 +1098,14 @@ void LLTextEditor::addChar(llwchar wc) } setCursorPos(mCursorPos + addChar( mCursorPos, wc )); + + if (!mReadOnly && mAutoreplaceCallback != NULL) + { + // call callback + mAutoreplaceCallback(getViewModel()->getEditableDisplay(), mCursorPos); + } } + void LLTextEditor::addLineBreakChar() { if( !getEnabled() ) diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index f8f636b876..ae5a983b60 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -157,6 +157,11 @@ public: BOOL isPristine() const; BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; } + // Autoreplace (formerly part of LLLineEditor) + typedef boost::function<void(LLWString&, S32&)> autoreplace_callback_t; + autoreplace_callback_t mAutoreplaceCallback; + void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } + // // Text manipulation // diff --git a/indra/newview/llautoreplace.cpp b/indra/newview/llautoreplace.cpp index d71cf290d6..94773e312c 100644 --- a/indra/newview/llautoreplace.cpp +++ b/indra/newview/llautoreplace.cpp @@ -30,29 +30,17 @@ #include "llviewercontrol.h" #include "llnotificationsutil.h" -LLAutoReplace* LLAutoReplace::sInstance; - const char* LLAutoReplace::SETTINGS_FILE_NAME = "autoreplace.xml"; -LLAutoReplace::LLAutoReplace() -{ -} - -LLAutoReplace::~LLAutoReplace() -{ - sInstance = NULL; -} - -void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos) +void LLAutoReplace::autoreplaceCallback(LLWString& inputText, S32& cursorPos) { static LLCachedControl<bool> perform_autoreplace(gSavedSettings, "AutoReplace"); if(perform_autoreplace) { S32 wordEnd = cursorPos-1; - LLWString text = inputText.getWString(); - bool atSpace = (text[wordEnd] == ' '); - bool haveWord = (LLWStringUtil::isPartOfWord(text[wordEnd])); + bool atSpace = (inputText[wordEnd] == ' '); + bool haveWord = (LLWStringUtil::isPartOfWord(inputText[wordEnd])); if (atSpace || haveWord) { @@ -60,7 +48,7 @@ void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos) { // find out if this space immediately follows a word wordEnd--; - haveWord = (LLWStringUtil::isPartOfWord(text[wordEnd])); + haveWord = (LLWStringUtil::isPartOfWord(inputText[wordEnd])); } if (haveWord) { @@ -68,14 +56,14 @@ void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos) std::string word; S32 wordStart = wordEnd; for ( S32 backOne = wordStart - 1; - backOne >= 0 && LLWStringUtil::isPartOfWord(text[backOne]); + backOne >= 0 && LLWStringUtil::isPartOfWord(inputText[backOne]); backOne-- ) { wordStart--; // walk wordStart back to the beginning of the word } LL_DEBUGS("AutoReplace")<<"wordStart: "<<wordStart<<" wordEnd: "<<wordEnd<<LL_ENDL; - std::string strText = std::string(text.begin(), text.end()); + std::string strText = std::string(inputText.begin(), inputText.end()); std::string lastWord = strText.substr(wordStart, wordEnd-wordStart+1); std::string replacementWord( mSettings.replaceWord( lastWord ) ); @@ -89,8 +77,7 @@ void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos) LLWString strOld = utf8str_to_wstring(lastWord); int size_change = strNew.size() - strOld.size(); - text.replace(wordStart,lastWord.length(),strNew); - inputText = wstring_to_utf8str(text); + inputText.replace(wordStart,lastWord.length(),strNew); cursorPos+=size_change; } } @@ -99,16 +86,6 @@ void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos) } } -LLAutoReplace* LLAutoReplace::getInstance() -{ - if(!sInstance) - { - sInstance = new LLAutoReplace(); - sInstance->loadFromSettings(); - } - return sInstance; -} - std::string LLAutoReplace::getUserSettingsFileName() { std::string path=gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); @@ -147,6 +124,15 @@ void LLAutoReplace::setSettings(const LLAutoReplaceSettings& newSettings) saveToUserSettings(); } +LLAutoReplace::LLAutoReplace() +{ +} + +void LLAutoReplace::initSingleton() +{ + loadFromSettings(); +} + void LLAutoReplace::loadFromSettings() { std::string filename=getUserSettingsFileName(); @@ -220,7 +206,7 @@ void LLAutoReplace::saveToUserSettings() std::string filename=getUserSettingsFileName(); llofstream file; file.open(filename.c_str()); - LLSDSerialize::toPrettyXML(mSettings.getAsLLSD(), file); + LLSDSerialize::toPrettyXML(mSettings.asLLSD(), file); file.close(); LL_INFOS("AutoReplace") << "settings saved to '" << filename << "'" << LL_ENDL; } @@ -801,7 +787,7 @@ LLSD LLAutoReplaceSettings::getExampleLLSD() return example; } -const LLSD& LLAutoReplaceSettings::getAsLLSD() +const LLSD& LLAutoReplaceSettings::asLLSD() { return mLists; } diff --git a/indra/newview/llautoreplace.h b/indra/newview/llautoreplace.h index f720cc4eda..bbb86294bc 100644 --- a/indra/newview/llautoreplace.h +++ b/indra/newview/llautoreplace.h @@ -132,7 +132,7 @@ class LLAutoReplaceSettings LLSD getExampleLLSD(); /// Get the actual settings as LLSD - const LLSD& getAsLLSD(); + const LLSD& asLLSD(); ///< @note for use only in AutoReplace::saveToUserSettings private: @@ -190,42 +190,37 @@ class LLAutoReplaceSettings */ class LLAutoReplace : public LLSingleton<LLAutoReplace> { - public: - LLAutoReplace(); - ~LLAutoReplace(); - - /// @return a pointer to the active instance - static LLAutoReplace* getInstance(); +public: + /// Callback that provides the hook for use in text entry methods + void autoreplaceCallback(LLWString& inputText, S32& cursorPos); - /// Callback that provides the hook for use in text entry methods - void autoreplaceCallback(LLUIString& inputText, S32& cursorPos); + /// Get a copy of the current settings + LLAutoReplaceSettings getSettings(); - /// Get a copy of the current settings - LLAutoReplaceSettings getSettings(); + /// Commit new settings after making changes + void setSettings(const LLAutoReplaceSettings& settings); - /// Commit new settings after making changes - void setSettings(const LLAutoReplaceSettings& settings); - - private: - friend class LLSingleton<LLAutoReplace>; - static LLAutoReplace* sInstance; ///< the active settings instance +private: + friend class LLSingleton<LLAutoReplace>; + LLAutoReplace(); + /*virtual*/ void initSingleton(); - LLAutoReplaceSettings mSettings; ///< configuration information + LLAutoReplaceSettings mSettings; ///< configuration information - /// Read settings from persistent storage - void loadFromSettings(); + /// Read settings from persistent storage + void loadFromSettings(); - /// Make the newSettings active and write them to user storage - void saveToUserSettings(); + /// Make the newSettings active and write them to user storage + void saveToUserSettings(); - /// Compute the user settings file name - std::string getUserSettingsFileName(); + /// Compute the user settings file name + std::string getUserSettingsFileName(); - /// Compute the (read-ony) application settings file name - std::string getAppSettingsFileName(); + /// Compute the (read-ony) application settings file name + std::string getAppSettingsFileName(); - /// basename for the settings files - static const char* SETTINGS_FILE_NAME; + /// basename for the settings files + static const char* SETTINGS_FILE_NAME; }; #endif /* LLAUTOREPLACE_H */ diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 797d590e1f..73eb822036 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -66,6 +66,7 @@ #include "llrootview.h" #include "llviewerchat.h" #include "lltranslate.h" +#include "llautoreplace.h" S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0; @@ -112,6 +113,7 @@ BOOL LLFloaterIMNearbyChat::postBuild() setIsSingleInstance(TRUE); BOOL result = LLFloaterIMSessionTab::postBuild(); + mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); mInputEditor->setCommitCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxCommit, this)); mInputEditor->setKeystrokeCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxKeystroke, this)); mInputEditor->setFocusLostCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxFocusLost, this)); diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index a09dc1914f..a2c7bacb5d 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -332,13 +332,7 @@ BOOL LLFloaterIMSession::postBuild() BOOL result = LLFloaterIMSessionTab::postBuild(); mInputEditor->setMaxTextLength(1023); - // enable line history support for instant message bar - // XXX stinson TODO : resolve merge by adding autoreplace to text editors -#if 0 - // *TODO Establish LineEditor with autoreplace callback mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); -#endif - mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) ); mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) ); mInputEditor->setKeystrokeCallback( boost::bind(onInputEditorKeystroke, _1, this) ); -- cgit v1.2.3 From c3fd7ae17b67568a68ae967cd2d30e20db1f6b6c Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Mon, 28 Jan 2013 19:59:13 +0200 Subject: CHUI-708 FIXED Call doToParticipants() only if selected conversation is p2p --- indra/newview/llfloaterimcontainer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index ff6234fa27..c272e5e391 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1086,7 +1086,10 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command, } else { - doToParticipants(command, selectedIDS); + if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + { + doToParticipants(command, selectedIDS); + } } } } -- cgit v1.2.3 From 2ac99f55f9e562e4ff8ebde4cba8270f1048c28d Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Thu, 24 Jan 2013 19:56:13 +0200 Subject: CHUI-578 FIXED Move preferences for conversation logs/transcripts to chat tab --- indra/llvfs/lldir.cpp | 13 +- indra/llvfs/lldir.h | 2 + indra/newview/app_settings/settings.xml | 4 +- indra/newview/llconversationlog.cpp | 60 +++-- indra/newview/llconversationlog.h | 11 +- indra/newview/llfloaterconversationlog.cpp | 14 +- indra/newview/llfloaterconversationlog.h | 2 +- indra/newview/llfloaterimcontainer.cpp | 6 +- indra/newview/llfloaterimnearbychat.cpp | 27 +- indra/newview/llfloaterimnearbychat.h | 2 +- indra/newview/llfloaterimsession.cpp | 12 +- indra/newview/llfloaterimsession.h | 2 +- indra/newview/llfloaterimsessiontab.cpp | 6 +- indra/newview/llfloaterimsessiontab.h | 2 +- indra/newview/llfloaterpreference.cpp | 109 +++++--- indra/newview/llfloaterpreference.h | 19 +- indra/newview/llimview.cpp | 37 +-- indra/newview/llimview.h | 2 + indra/newview/lllogchat.cpp | 235 ++++++++++------- indra/newview/lllogchat.h | 15 +- indra/newview/llviewermessage.cpp | 2 +- .../newview/skins/default/xui/en/notifications.xml | 26 ++ .../default/xui/en/panel_preferences_chat.xml | 284 ++++++++++++++------- .../default/xui/en/panel_preferences_privacy.xml | 226 +++++----------- 24 files changed, 641 insertions(+), 477 deletions(-) (limited to 'indra') diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 5e5aeefba1..f7bc19574a 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -90,7 +90,8 @@ LLDir::LLDir() mCAFile(""), mTempDir(""), mDirDelimiter("/"), // fallback to forward slash if not overridden - mLanguage("en") + mLanguage("en"), + mUserName("undefined") { } @@ -814,6 +815,11 @@ void LLDir::setChatLogsDir(const std::string &path) } } +void LLDir::updatePerAccountChatLogsDir() +{ + mPerAccountChatLogsDir = add(getChatLogsDir(), mUserName); +} + void LLDir::setPerAccountChatLogsDir(const std::string &username) { // if both first and last aren't set, assume we're grabbing the cached dir @@ -824,13 +830,14 @@ void LLDir::setPerAccountChatLogsDir(const std::string &username) std::string userlower(username); LLStringUtil::toLower(userlower); LLStringUtil::replaceChar(userlower, ' ', '_'); - mPerAccountChatLogsDir = add(getChatLogsDir(), userlower); + + mUserName = userlower; + updatePerAccountChatLogsDir(); } else { llerrs << "NULL name for LLDir::setPerAccountChatLogsDir" << llendl; } - } void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language) diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 300ff1eef6..95cab65149 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -186,6 +186,7 @@ class LLDir virtual std::string getSkinFolder() const; virtual std::string getLanguage() const; virtual bool setCacheDir(const std::string &path); + virtual void updatePerAccountChatLogsDir(); virtual void dumpCurrentDirectories(); @@ -243,6 +244,7 @@ protected: std::vector<std::string> mSearchSkinDirs; std::string mLanguage; // Current viewer language std::string mLLPluginDir; // Location for plugins and plugin shell + std::string mUserName; // Current user name }; void dir_exists_or_crash(const std::string &dir_name); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index fd4d1df894..dd9a0100c0 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4674,9 +4674,9 @@ <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Boolean</string> + <string>S32</string> <key>Value</key> - <integer>1</integer> + <integer>2</integer> </map> <key>LandBrushSize</key> <map> diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index ff1f819d7d..8de041f983 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -28,13 +28,14 @@ #include "llagent.h" #include "llavatarnamecache.h" #include "llconversationlog.h" +#include "llnotificationsutil.h" #include "lltrans.h" const int CONVERSATION_LIFETIME = 30; // lifetime of LLConversation is 30 days by spec -struct Conversation_params +struct ConversationParams { - Conversation_params(time_t time) + ConversationParams(time_t time) : mTime(time), mTimestamp(LLConversation::createTimestamp(time)) {} @@ -53,7 +54,7 @@ struct Conversation_params /* LLConversation implementation */ /************************************************************************/ -LLConversation::LLConversation(const Conversation_params& params) +LLConversation::LLConversation(const ConversationParams& params) : mTime(params.mTime), mTimestamp(params.mTimestamp), mConversationType(params.mConversationType), @@ -188,33 +189,24 @@ void LLConversationLogFriendObserver::changed(U32 mask) LLConversationLog::LLConversationLog() : mAvatarNameCacheConnection() { - LLControlVariable* log_instant_message = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); - LLControlVariable* keep_convers_log = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); - bool is_log_message = false; - bool is_keep_log = false; + LLControlVariable * keep_log_ctrlp = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); + S32 log_mode = keep_log_ctrlp->getValue(); - if (log_instant_message) + if (log_mode > 0) { - log_instant_message->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); - is_log_message = log_instant_message->getValue().asBoolean(); + keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); + enableLogging(log_mode); } - if (keep_convers_log) - { - keep_convers_log->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); - is_keep_log = keep_convers_log->getValue().asBoolean(); - } - - enableLogging(is_log_message && is_keep_log); } -void LLConversationLog::enableLogging(bool enable) +void LLConversationLog::enableLogging(S32 log_mode) { - if (enable) + if (log_mode > 0) { loadFromFile(getFileName()); LLIMMgr::instance().addSessionObserver(this); - newMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); + mNewMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); mFriendObserver = new LLConversationLogFriendObserver; LLAvatarTracker::instance().addObserver(mFriendObserver); @@ -224,7 +216,7 @@ void LLConversationLog::enableLogging(bool enable) saveToFile(getFileName()); LLIMMgr::instance().removeSessionObserver(this); - newMessageSignalConnection.disconnect(); + mNewMessageSignalConnection.disconnect(); LLAvatarTracker::instance().removeObserver(mFriendObserver); mConversations.clear(); } @@ -377,7 +369,7 @@ void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string void LLConversationLog::cache() { - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + if (gSavedSettings.getS32("KeepConversationLogTranscripts") > 0) { saveToFile(getFileName()); } @@ -450,9 +442,9 @@ bool LLConversationLog::loadFromFile(const std::string& filename) char part_id_buffer[MAX_STRING]; char conv_id_buffer[MAX_STRING]; char history_file_name[MAX_STRING]; - int has_offline_ims; - int stype; - time_t time; + S32 has_offline_ims; + S32 stype; + S64 time; // before CHUI-348 it was a flag of conversation voice state int prereserved_unused; @@ -462,7 +454,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename) part_id_buffer[0] = '\0'; conv_id_buffer[0] = '\0'; - sscanf(buffer, "[%ld] %d %d %d %[^|]| %s %s %[^|]|", + sscanf(buffer, "[%lld] %d %d %d %[^|]| %s %s %[^|]|", &time, &stype, &prereserved_unused, @@ -472,7 +464,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename) conv_id_buffer, history_file_name); - Conversation_params params(time); + ConversationParams params((time_t)time); params.mConversationType = (SessionType)stype; params.mHasOfflineIMs = has_offline_ims; params.mConversationName = std::string(conv_name_buffer); @@ -530,3 +522,17 @@ void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LL mAvatarNameCacheConnection.disconnect(); updateConversationName(session, av_name.getCompleteName()); } + +void LLConversationLog::onClearLog() +{ + LLNotificationsUtil::add("PreferenceChatClearLog", LLSD(), LLSD(), boost::bind(&LLConversationLog::onClearLogResponse, this, _1, _2)); +} + +void LLConversationLog::onClearLogResponse(const LLSD& notification, const LLSD& response) +{ + if (0 == LLNotificationsUtil::getSelectedOption(notification, response)) + { + mConversations.clear(); + notifyObservers(); + } +} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 35462ec3a4..65a18c02e5 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -31,7 +31,7 @@ #include "llimview.h" class LLConversationLogObserver; -struct Conversation_params; +struct ConversationParams; typedef LLIMModel::LLIMSession::SType SessionType; @@ -43,7 +43,7 @@ class LLConversation { public: - LLConversation(const Conversation_params& params); + LLConversation(const ConversationParams& params); LLConversation(const LLIMModel::LLIMSession& session); LLConversation(const LLConversation& conversation); @@ -138,6 +138,9 @@ public: */ void cache(); + void onClearLog(); + void onClearLogResponse(const LLSD& notification, const LLSD& response); + private: LLConversationLog(); @@ -149,7 +152,7 @@ private: } } - void enableLogging(bool enable); + void enableLogging(S32 log_mode); /** * adds conversation to the conversation list and notifies observers @@ -182,7 +185,7 @@ private: LLFriendObserver* mFriendObserver; // Observer of the LLAvatarTracker instance - boost::signals2::connection newMessageSignalConnection; + boost::signals2::connection mNewMessageSignalConnection; boost::signals2::connection mAvatarNameCacheConnection; }; diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index a40a000bab..a44ebcf6ab 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -63,13 +63,9 @@ BOOL LLFloaterConversationLog::postBuild() getChild<LLFilterEditor>("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); - LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); - if (ctrl) - { - ctrl->getSignal()->connect(boost::bind(&LLFloaterConversationLog::onCallLoggingEnabledDisabled, this, _2)); - onCallLoggingEnabledDisabled(ctrl->getValue().asBoolean() - && gSavedSettings.getBOOL("KeepConversationLogTranscripts")); - } + LLControlVariable * keep_log_ctrlp = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); + keep_log_ctrlp->getSignal()->connect(boost::bind(&LLFloaterConversationLog::onCallLoggingEnabledDisabled, this, _2)); + onCallLoggingEnabledDisabled(keep_log_ctrlp->getValue()); return LLFloater::postBuild(); } @@ -139,8 +135,8 @@ bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) return false; } -void LLFloaterConversationLog::onCallLoggingEnabledDisabled(bool enabled) +void LLFloaterConversationLog::onCallLoggingEnabledDisabled(S32 log_mode) { - std::string no_items_msg = enabled ? "" : getString("logging_calls_disabled"); + std::string no_items_msg = log_mode > 0 ? "" : getString("logging_calls_disabled"); mConversationLogList->setNoItemsCommentText(no_items_msg); } diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h index 9e79cbd7d8..aa0f480aae 100644 --- a/indra/newview/llfloaterconversationlog.h +++ b/indra/newview/llfloaterconversationlog.h @@ -49,7 +49,7 @@ private: bool isActionEnabled(const LLSD& userdata); bool isActionChecked(const LLSD& userdata); - void onCallLoggingEnabledDisabled(bool enabled); + void onCallLoggingEnabledDisabled(S32 log_mode); LLConversationLogList* mConversationLogList; }; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c272e5e391..54e5085490 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -224,7 +224,7 @@ BOOL LLFloaterIMContainer::postBuild() collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); - LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate)); + LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false)); mMicroChangedSignal = LLVoiceClient::getInstance()->MicroChangedCallback(boost::bind(&LLFloaterIMContainer::updateSpeakBtnState, this)); if (! mMessagesPane->isCollapsed()) { @@ -1142,7 +1142,7 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) if ("conversation_log" == item) { - return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); + return gSavedSettings.getS32("KeepConversationLogTranscripts") > 0; } //Enable Chat history item for ad-hoc and group conversations @@ -1793,7 +1793,7 @@ void LLFloaterIMContainer::updateSpeakBtnState() bool LLFloaterIMContainer::isConversationLoggingAllowed() { - return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); + return gSavedSettings.getS32("KeepConversationLogTranscripts") > 0; } void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes) diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 797d590e1f..17d2341b3c 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -148,8 +148,14 @@ void LLFloaterIMNearbyChat::refresh() } } -void LLFloaterIMNearbyChat::reloadMessages() +void LLFloaterIMNearbyChat::reloadMessages(bool clean_messages/* = false*/) { + if (clean_messages) + { + mMessageArchive.clear(); + loadHistory(); + } + mChatHistory->clear(); LLSD do_not_log; @@ -174,11 +180,11 @@ void LLFloaterIMNearbyChat::loadHistory() { const LLSD& msg = *it; - std::string from = msg[IM_FROM]; + std::string from = msg[LL_IM_FROM]; LLUUID from_id; - if (msg[IM_FROM_ID].isDefined()) + if (msg[LL_IM_FROM_ID].isDefined()) { - from_id = msg[IM_FROM_ID].asUUID(); + from_id = msg[LL_IM_FROM_ID].asUUID(); } else { @@ -189,8 +195,8 @@ void LLFloaterIMNearbyChat::loadHistory() LLChat chat; chat.mFromName = from; chat.mFromID = from_id; - chat.mText = msg[IM_TEXT].asString(); - chat.mTimeStr = msg[IM_TIME].asString(); + chat.mText = msg[LL_IM_TEXT].asString(); + chat.mTimeStr = msg[LL_IM_TIME].asString(); chat.mChatStyle = CHAT_STYLE_HISTORY; chat.mSourceType = CHAT_SOURCE_AGENT; @@ -519,20 +525,21 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type ) } } -void LLFloaterIMNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +void LLFloaterIMNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) { appendMessage(chat, args); if(archive) { mMessageArchive.push_back(chat); - if(mMessageArchive.size()>200) + if(mMessageArchive.size() > 200) + { mMessageArchive.erase(mMessageArchive.begin()); + } } // logging - if (!args["do_not_log"].asBoolean() - && gSavedPerAccountSettings.getBOOL("LogNearbyChat")) + if (!args["do_not_log"].asBoolean() && gSavedSettings.getS32("KeepConversationLogTranscripts") > 1) { std::string from_name = chat.mFromName; diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index f4213eda5a..14c7d01ecd 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -56,7 +56,7 @@ public: /*virtual*/ void setVisible(BOOL visible); void loadHistory(); - void reloadMessages(); + void reloadMessages(bool clean_messages = false); void removeScreenChat(); void show(); diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index a09dc1914f..07f5515582 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -853,8 +853,18 @@ void LLFloaterIMSession::updateMessages() } } -void LLFloaterIMSession::reloadMessages() +void LLFloaterIMSession::reloadMessages(bool clean_messages/* = false*/) { + if (clean_messages) + { + LLIMModel::LLIMSession * sessionp = LLIMModel::instance().findIMSession(mSessionID); + + if (NULL != sessionp) + { + sessionp->loadHistory(); + } + } + mChatHistory->clear(); mLastMessageIndex = -1; updateMessages(); diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index 2049cedfd7..e7fd6f9ff3 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -86,7 +86,7 @@ public: // get new messages from LLIMModel /*virtual*/ void updateMessages(); - void reloadMessages(); + void reloadMessages(bool clean_messages = false); static void onSendMsg(LLUICtrl*, void*); void sendMsgFromInputEditor(); void sendMsg(const std::string& msg); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 37404ab716..f7c6f19450 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -680,7 +680,7 @@ void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show) } // static -void LLFloaterIMSessionTab::processChatHistoryStyleUpdate() +void LLFloaterIMSessionTab::processChatHistoryStyleUpdate(bool clean_messages/* = false*/) { LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); @@ -689,14 +689,14 @@ void LLFloaterIMSessionTab::processChatHistoryStyleUpdate() LLFloaterIMSession* floater = dynamic_cast<LLFloaterIMSession*>(*iter); if (floater) { - floater->reloadMessages(); + floater->reloadMessages(clean_messages); } } LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); if (nearby_chat) { - nearby_chat->reloadMessages(); + nearby_chat->reloadMessages(clean_messages); } } diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index beaffc14a6..e90fcbb806 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -53,7 +53,7 @@ public: ~LLFloaterIMSessionTab(); // reload all message with new settings of visual modes - static void processChatHistoryStyleUpdate(); + static void processChatHistoryStyleUpdate(bool clean_messages = false); /** * Returns true if chat is displayed in multi tabbed floater diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 3d4a1c44d8..7742e5b3c3 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -306,7 +306,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mAvatarDataInitialized(false), mClickActionDirty(false) { - + LLConversationLog::instance().addObserver(this); + //Build Floater is now Called from LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>); static bool registered_dialog = false; @@ -329,8 +330,6 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.VoiceSetKey", boost::bind(&LLFloaterPreference::onClickSetKey, this)); mCommitCallbackRegistrar.add("Pref.VoiceSetMiddleMouse", boost::bind(&LLFloaterPreference::onClickSetMiddleMouse, this)); mCommitCallbackRegistrar.add("Pref.SetSounds", boost::bind(&LLFloaterPreference::onClickSetSounds, this)); -// mCommitCallbackRegistrar.add("Pref.ClickSkipDialogs", boost::bind(&LLFloaterPreference::onClickSkipDialogs, this)); -// mCommitCallbackRegistrar.add("Pref.ClickResetDialogs", boost::bind(&LLFloaterPreference::onClickResetDialogs, this)); mCommitCallbackRegistrar.add("Pref.ClickEnablePopup", boost::bind(&LLFloaterPreference::onClickEnablePopup, this)); mCommitCallbackRegistrar.add("Pref.ClickDisablePopup", boost::bind(&LLFloaterPreference::onClickDisablePopup, this)); mCommitCallbackRegistrar.add("Pref.LogPath", boost::bind(&LLFloaterPreference::onClickLogPath, this)); @@ -351,13 +350,16 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) sSkin = gSavedSettings.getString("SkinCurrent"); - mCommitCallbackRegistrar.add("Pref.ClickActionChange", boost::bind(&LLFloaterPreference::onClickActionChange, this)); + mCommitCallbackRegistrar.add("Pref.ClickActionChange", boost::bind(&LLFloaterPreference::onClickActionChange, this)); gSavedSettings.getControl("NameTagShowUsernames")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("NameTagShowFriends")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged, _2)); LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this ); + + mCommitCallbackRegistrar.add("Pref.ClearLog", boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance())); + mCommitCallbackRegistrar.add("Pref.DeleteTranscripts", boost::bind(&LLFloaterPreference::onDeleteTranscripts, this)); } void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type ) @@ -425,7 +427,7 @@ void LLFloaterPreference::saveAvatarProperties( void ) BOOL LLFloaterPreference::postBuild() { - gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate)); + gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false)); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLViewerChat::signalChatFontChanged)); @@ -455,9 +457,24 @@ BOOL LLFloaterPreference::postBuild() gSavedPerAccountSettings.setString("DoNotDisturbModeResponse", LLTrans::getString("DoNotDisturbModeResponseDefault")); } + // set 'enable' property for 'Clear log...' button + changed(); + + // set 'enable' property for 'Delete transcripts...' button + updateDeleteTranscriptsButton(); + + LLLogChat::setSaveHistorySignal(boost::bind(&LLFloaterPreference::onLogChatHistorySaved, this)); + return TRUE; } +void LLFloaterPreference::updateDeleteTranscriptsButton() +{ + std::vector<std::string> list_of_transcriptions_file_names; + LLLogChat::getListOfTranscriptFiles(list_of_transcriptions_file_names); + getChild<LLButton>("delete_transcripts")->setEnabled(list_of_transcriptions_file_names.size() > 0); +} + void LLFloaterPreference::onDoNotDisturbResponseChanged() { // set "DoNotDisturbResponseChanged" TRUE if user edited message differs from default, FALSE otherwise @@ -476,6 +493,8 @@ LLFloaterPreference::~LLFloaterPreference() { ctrl_window_size->setCurrentByIndex(i); } + + LLConversationLog::instance().removeObserver(this); } void LLFloaterPreference::draw() @@ -833,12 +852,12 @@ void LLFloaterPreference::onBtnCancel() } // static -void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email) +void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email) { LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); if (instance) { - instance->setPersonalInfo(visibility, im_via_email, email); + instance->setPersonalInfo(visibility, im_via_email); } } @@ -1425,10 +1444,21 @@ void LLFloaterPreference::onClickLogPath() return; //Canceled! } - gSavedPerAccountSettings.setString("InstantMessageLogPath", picker.getDirName()); + std::string dir_name = picker.getDirName(); + gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); + + gDirUtilp->setChatLogsDir(dir_name); + gDirUtilp->updatePerAccountChatLogsDir(); + LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); + + // refresh IM floaters with new logs from files from new selected directory + LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); + + // enable/disable 'Delete transcripts button + updateDeleteTranscriptsButton(); } -void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email) +void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im_via_email) { mGotPersonalInfo = true; mOriginalIMViaEmail = im_via_email; @@ -1450,32 +1480,14 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im } getChild<LLUICtrl>("online_searchresults")->setEnabled(TRUE); - - getChildView("include_im_in_chat_history")->setEnabled(TRUE); - getChildView("show_timestamps_check_im")->setEnabled(TRUE); getChildView("friends_online_notify_checkbox")->setEnabled(TRUE); - getChild<LLUICtrl>("online_visibility")->setValue(mOriginalHideOnlineStatus); getChild<LLUICtrl>("online_visibility")->setLabelArg("[DIR_VIS]", mDirectoryVisibility); getChildView("send_im_to_email")->setEnabled(TRUE); getChild<LLUICtrl>("send_im_to_email")->setValue(im_via_email); - getChildView("log_instant_messages")->setEnabled(TRUE); -// getChildView("log_chat")->setEnabled(TRUE); -// getChildView("log_instant_messages_timestamp")->setEnabled(TRUE); -// getChildView("log_chat_timestamp")->setEnabled(TRUE); - getChildView("log_chat_IM")->setEnabled(TRUE); - getChildView("log_date_timestamp")->setEnabled(TRUE); - getChildView("favorites_on_login_check")->setEnabled(TRUE); - getChildView("log_nearby_chat")->setEnabled(TRUE); - getChildView("log_instant_messages")->setEnabled(TRUE); - getChildView("show_timestamps_check_im")->setEnabled(TRUE); getChildView("log_path_string")->setEnabled(FALSE);// LineEditor becomes readonly in this case. getChildView("log_path_button")->setEnabled(TRUE); - childEnable("logfile_name_datestamp"); - std::string display_email(email); - getChild<LLUICtrl>("email_address")->setValue(display_email); - } void LLFloaterPreference::onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name) @@ -1566,6 +1578,35 @@ void LLFloaterPreference::onClickActionChange() mClickActionDirty = true; } +void LLFloaterPreference::onDeleteTranscripts() +{ + LLNotificationsUtil::add("PreferenceChatDeleteTranscripts", LLSD(), LLSD(), boost::bind(&LLFloaterPreference::onDeleteTranscriptsResponse, this, _1, _2)); +} + +void LLFloaterPreference::onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response) +{ + if (0 == LLNotificationsUtil::getSelectedOption(notification, response)) + { + gDirUtilp->deleteFilesInDir(gDirUtilp->getPerAccountChatLogsDir(), "*." + LL_TRANSCRIPT_FILE_EXTENSION); + + std::vector<std::string> list_of_transcriptions_file_names; + LLLogChat::getListOfTranscriptFiles(list_of_transcriptions_file_names); + getChild<LLButton>("delete_transcripts")->setEnabled(list_of_transcriptions_file_names.size() > 0); + + LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); + } +} + +void LLFloaterPreference::onLogChatHistorySaved() +{ + LLButton * delete_transcripts_buttonp = getChild<LLButton>("delete_transcripts"); + + if (!delete_transcripts_buttonp->getEnabled()) + { + delete_transcripts_buttonp->setEnabled(true); + } +} + void LLFloaterPreference::updateClickActionSettings() { const int single_clk_action = getChild<LLComboBox>("single_click_action_combo")->getValue().asInteger(); @@ -1624,6 +1665,11 @@ void LLFloaterPreference::selectChatPanel() selectPanel("chat"); } +void LLFloaterPreference::changed() +{ + getChild<LLButton>("clear_log")->setEnabled(LLConversationLog::instance().getConversations().size() > 0); +} + //------------------------------Updater--------------------------------------- static bool handleBandwidthChanged(const LLSD& newvalue) @@ -1717,11 +1763,6 @@ BOOL LLPanelPreference::postBuild() } - if (hasChild("online_visibility") && hasChild("send_im_to_email")) - { - getChild<LLUICtrl>("email_address")->setValue(getString("log_in_to_change") ); - } - //////////////////////PanelPrivacy /////////////////// if (hasChild("media_enabled")) { @@ -1898,7 +1939,7 @@ public: for (control_values_map_t::iterator it = mSavedValues.begin(); it != mSavedValues.end(); ) { const std::string setting = it->first->getName(); - if (std::find(mAccountIndependentSettings.begin(), + if (find(mAccountIndependentSettings.begin(), mAccountIndependentSettings.end(), setting) == mAccountIndependentSettings.end()) { mSavedValues.erase(it++); @@ -2187,4 +2228,4 @@ void LLFloaterPreferenceProxy::onChangeSocksSettings() otherHttpProxy->selectFirstItem(); } -}; +} diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 37a531e99e..f9f1d52244 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -35,7 +35,9 @@ #include "llfloater.h" #include "llavatarpropertiesprocessor.h" +#include "llconversationlog.h" +class LLConversationLogObserver; class LLPanelPreference; class LLPanelLCD; class LLPanelDebug; @@ -58,7 +60,7 @@ typedef enum // Floater to control preferences (display, audio, bandwidth, general. -class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver +class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver, public LLConversationLogObserver { public: LLFloaterPreference(const LLSD& key); @@ -70,9 +72,11 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); + /*virtual*/ void changed(); + /*virtual*/ void changed(const LLUUID& session_id, U32 mask) {}; // static data update, called from message handler - static void updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email); + static void updateUserInfo(const std::string& visibility, bool im_via_email); // refresh all the graphics preferences menus static void refreshEnabledGraphics(); @@ -134,15 +138,13 @@ public: void setKey(KEY key); void onClickSetMiddleMouse(); void onClickSetSounds(); -// void onClickSkipDialogs(); -// void onClickResetDialogs(); void onClickEnablePopup(); void onClickDisablePopup(); void resetAllIgnored(); void setAllIgnored(); void onClickLogPath(); void enableHistory(); - void setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email); + void setPersonalInfo(const std::string& visibility, bool im_via_email); void refreshEnabledState(); void disableUnavailableSettings(); void onCommitWindowedMode(); @@ -166,12 +168,17 @@ public: void onClickSpellChecker(); void applyUIColor(LLUICtrl* ctrl, const LLSD& param); void getUIColor(LLUICtrl* ctrl, const LLSD& param); - + void onLogChatHistorySaved(); void buildPopupLists(); static void refreshSkin(void* data); void selectPanel(const LLSD& name); private: + + void onDeleteTranscripts(); + void onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response); + void updateDeleteTranscriptsButton(); + static std::string sSkin; notifications_map mNotificationOptions; bool mClickActionDirty; ///< Set to true when the click/double-click options get changed by user. diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 433ddad35d..37c9ee8c99 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -378,15 +378,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& } buildHistoryFileName(); - - if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) - { - std::list<LLSD> chat_history; - - //involves parsing of a chat history - LLLogChat::loadChatHistory(mHistoryFileName, chat_history); - addMessagesFromHistory(chat_history); - } + loadHistory(); // Localizing name of ad-hoc session. STORM-153 // Changing name should happen here- after the history file was created, so that @@ -579,11 +571,11 @@ void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list<LLSD>& histo { const LLSD& msg = *it; - std::string from = msg[IM_FROM]; + std::string from = msg[LL_IM_FROM]; LLUUID from_id; - if (msg[IM_FROM_ID].isDefined()) + if (msg[LL_IM_FROM_ID].isDefined()) { - from_id = msg[IM_FROM_ID].asUUID(); + from_id = msg[LL_IM_FROM_ID].asUUID(); } else { @@ -592,8 +584,8 @@ void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list<LLSD>& histo gCacheName->getUUID(legacy_name, from_id); } - std::string timestamp = msg[IM_TIME]; - std::string text = msg[IM_TEXT]; + std::string timestamp = msg[LL_IM_TIME]; + std::string text = msg[LL_IM_TEXT]; addMessage(from, from_id, text, timestamp, true); @@ -617,6 +609,20 @@ void LLIMModel::LLIMSession::chatFromLogFile(LLLogChat::ELogLineType type, const } } +void LLIMModel::LLIMSession::loadHistory() +{ + mMsgs.clear(); + + if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) + { + std::list<LLSD> chat_history; + + //involves parsing of a chat history + LLLogChat::loadChatHistory(mHistoryFileName, chat_history); + addMessagesFromHistory(chat_history); + } +} + LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const { return get_if_there(mId2SessionMap, session_id, @@ -921,8 +927,7 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) { - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages") - && gSavedSettings.getBOOL("KeepConversationLogTranscripts")) + if (gSavedSettings.getS32("KeepConversationLogTranscripts") > 1) { std::string from_name = from; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 8578fa8c06..da6039a3ae 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -101,6 +101,8 @@ public: /** ad-hoc sessions involve sophisticated chat history file naming schemes */ void buildHistoryFileName(); + void loadHistory(); + LLUUID mSessionID; std::string mName; EInstantMessage mType; diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 3692658e9e..545b44ef92 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -58,10 +58,11 @@ const S32 LOG_RECALL_SIZE = 2048; -const std::string IM_TIME("time"); -const std::string IM_TEXT("message"); -const std::string IM_FROM("from"); -const std::string IM_FROM_ID("from_id"); +const std::string LL_IM_TIME("time"); +const std::string LL_IM_TEXT("message"); +const std::string LL_IM_FROM("from"); +const std::string LL_IM_FROM_ID("from_id"); +const std::string LL_TRANSCRIPT_FILE_EXTENSION("ll.txt"); const static std::string IM_SEPARATOR(": "); const static std::string NEW_LINE("\n"); @@ -116,6 +117,15 @@ const static int IDX_TEXT = 3; using namespace boost::posix_time; using namespace boost::gregorian; +void append_to_last_message(std::list<LLSD>& messages, const std::string& line) +{ + if (!messages.size()) return; + + std::string im_text = messages.back()[LL_IM_TEXT].asString(); + im_text.append(line); + messages.back()[LL_IM_TEXT] = im_text; +} + class LLLogChatTimeScanner: public LLSingleton<LLLogChatTimeScanner> { public: @@ -191,15 +201,17 @@ private: std::stringstream mTimeStream; }; +LLLogChat::save_history_signal_t * LLLogChat::sSaveHistorySignal = NULL; + //static std::string LLLogChat::makeLogFileName(std::string filename) { /** - * Testing for in bound and out bound ad-hoc file names - * if it is then skip date stamping. - **/ - //LL_INFOS("") << "Befor:" << filename << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ - boost::match_results<std::string::const_iterator> matches; + * Testing for in bound and out bound ad-hoc file names + * if it is then skip date stamping. + **/ + + boost::match_results<std::string::const_iterator> matches; bool inboundConf = boost::regex_match(filename, matches, INBOUND_CONFERENCE); bool outboundConf = boost::regex_match(filename, matches, OUTBOUND_CONFERENCE); if (!(inboundConf || outboundConf)) @@ -220,17 +232,17 @@ std::string LLLogChat::makeLogFileName(std::string filename) filename += dbuffer; } } - //LL_INFOS("") << "After:" << filename << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ + filename = cleanFileName(filename); - filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS,filename); - filename += ".txt"; - //LL_INFOS("") << "Full:" << filename << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ + filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename); + filename += '.' + LL_TRANSCRIPT_FILE_EXTENSION; + return filename; } std::string LLLogChat::cleanFileName(std::string filename) { - std::string invalidChars = "\"\'\\/?*:.<>|[]{}~"; // Cannot match glob or illegal filename chars + std::string invalidChars = "\"\'\\/?*:.<>|[]{}~"; // Cannot match glob or illegal filename chars std::string::size_type position = filename.find_first_of(invalidChars); while (position != filename.npos) { @@ -242,27 +254,24 @@ std::string LLLogChat::cleanFileName(std::string filename) std::string LLLogChat::timestamp(bool withdate) { - time_t utc_time; - utc_time = time_corrected(); - std::string timeStr; - LLSD substitution; - substitution["datetime"] = (S32) utc_time; - if (withdate) { - timeStr = "["+LLTrans::getString ("TimeYear")+"]/[" - +LLTrans::getString ("TimeMonth")+"]/[" - +LLTrans::getString ("TimeDay")+"] [" - +LLTrans::getString ("TimeHour")+"]:[" - +LLTrans::getString ("TimeMin")+"]"; + timeStr = "[" + LLTrans::getString ("TimeYear") + "]/[" + + LLTrans::getString ("TimeMonth") + "]/[" + + LLTrans::getString ("TimeDay") + "] [" + + LLTrans::getString ("TimeHour") + "]:[" + + LLTrans::getString ("TimeMin") + "]"; } else { timeStr = "[" + LLTrans::getString("TimeHour") + "]:[" - + LLTrans::getString ("TimeMin")+"]"; + + LLTrans::getString ("TimeMin")+"]"; } + LLSD substitution; + substitution["datetime"] = (S32)time_corrected(); + LLStringUtil::format (timeStr, substitution); return timeStr; } @@ -270,9 +279,9 @@ std::string LLLogChat::timestamp(bool withdate) //static void LLLogChat::saveHistory(const std::string& filename, - const std::string& from, - const LLUUID& from_id, - const std::string& line) + const std::string& from, + const LLUUID& from_id, + const std::string& line) { std::string tmp_filename = filename; LLStringUtil::trim(tmp_filename); @@ -312,6 +321,11 @@ void LLLogChat::saveHistory(const std::string& filename, file << LLChatLogFormatter(item) << std::endl; file.close(); + + if (NULL != sSaveHistorySignal) + { + (*sSaveHistorySignal)(); + } } void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata) @@ -321,7 +335,7 @@ void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLi llwarns << "Filename is Empty!" << llendl; return ; } - + LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "r"); /*Flawfinder: ignore*/ if (!fptr) { @@ -377,15 +391,6 @@ void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLi } } -void append_to_last_message(std::list<LLSD>& messages, const std::string& line) -{ - if (!messages.size()) return; - - std::string im_text = messages.back()[IM_TEXT].asString(); - im_text.append(line); - messages.back()[IM_TEXT] = im_text; -} - // static void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params) { @@ -397,19 +402,16 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false; - //LL_INFOS("") << "Loading:" << file_name << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ - //LL_INFOS("") << "Current:" << makeLogFileName(file_name) << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r");/*Flawfinder: ignore*/ if (!fptr) - { + { fptr = LLFile::fopen(oldLogFileName(file_name), "r");/*Flawfinder: ignore*/ - if (!fptr) - { - if (!fptr) return; //No previous conversation with this name. - } + if (!fptr) + { + return; //No previous conversation with this name. + } } - //LL_INFOS("") << "Reading:" << file_name << LL_ENDL; char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/ char *bptr; S32 len; @@ -454,7 +456,7 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m LLSD item; if (!LLChatLogParser::parse(line, item, load_params)) { - item[IM_TEXT] = line; + item[LL_IM_TEXT] = line; } messages.push_back(item); } @@ -462,9 +464,78 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m fclose(fptr); } +// static +std::string LLLogChat::oldLogFileName(std::string filename) +{ + // get Users log directory + std::string directory = gDirUtilp->getPerAccountChatLogsDir(); + + // add final OS dependent delimiter + directory += gDirUtilp->getDirDelimiter(); + + // lest make sure the file name has no invalid characters before making the pattern + filename = cleanFileName(filename); + + // create search pattern + std::string pattern = filename + ( filename == "chat" ? "-???\?-?\?-??.txt" : "-???\?-??.txt"); + + std::vector<std::string> allfiles; + LLDirIterator iter(directory, pattern); + std::string scanResult; + + while (iter.next(scanResult)) + { + allfiles.push_back(scanResult); + } + + if (allfiles.size() == 0) // if no result from date search, return generic filename + { + scanResult = directory + filename + '.' + LL_TRANSCRIPT_FILE_EXTENSION; + } + else + { + sort(allfiles.begin(), allfiles.end()); + scanResult = directory + allfiles.back(); + // this file is now the most recent version of the file. + } + + return scanResult; +} + +// static +void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_transcriptions) +{ + // get Users log directory + std::string directory = gDirUtilp->getPerAccountChatLogsDir(); + + // add final OS dependent delimiter + directory += gDirUtilp->getDirDelimiter(); + + // create search pattern + std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION; + + LLDirIterator iter(directory, pattern); + std::string scanResult; + while (iter.next(scanResult)) + { + list_of_transcriptions.push_back(scanResult); + } +} + +//static +boost::signals2::connection LLLogChat::setSaveHistorySignal(const save_history_signal_t::slot_type& cb) +{ + if (NULL == sSaveHistorySignal) + { + sSaveHistorySignal = new save_history_signal_t(); + } + + return sSaveHistorySignal->connect(cb); +} + //*TODO mark object's names in a special way so that they will be distinguishable form avatar name //which are more strict by its nature (only firstname and secondname) -//Example, an object's name can be writen like "Object <actual_object's_name>" +//Example, an object's name can be written like "Object <actual_object's_name>" void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const { if (!im.isMap()) @@ -473,19 +544,19 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const return; } - if (im[IM_TIME].isDefined()) + if (im[LL_IM_TIME].isDefined()) { - std::string timestamp = im[IM_TIME].asString(); + std::string timestamp = im[LL_IM_TIME].asString(); boost::trim(timestamp); ostr << '[' << timestamp << ']' << TWO_SPACES; } //*TODO mark object's names in a special way so that they will be distinguishable form avatar name //which are more strict by its nature (only firstname and secondname) - //Example, an object's name can be writen like "Object <actual_object's_name>" - if (im[IM_FROM].isDefined()) + //Example, an object's name can be written like "Object <actual_object's_name>" + if (im[LL_IM_FROM].isDefined()) { - std::string from = im[IM_FROM].asString(); + std::string from = im[LL_IM_FROM].asString(); boost::trim(from); if (from.size()) { @@ -493,9 +564,9 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const } } - if (im[IM_TEXT].isDefined()) + if (im[LL_IM_TEXT].isDefined()) { - std::string im_text = im[IM_TEXT].asString(); + std::string im_text = im[LL_IM_TEXT].asString(); //multilined text will be saved with prepended spaces boost::replace_all(im_text, NEW_LINE, NEW_LINE_SPACE_PREFIX); @@ -528,12 +599,12 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params LLLogChatTimeScanner::instance().checkAndCutOffDate(timestamp); } - im[IM_TIME] = timestamp; + im[LL_IM_TIME] = timestamp; } else { //timestamp is optional - im[IM_TIME] = ""; + im[LL_IM_TIME] = ""; } bool has_stuff = matches[IDX_STUFF].matched; @@ -559,8 +630,8 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params if (!has_name || name == SYSTEM_FROM) { //name is optional too - im[IM_FROM] = SYSTEM_FROM; - im[IM_FROM_ID] = LLUUID::null; + im[LL_IM_FROM] = SYSTEM_FROM; + im[LL_IM_FROM_ID] = LLUUID::null; } //possibly a case of complex object names consisting of 3+ words @@ -569,8 +640,8 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params U32 divider_pos = stuff.find(NAME_TEXT_DIVIDER); if (divider_pos != std::string::npos && divider_pos < (stuff.length() - NAME_TEXT_DIVIDER.length())) { - im[IM_FROM] = stuff.substr(0, divider_pos); - im[IM_TEXT] = stuff.substr(divider_pos + NAME_TEXT_DIVIDER.length()); + im[LL_IM_FROM] = stuff.substr(0, divider_pos); + im[LL_IM_TEXT] = stuff.substr(divider_pos + NAME_TEXT_DIVIDER.length()); return true; } } @@ -578,7 +649,7 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params if (!has_name) { //text is mandatory - im[IM_TEXT] = stuff; + im[LL_IM_TEXT] = stuff; return true; //parse as a message from Second Life } @@ -590,45 +661,15 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params { std::string agent_name; LLAgentUI::buildFullname(agent_name); - im[IM_FROM] = agent_name; - im[IM_FROM_ID] = gAgentID; + im[LL_IM_FROM] = agent_name; + im[LL_IM_FROM_ID] = gAgentID; } else { - im[IM_FROM] = name; + im[LL_IM_FROM] = name; } - im[IM_TEXT] = name_and_text[IDX_TEXT]; + im[LL_IM_TEXT] = name_and_text[IDX_TEXT]; return true; //parsed name and message text, maybe have a timestamp too } -std::string LLLogChat::oldLogFileName(std::string filename) -{ - std::string scanResult; - std::string directory = gDirUtilp->getPerAccountChatLogsDir();/* get Users log directory */ - directory += gDirUtilp->getDirDelimiter();/* add final OS dependent delimiter */ - filename=cleanFileName(filename);/* lest make shure the file name has no invalad charecters befor making the pattern */ - std::string pattern = (filename+(( filename == "chat" ) ? "-???\?-?\?-??.txt" : "-???\?-??.txt"));/* create search pattern*/ - //LL_INFOS("") << "Checking:" << directory << " for " << pattern << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ - std::vector<std::string> allfiles; - - LLDirIterator iter(directory, pattern); - while (iter.next(scanResult)) - { - //LL_INFOS("") << "Found :" << scanResult << LL_ENDL; - allfiles.push_back(scanResult); - } - - if (allfiles.size() == 0) // if no result from date search, return generic filename - { - scanResult = directory + filename + ".txt"; - } - else - { - std::sort(allfiles.begin(), allfiles.end()); - scanResult = directory + allfiles.back(); - // thisfile is now the most recent version of the file. - } - //LL_INFOS("") << "Reading:" << scanResult << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ - return scanResult; -} diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index d3e9adcc37..b35a94b4b3 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -49,6 +49,7 @@ public: const std::string& from, const LLUUID& from_id, const std::string& line); + static void getListOfTranscriptFiles(std::vector<std::string>& list); /** @deprecated @see loadChatHistory() */ static void loadHistory(const std::string& filename, @@ -56,8 +57,13 @@ public: void* userdata); static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD()); + + typedef boost::signals2::signal<void ()> save_history_signal_t; + static boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb); + private: static std::string cleanFileName(std::string filename); + static save_history_signal_t * sSaveHistorySignal; }; /** @@ -113,9 +119,10 @@ protected: }; // LLSD map lookup constants -extern const std::string IM_TIME; //("time"); -extern const std::string IM_TEXT; //("message"); -extern const std::string IM_FROM; //("from"); -extern const std::string IM_FROM_ID; //("from_id"); +extern const std::string LL_IM_TIME; //("time"); +extern const std::string LL_IM_TEXT; //("message"); +extern const std::string LL_IM_FROM; //("from"); +extern const std::string LL_IM_FROM_ID; //("from_id"); +extern const std::string LL_TRANSCRIPT_FILE_EXTENSION; //("ll.txt"); #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 8489e92d15..f141419c43 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6943,7 +6943,7 @@ void process_user_info_reply(LLMessageSystem* msg, void**) std::string dir_visibility; msg->getString( "UserData", "DirectoryVisibility", dir_visibility); - LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email, email); + LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email); LLFloaterSnapshot::setAgentEmail(email); } diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 6a464ccdc4..9c36873141 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -8316,4 +8316,30 @@ Attempt cancelled. yestext="Yes"/> </notification> + <notification + icon="alertmodal.tga" + name="PreferenceChatClearLog" + type="alertmodal"> + This will delete the log of previous conversations, and all transcripts of those conversations. Proceed? + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm before I delete the log of previous conversations." + name="okcancelignore" + notext="Cancel" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="PreferenceChatDeleteTranscripts" + type="alertmodal"> + This will delete transcripts for all previous conversations. The list of conversations will not be affected. Proceed? + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm before I delete transcripts." + name="okcancelignore" + notext="Cancel" + yestext="OK"/> + </notification> + </notifications> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 37bfbae991..4f33699aa6 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel border="true" - follows="left|top|right|bottom" + has_border="true" height="408" label="Text Chat" layout="topleft" @@ -12,8 +12,7 @@ <panel border="false" - follows="left|top" - height="90" + height="60" layout="topleft" top="10" left="13" @@ -27,7 +26,9 @@ layout="topleft" top="0" name="play_typing_animation" - width="330" /> + width="330"> + </check_box> + <check_box enabled="false" height="16" @@ -35,26 +36,21 @@ layout="topleft" name="send_im_to_email" top_pad="6" - width="330" /> - <check_box - control_name="KeepConversationLogTranscripts" - height="16" - label="Keep a conversation log and transcripts" - layout="topleft" - name="keep_convo_log_and_transcripts" - top_pad="6" - width="330" /> + width="330"> + </check_box> + <check_box - control_name="UseChatBubbles" - follows="left|top" + control_name="VoiceCallsFriendsOnly" height="16" - label="Bubble Chat" + label="Only friends and groups can call or IM me" layout="topleft" + name="voice_call_friends_only_check" top_pad="6" - name="bubble_text_chat" - width="330" /> + width="350"> + <check_box.label_text text_color="White" /> + </check_box> + <text - follows="left|top" layout="topleft" left="345" height="12" @@ -63,67 +59,65 @@ top="0"> Font size: </text> - <radio_group - height="90" - layout="topleft" - left="352" + + <combo_box control_name="ChatFontSize" + height="23" + layout="topleft" + left="341" name="chat_font_size" - top_pad="0" - width="50"> - <radio_item - height="16" + top_pad="5" + width="100"> + <item label="Small" - layout="topleft" - name="radio" - value="0" - top="10" - width="125" /> - <radio_item - height="16" + name="Small" + value="0"/> + <item label="Medium" - layout="topleft" - name="radio2" - value="1" - top_pad="6" - width="125" /> - <radio_item - height="16" + name="Medium" + value="1"/> + <item label="Large" - layout="topleft" - name="radio3" - value="2" - top_pad="6" - width="125" /> - </radio_group> - - </panel> + name="Large" + value="2"/> + <combo_box.drop_down_button label_color="White" /> + </combo_box> + + <check_box + control_name="UseChatBubbles" + height="16" + label="Bubble Chat" + layout="topleft" + top_pad="4" + name="bubble_text_chat" + width="330"> + </check_box> + + </panel> <panel border="false" - follows="left|top" - height="198" + height="165" layout="topleft" left="13" width="517"> <text - follows="left|top" layout="topleft" height="12" name="notifications" left="0" + text_color="White" width="120"> - Notifications: + Notifications </text> <text - follows="left|top" layout="topleft" height="12" name="friend_ims" width="145" left="0" - top_pad="15"> + top_pad="13"> Friend IMs: </text> <combo_box @@ -134,31 +128,30 @@ top_delta="-6" name="FriendIMOptions" width="223"> - <combo_box.item + <item label="Open Conversations window" name="OpenConversationsWindow" value="openconversations"/> - <combo_box.item + <item label="Pop up the message" name="PopUpMessage" value="toast"/> - <combo_box.item + <item label="Flash toolbar button" name="FlashToolbarButton" value="flash"/> - <combo_box.item + <item label="None" name="None" value="none"/> </combo_box> <text - follows="left|top" layout="topleft" height="12" name="non_friend_ims" width="145" left="0" - top_pad="15"> + top_pad="9"> Non-friend IMs: </text> <combo_box @@ -169,31 +162,30 @@ top_delta="-6" name="NonFriendIMOptions" width="223"> - <combo_box.item + <item label="Open Conversations window" name="OpenConversationsWindow" value="openconversations"/> - <combo_box.item + <item label="Pop up the message" name="PopUpMessage" value="toast"/> - <combo_box.item + <item label="Flash toolbar button" name="FlashToolbarButton" value="flash"/> - <combo_box.item + <item label="None" name="None" value="none"/> </combo_box> <text - follows="left|top" layout="topleft" left="0" height="13" name="conference_ims" width="145" - top_pad="14"> + top_pad="9"> Conference IMs: </text> <combo_box @@ -204,31 +196,30 @@ top_delta="-6" name="ConferenceIMOptions" width="223"> - <combo_box.item + <item label="Open Conversations window" name="OpenConversationsWindow" value="openconversations"/> - <combo_box.item + <item label="Pop up the message" name="PopUpMessage" value="toast"/> - <combo_box.item + <item label="Flash toolbar button" name="FlashToolbarButton" value="flash"/> - <combo_box.item + <item label="None" name="None" value="none"/> </combo_box> <text - follows="left|top" layout="topleft" left="0" height="13" name="group_chat" width="145" - top_pad="14"> + top_pad="9"> Group chat: </text> <combo_box @@ -239,31 +230,30 @@ top_delta="-6" name="GroupChatOptions" width="223"> - <combo_box.item + <item label="Open Conversations window" name="OpenConversationsWindow" value="openconversations"/> - <combo_box.item + <item label="Pop up the message" name="PopUpMessage" value="toast"/> - <combo_box.item + <item label="Flash toolbar button" name="FlashToolbarButton" value="flash"/> - <combo_box.item + <item label="None" name="None" value="none"/> </combo_box> <text - follows="left|top" layout="topleft" left="0" height="12" name="nearby_chat" width="145" - top_pad="14"> + top_pad="9"> Nearby chat: </text> <combo_box @@ -274,31 +264,30 @@ top_delta="-6" name="NearbyChatOptions" width="223"> - <combo_box.item + <item label="Open Conversations window" name="OpenConversationsWindow" value="openconversations"/> - <combo_box.item + <item label="Pop up the message" name="PopUpMessage" value="toast"/> - <combo_box.item + <item label="Flash toolbar button" name="FlashToolBarButton" value="flash"/> - <combo_box.item + <item label="None" name="None" value="none"/> </combo_box> <text - follows="left|top" layout="topleft" left="0" height="13" name="notifications_alert" width="500" - top_pad="11" + top_pad="9" visible="true" text_color="DrYellow"> To temporarily stop all notifications, use Communicate > Do Not Disturb. @@ -308,14 +297,13 @@ <panel border="false" - follows="left|top" - height="67" + height="50" layout="topleft" left="13" + top_pad="10" width="517"> <text - follows="left|top" layout="topleft" left="0" name="play_sound" @@ -360,9 +348,123 @@ width="150" /> </panel> + + <view_border + bevel_style="none" + height="0" + layout="topleft" + left="13" + name="cost_text_border" + top_pad="5" + width="495"/> + + <panel + height="50" + layout="topleft" + left="13" + top_pad="10" + width="505"> + + <text + layout="topleft" + left="0" + text_color="White" + height="12" + top="5" + width="55"> + Save: + </text> + + <combo_box + control_name="KeepConversationLogTranscripts" + height="23" + layout="topleft" + left_pad="5" + name="chat_font_size" + top="0" + width="165"> + <item + label="Log and transcripts" + value="2"/> + <item + label="Log only" + value="1"/> + <item + label="No log or transcripts" + value="0"/> + <drop_down_button label_color="White" /> + </combo_box> + + <button + enabled="false" + height="23" + label="Clear log..." + label_color="White" + layout="topleft" + left_pad="5" + top="0" + name="clear_log" + width="110"> + <commit_callback + function="Pref.ClearLog" /> + </button> + + <button + enabled="false" + height="23" + label="Delete transcripts..." + label_color="White" + layout="topleft" + left_pad="5" + top="0" + name="delete_transcripts" + width="147"> + <button.commit_callback + function="Pref.DeleteTranscripts" /> + </button> + + <text + layout="topleft" + left="0" + text_color="White" + height="12" + top_pad="15" + width="55"> + Location: + </text> + + <line_editor + control_name="InstantMessageLogPath" + border_style="line" + border_thickness="1" + font="SansSerif" + height="23" + layout="topleft" + left_pad="55" + max_length="4096" + name="log_path_string" + top_delta="-5" + width="185"> + </line_editor> + + <button + enabled="false" + follows="left|top" + height="23" + label="Browse..." + label_color="White" + label_selected="Browse" + layout="topleft" + left_pad="5" + name="log_path_button" + top_delta="0" + width="112"> + <commit_callback function="Pref.LogPath" /> + </button> + + </panel> <button - follows="left|top" height="23" label="Translation..." layout="topleft" @@ -370,11 +472,10 @@ name="ok_btn" top="-29" width="170"> - <button.commit_callback + <commit_callback function="Pref.TranslationSettings" /> </button> <button - follows="top|left" height="23" layout="topleft" top_pad="-23" @@ -385,7 +486,6 @@ width="150"> </button> <button - follows="top|left" height="23" layout="topleft" top_pad="-23" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index 587c461bee..78743d26bb 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -1,72 +1,69 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel - border="true" - follows="left|top|right|bottom" - height="408" - label="Communication" - layout="topleft" - left="102" - name="im" - top="1" - width="517"> - <panel.string - name="log_in_to_change"> - log in to change - </panel.string> - <button - follows="left|bottom" - height="23" - label="Clear History" - tool_tip="Clear login image, last location, teleport history, web, and texture cache" - layout="topleft" - left="30" - name="clear_cache" - top="10" - width="145"> - <button.commit_callback - function="Pref.WebClearCache" /> - </button> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_pad="10" - mouse_opaque="false" - name="cache_size_label_l" - top_delta="3" - text_color="LtGray_50" - width="300"> - (Locations, images, web, search history) - </text> - <check_box - height="16" - enabled="false" - label="Show me in Search results" - layout="topleft" - left="30" - name="online_searchresults" - top_pad="20" - width="350" /> - <check_box - height="16" - enabled="false" - label="Only friends and groups know I'm online" - layout="topleft" - left="30" - name="online_visibility" - top_pad="30" - width="350" /> - <check_box - control_name="VoiceCallsFriendsOnly" - height="16" - label="Only friends and groups can call or IM me" - layout="topleft" - left="30" - name="voice_call_friends_only_check" - top_pad="10" - width="350" /> + border="true" + follows="left|top|right|bottom" + height="408" + label="Communication" + layout="topleft" + left="102" + name="im" + top="1" + width="517"> + + <panel.string + name="log_in_to_change"> + log in to change + </panel.string> + + <button + follows="left|bottom" + height="23" + label="Clear History" + tool_tip="Clear login image, last location, teleport history, web, and texture cache" + layout="topleft" + left="30" + name="clear_cache" + top="10" + width="145"> + <button.commit_callback + function="Pref.WebClearCache" /> + </button> + + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left_pad="10" + mouse_opaque="false" + name="cache_size_label_l" + top_delta="3" + text_color="LtGray_50" + width="300"> + (Locations, images, web, search history) + </text> + + <check_box + height="16" + enabled="false" + label="Show me in Search results" + layout="topleft" + left="30" + name="online_searchresults" + top_pad="20" + width="350" /> + + <check_box + height="16" + enabled="false" + label="Only friends and groups know I'm online" + layout="topleft" + left="30" + name="online_visibility" + top_pad="30" + width="350" /> + <check_box enabled_control="EnableVoiceChat" control_name="AutoDisengageMic" @@ -87,100 +84,7 @@ name="favorites_on_login_check" top_pad="10" width="350" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="30" - mouse_opaque="false" - name="Logs:" - top_pad="20" - width="350"> - Chat Logs: - </text> - <check_box - enabled="false" - control_name="LogNearbyChat" - height="16" - label="Save nearby chat logs on my computer" - layout="topleft" - left="30" - name="log_nearby_chat" - top_pad="10" - width="350"> - </check_box> - <check_box - enabled="false" - control_name="LogInstantMessages" - height="16" - label="Save IM logs on my computer" - layout="topleft" - left="30" - name="log_instant_messages" - top_pad="10" - width="350"> - </check_box> - <check_box - control_name="LogTimestamp" - enabled="false" - height="16" - label="Add timestamp to each line in chat log" - layout="topleft" - left_delta="0" - name="show_timestamps_check_im" - top_pad="10" - width="237" /> - <check_box - control_name="LogFileNamewithDate" - enabled="false" - height="16" - label="Add datestamp to log file name." - layout="topleft" - left_delta="5" - name="logfile_name_datestamp" - top_pad="10" - width="350"/> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="0" - mouse_opaque="false" - name="log_path_desc" - top_pad="30" - width="128"> - Location of logs: - </text> - <line_editor - bottom="366" - control_name="InstantMessageLogPath" - follows="top|left|right" - halign="right" - height="23" - layout="topleft" - left_delta="0" - mouse_opaque="false" - name="log_path_string" - top_pad="5" - width="250"/> - <button - enabled="false" - follows="right|bottom" - height="23" - label="Browse" - label_selected="Browse" - layout="topleft" - left_pad="5" - name="log_path_button" - top_delta="0" - width="145"> - <button.commit_callback - function="Pref.LogPath" /> - </button> + <button follows="left|bottom" height="23" -- cgit v1.2.3 From d67804543d4042c1196c05db5303b76089d4ade2 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Fri, 25 Jan 2013 01:57:56 +0000 Subject: CHUI-291 FIX New auto-replace feature does not work with chui text input boxes in conversation floater Fixed autoreplace in LLTextEditor so it updates correctly and works with undo --- indra/llui/lltexteditor.cpp | 24 +++++++++++++++++------- indra/llui/lltexteditor.h | 8 ++++---- indra/newview/llfloaterimnearbychat.cpp | 4 ++-- 3 files changed, 23 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index d297e54f2f..42c5f150dc 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -246,8 +246,8 @@ LLTextEditor::Params::Params() } LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : - LLTextBase(p), - mAutoreplaceCallback(), + LLTextBase(p), + mAutoreplaceCallback(), mBaseDocIsPristine(TRUE), mPristineCmd( NULL ), mLastCmd( NULL ), @@ -1099,11 +1099,21 @@ void LLTextEditor::addChar(llwchar wc) setCursorPos(mCursorPos + addChar( mCursorPos, wc )); - if (!mReadOnly && mAutoreplaceCallback != NULL) - { - // call callback - mAutoreplaceCallback(getViewModel()->getEditableDisplay(), mCursorPos); - } + if (!mReadOnly && mAutoreplaceCallback != NULL) + { + // autoreplace on a copy of the text (so we can go through proper channels to set it later) + LLWString new_text(getWText()); + S32 new_cursor_pos(mCursorPos); + mAutoreplaceCallback(new_text, new_cursor_pos); + + if (new_text != getWText()) + { + // setText() might be simpler here but it wipes the undo stack (bad) + remove(0, getWText().length(), true); + insert(0, new_text, false, LLTextSegmentPtr()); + setCursorPos(new_cursor_pos); + } + } } void LLTextEditor::addLineBreakChar() diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index ae5a983b60..7f0dbc9865 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -157,10 +157,10 @@ public: BOOL isPristine() const; BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; } - // Autoreplace (formerly part of LLLineEditor) - typedef boost::function<void(LLWString&, S32&)> autoreplace_callback_t; - autoreplace_callback_t mAutoreplaceCallback; - void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } + // Autoreplace (formerly part of LLLineEditor) + typedef boost::function<void(LLWString&, S32&)> autoreplace_callback_t; + autoreplace_callback_t mAutoreplaceCallback; + void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } // // Text manipulation diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 73eb822036..38f49e76d4 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -112,8 +112,8 @@ BOOL LLFloaterIMNearbyChat::postBuild() { setIsSingleInstance(TRUE); BOOL result = LLFloaterIMSessionTab::postBuild(); - - mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); + + mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); mInputEditor->setCommitCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxCommit, this)); mInputEditor->setKeystrokeCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxKeystroke, this)); mInputEditor->setFocusLostCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxFocusLost, this)); -- cgit v1.2.3 From 163f3de73d93be8f5e482be03a1952244cadee68 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Fri, 25 Jan 2013 19:53:12 +0000 Subject: CHUI-291 FIX New auto-replace feature does not work with chui text input boxes in conversation floater Modified LLAutoReplace to pass back a string for replacement instead of modifying the input string --- indra/llui/lltexteditor.cpp | 19 +++++----- indra/llui/lltexteditor.h | 2 +- indra/newview/llautoreplace.cpp | 65 ++++++++++++++++++--------------- indra/newview/llautoreplace.h | 5 ++- indra/newview/llfloaterimnearbychat.cpp | 2 +- indra/newview/llfloaterimsession.cpp | 2 +- 6 files changed, 51 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 42c5f150dc..562bbc7100 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1101,16 +1101,17 @@ void LLTextEditor::addChar(llwchar wc) if (!mReadOnly && mAutoreplaceCallback != NULL) { - // autoreplace on a copy of the text (so we can go through proper channels to set it later) - LLWString new_text(getWText()); - S32 new_cursor_pos(mCursorPos); - mAutoreplaceCallback(new_text, new_cursor_pos); - - if (new_text != getWText()) + // autoreplace the text, if necessary + S32 replacement_start; + S32 replacement_length; + LLWString replacement_string; + S32 new_cursor_pos = mCursorPos; + mAutoreplaceCallback(replacement_start, replacement_length, replacement_string, new_cursor_pos, getWText()); + + if (replacement_length > 0 || !replacement_string.empty()) { - // setText() might be simpler here but it wipes the undo stack (bad) - remove(0, getWText().length(), true); - insert(0, new_text, false, LLTextSegmentPtr()); + remove(replacement_start, replacement_length, true); + insert(replacement_start, replacement_string, false, LLTextSegmentPtr()); setCursorPos(new_cursor_pos); } } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 7f0dbc9865..5e189070fa 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -158,7 +158,7 @@ public: BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; } // Autoreplace (formerly part of LLLineEditor) - typedef boost::function<void(LLWString&, S32&)> autoreplace_callback_t; + typedef boost::function<void(S32&, S32&, LLWString&, S32&, const LLWString&)> autoreplace_callback_t; autoreplace_callback_t mAutoreplaceCallback; void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } diff --git a/indra/newview/llautoreplace.cpp b/indra/newview/llautoreplace.cpp index 94773e312c..1d72397cbc 100644 --- a/indra/newview/llautoreplace.cpp +++ b/indra/newview/llautoreplace.cpp @@ -32,53 +32,58 @@ const char* LLAutoReplace::SETTINGS_FILE_NAME = "autoreplace.xml"; -void LLAutoReplace::autoreplaceCallback(LLWString& inputText, S32& cursorPos) +void LLAutoReplace::autoreplaceCallback(S32& replacement_start, S32& replacement_length, LLWString& replacement_string, S32& cursor_pos, const LLWString& input_text) { + // make sure these returned values are cleared in case there is no replacement + replacement_start = 0; + replacement_length = 0; + replacement_string.clear(); + static LLCachedControl<bool> perform_autoreplace(gSavedSettings, "AutoReplace"); - if(perform_autoreplace) + if (perform_autoreplace) { - S32 wordEnd = cursorPos-1; + S32 word_end = cursor_pos - 1; - bool atSpace = (inputText[wordEnd] == ' '); - bool haveWord = (LLWStringUtil::isPartOfWord(inputText[wordEnd])); + bool at_space = (input_text[word_end] == ' '); + bool have_word = (LLWStringUtil::isPartOfWord(input_text[word_end])); - if (atSpace || haveWord) + if (at_space || have_word) { - if (atSpace && wordEnd > 0) + if (at_space && word_end > 0) { // find out if this space immediately follows a word - wordEnd--; - haveWord = (LLWStringUtil::isPartOfWord(inputText[wordEnd])); + word_end--; + have_word = (LLWStringUtil::isPartOfWord(input_text[word_end])); } - if (haveWord) + if (have_word) { - // wordEnd points to the end of a word, now find the start of the word + // word_end points to the end of a word, now find the start of the word std::string word; - S32 wordStart = wordEnd; - for ( S32 backOne = wordStart - 1; - backOne >= 0 && LLWStringUtil::isPartOfWord(inputText[backOne]); - backOne-- - ) + S32 word_start = word_end; + for (S32 back_one = word_start - 1; + back_one >= 0 && LLWStringUtil::isPartOfWord(input_text[back_one]); + back_one-- + ) { - wordStart--; // walk wordStart back to the beginning of the word + word_start--; // walk word_start back to the beginning of the word } - LL_DEBUGS("AutoReplace")<<"wordStart: "<<wordStart<<" wordEnd: "<<wordEnd<<LL_ENDL; - std::string strText = std::string(inputText.begin(), inputText.end()); - std::string lastWord = strText.substr(wordStart, wordEnd-wordStart+1); - std::string replacementWord( mSettings.replaceWord( lastWord ) ); + LL_DEBUGS("AutoReplace") << "word_start: " << word_start << " word_end: " << word_end << LL_ENDL; + std::string str_text = std::string(input_text.begin(), input_text.end()); + std::string last_word = str_text.substr(word_start, word_end - word_start + 1); + std::string replacement_word(mSettings.replaceWord(last_word)); - if ( replacementWord != lastWord ) + if (replacement_word != last_word) { // The last word is one for which we have a replacement - if (atSpace) + if (at_space) { - // replace the last word in the input - LLWString strNew = utf8str_to_wstring(replacementWord); - LLWString strOld = utf8str_to_wstring(lastWord); - int size_change = strNew.size() - strOld.size(); - - inputText.replace(wordStart,lastWord.length(),strNew); - cursorPos+=size_change; + // return the replacement string + replacement_start = word_start; + replacement_length = last_word.length(); + replacement_string = utf8str_to_wstring(replacement_word); + LLWString old_string = utf8str_to_wstring(last_word); + S32 size_change = replacement_string.size() - old_string.size(); + cursor_pos += size_change; } } } diff --git a/indra/newview/llautoreplace.h b/indra/newview/llautoreplace.h index bbb86294bc..9eecc2d981 100644 --- a/indra/newview/llautoreplace.h +++ b/indra/newview/llautoreplace.h @@ -183,7 +183,8 @@ class LLAutoReplaceSettings * When the end of a word is detected (defined as any punctuation character, * or any whitespace except newline or return), the preceding word is used * as a lookup key in an ordered list of maps. If a match is found in any - * map, the keyword is replaced by the associated value from the map. + * map, the replacement start index and length are returned along with the + * new replacement string. * * See the autoreplaceCallback method for how to add autoreplace functionality * to a text entry tool. @@ -192,7 +193,7 @@ class LLAutoReplace : public LLSingleton<LLAutoReplace> { public: /// Callback that provides the hook for use in text entry methods - void autoreplaceCallback(LLWString& inputText, S32& cursorPos); + void autoreplaceCallback(S32& replacement_start, S32& replacement_length, LLWString& replacement_string, S32& cursor_pos, const LLWString& input_text); /// Get a copy of the current settings LLAutoReplaceSettings getSettings(); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 38f49e76d4..a2dfd4b53e 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -113,7 +113,7 @@ BOOL LLFloaterIMNearbyChat::postBuild() setIsSingleInstance(TRUE); BOOL result = LLFloaterIMSessionTab::postBuild(); - mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); + mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2, _3, _4, _5)); mInputEditor->setCommitCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxCommit, this)); mInputEditor->setKeystrokeCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxKeystroke, this)); mInputEditor->setFocusLostCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxFocusLost, this)); diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index a2c7bacb5d..a08479c7be 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -332,7 +332,7 @@ BOOL LLFloaterIMSession::postBuild() BOOL result = LLFloaterIMSessionTab::postBuild(); mInputEditor->setMaxTextLength(1023); - mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); + mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2, _3, _4, _5)); mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) ); mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) ); mInputEditor->setKeystrokeCallback( boost::bind(onInputEditorKeystroke, _1, this) ); -- cgit v1.2.3 From fa54b50e029c963d90b5533174a29eefc22227e5 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Sat, 26 Jan 2013 00:19:29 +0000 Subject: CHUI-644 FIX [CHUIBUG]Received IM's Don't Always Appear in Communication Console Immediately. Added call to LLFloaterIMContainer::selectConversation() in on_new_message for LLIMView --- indra/newview/llimview.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cb03c1d234..c94f2e967e 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -144,7 +144,7 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id, args["FROM"] = av_name.getCompleteName(); args["FROM_ID"] = msg["from_id"]; args["SESSION_ID"] = msg["session_id"]; - LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); + LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); } void on_new_message(const LLSD& msg) @@ -239,6 +239,12 @@ void on_new_message(const LLSD& msg) { LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); } + + // Make sure the message actually appears, without having to click on the conversation + if(!conversation_floater_is_closed) + { + im_box->selectConversation(session_id); + } } } } @@ -276,9 +282,9 @@ void on_new_message(const LLSD& msg) if(!gAgent.isDoNotDisturb()) { - //Surface conversations floater - LLFloaterReg::showInstance("im_container"); - } + //Surface conversations floater + LLFloaterReg::showInstance("im_container"); + } //If in DND mode, allow notification to be stored so upon DND exit //useMostItrusiveIMNotification will be called to notify user a message exists @@ -287,8 +293,8 @@ void on_new_message(const LLSD& msg) && gAgent.isDoNotDisturb()) { LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); - } -} + } + } } } -- cgit v1.2.3 From c1b8e4b1ffcb9c759d109d603004f363dbb0df63 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Sat, 26 Jan 2013 00:36:49 +0000 Subject: undid accidental revert of someone else's fix --- indra/newview/llimview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index c94f2e967e..acbf5fcde4 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -144,7 +144,7 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id, args["FROM"] = av_name.getCompleteName(); args["FROM_ID"] = msg["from_id"]; args["SESSION_ID"] = msg["session_id"]; - LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); + LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); } void on_new_message(const LLSD& msg) -- cgit v1.2.3 From c418d616276ce16d910c6e5528f6aa058803e1c7 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 25 Jan 2013 17:47:36 -0800 Subject: CHUI-667 Upon exit from DND mode, a maximum of one sound should be played. Solution. Added a deferred sound class which will have sound id's added to it and upon unmuting the deferred sounds will be played. --- indra/llui/llui.cpp | 31 +++++++++++++-- indra/llui/llui.h | 3 ++ indra/newview/CMakeLists.txt | 2 + indra/newview/llappviewer.cpp | 14 ++++++- indra/newview/lldeferredsounds.cpp | 45 ++++++++++++++++++++++ indra/newview/lldeferredsounds.h | 44 +++++++++++++++++++++ .../newview/lldonotdisturbnotificationstorage.cpp | 20 ++++++++++ indra/newview/llnotificationofferhandler.cpp | 3 +- indra/newview/llprogressview.cpp | 4 +- indra/newview/llvieweraudio.cpp | 7 ++++ 10 files changed, 165 insertions(+), 8 deletions(-) create mode 100644 indra/newview/lldeferredsounds.cpp create mode 100644 indra/newview/lldeferredsounds.h (limited to 'indra') diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index ee09625890..2a774d54a3 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -77,6 +77,7 @@ std::list<std::string> gUntranslated; /*static*/ LLUI::settings_map_t LLUI::sSettingGroups; /*static*/ LLImageProviderInterface* LLUI::sImageProvider = NULL; /*static*/ LLUIAudioCallback LLUI::sAudioCallback = NULL; +/*static*/ LLUIAudioCallback LLUI::sDeferredAudioCallback = NULL; /*static*/ LLVector2 LLUI::sGLScaleFactor(1.f, 1.f); /*static*/ LLWindow* LLUI::sWindow = NULL; /*static*/ LLView* LLUI::sRootView = NULL; @@ -101,16 +102,18 @@ static LLDefaultChildRegistry::Register<LLToolBar> register_toolbar("toolbar"); // // Functions // -void make_ui_sound(const char* namep) + +LLUUID find_ui_sound(const char * namep) { std::string name = ll_safe_string(namep); + LLUUID uuid = LLUUID(NULL); if (!LLUI::sSettingGroups["config"]->controlExists(name)) { llwarns << "tried to make UI sound for unknown sound name: " << name << llendl; } else { - LLUUID uuid(LLUI::sSettingGroups["config"]->getString(name)); + uuid = LLUUID(LLUI::sSettingGroups["config"]->getString(name)); if (uuid.isNull()) { if (LLUI::sSettingGroups["config"]->getString(name) == LLUUID::null.asString()) @@ -124,7 +127,6 @@ void make_ui_sound(const char* namep) { llwarns << "UI sound named: " << name << " does not translate to a valid uuid" << llendl; } - } else if (LLUI::sAudioCallback != NULL) { @@ -132,9 +134,28 @@ void make_ui_sound(const char* namep) { llinfos << "UI sound name: " << name << llendl; } - LLUI::sAudioCallback(uuid); } } + + return uuid; +} + +void make_ui_sound(const char* namep) +{ + LLUUID soundUUID = find_ui_sound(namep); + if(soundUUID.notNull()) + { + LLUI::sAudioCallback(soundUUID); + } +} + +void make_ui_sound_deferred(const char* namep) +{ + LLUUID soundUUID = find_ui_sound(namep); + if(soundUUID.notNull()) + { + LLUI::sDeferredAudioCallback(soundUUID); + } } BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom) @@ -1608,6 +1629,7 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv void LLUI::initClass(const settings_map_t& settings, LLImageProviderInterface* image_provider, LLUIAudioCallback audio_callback, + LLUIAudioCallback deferred_audio_callback, const LLVector2* scale_factor, const std::string& language) { @@ -1622,6 +1644,7 @@ void LLUI::initClass(const settings_map_t& settings, sImageProvider = image_provider; sAudioCallback = audio_callback; + sDeferredAudioCallback = deferred_audio_callback; sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor; sWindow = NULL; // set later in startup LLFontGL::sShadowColor = LLUIColorTable::instance().getColor("ColorDropShadow"); diff --git a/indra/llui/llui.h b/indra/llui/llui.h index e54cae1d78..4c1703392a 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -62,6 +62,7 @@ class LLHelp; // UI colors extern const LLColor4 UI_VERTEX_COLOR; void make_ui_sound(const char* name); +void make_ui_sound_deferred(const char * name); BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom); void gl_state_for_2d(S32 width, S32 height); @@ -274,6 +275,7 @@ public: static void initClass(const settings_map_t& settings, LLImageProviderInterface* image_provider, LLUIAudioCallback audio_callback = NULL, + LLUIAudioCallback deferred_audio_callback = NULL, const LLVector2 *scale_factor = NULL, const std::string& language = LLStringUtil::null); static void cleanupClass(); @@ -359,6 +361,7 @@ public: // static settings_map_t sSettingGroups; static LLUIAudioCallback sAudioCallback; + static LLUIAudioCallback sDeferredAudioCallback; static LLVector2 sGLScaleFactor; static LLWindow* sWindow; static LLView* sRootView; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index d40537fc78..bd4cdac5f2 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -151,6 +151,7 @@ set(viewer_SOURCE_FILES lldaycyclemanager.cpp lldebugmessagebox.cpp lldebugview.cpp + lldeferredsounds.cpp lldelayedgestureerror.cpp lldirpicker.cpp lldonotdisturbnotificationstorage.cpp @@ -739,6 +740,7 @@ set(viewer_HEADER_FILES lldaycyclemanager.h lldebugmessagebox.h lldebugview.h + lldeferredsounds.h lldelayedgestureerror.h lldirpicker.h lldonotdisturbnotificationstorage.h diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 3c42734e6e..a291fac5a1 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -201,6 +201,7 @@ #include "llviewercontrol.h" #include "lleventnotifier.h" #include "llcallbacklist.h" +#include "lldeferredsounds.h" #include "pipeline.h" #include "llgesturemgr.h" #include "llsky.h" @@ -220,6 +221,7 @@ #include "llmachineid.h" #include "llmainlooprepeater.h" +#include <queue> // *FIX: These extern globals should be cleaned up. // The globals either represent state/config/resource-storage of either @@ -456,7 +458,7 @@ void idle_afk_check() } // A callback set in LLAppViewer::init() -static void ui_audio_callback(const LLUUID& uuid) +void ui_audio_callback(const LLUUID& uuid) { if (gAudiop) { @@ -464,6 +466,15 @@ static void ui_audio_callback(const LLUUID& uuid) } } +// A callback set in LLAppViewer::init() +static void deferred_ui_audio_callback(const LLUUID& uuid) +{ + if (gAudiop) + { + LLDeferredSounds::instance().deferSound(uuid); + } +} + bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base) { if(!match || !base || base->getPlainText()) @@ -778,6 +789,7 @@ bool LLAppViewer::init() LLUI::initClass(settings_map, LLUIImageList::getInstance(), ui_audio_callback, + deferred_ui_audio_callback, &LLUI::sGLScaleFactor); LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ; diff --git a/indra/newview/lldeferredsounds.cpp b/indra/newview/lldeferredsounds.cpp new file mode 100644 index 0000000000..2b2b493875 --- /dev/null +++ b/indra/newview/lldeferredsounds.cpp @@ -0,0 +1,45 @@ +/** +* @file lldeferredsounds.cpp +* @brief Implementation of lldeferredsounds +* @author Gilbert@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" + +#include "lldeferredsounds.h" + +void ui_audio_callback(const LLUUID& uuid); + +void LLDeferredSounds::deferSound(LLUUID sound) +{ + soundQueue.push(sound); +} +void LLDeferredSounds::playdeferredSounds() +{ + while(soundQueue.size()) + { + ui_audio_callback(soundQueue.front()); + soundQueue.pop(); + } +} diff --git a/indra/newview/lldeferredsounds.h b/indra/newview/lldeferredsounds.h new file mode 100644 index 0000000000..50da9acf2b --- /dev/null +++ b/indra/newview/lldeferredsounds.h @@ -0,0 +1,44 @@ +/** +* @file lldeferredsounds.h +* @brief Header file for lldeferredsounds +* @author Gilbert@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#ifndef LL_LLDEFERREDSOUNDS_H +#define LL_LLDEFERREDSOUNDS_H + +#include "llsingleton.h" + +class LLDeferredSounds : public LLSingleton<LLDeferredSounds> +{ +private: + std::queue<LLUUID> soundQueue; +public: + //Add sounds to be played once progress bar is hidden (such as after teleport or loading screen) + void deferSound(LLUUID sound); + + void playdeferredSounds(); +}; + +#endif // LL_LLDEFERREDSOUNDS_H + diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 15c42e8285..6e39d049a5 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -146,6 +146,7 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() LLNotifications& instance = LLNotifications::instance(); bool imToastExists = false; + bool offerExists = false; for (LLSD::array_const_iterator notification_it = data.beginArray(); notification_it != data.endArray(); @@ -160,6 +161,10 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() { imToastExists = true; } + else if(notificationName == offerName) + { + offerExists = true; + } //New notification needs to be added notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true)); @@ -183,6 +188,11 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() LLFloaterReg::showInstance("im_container"); } + if(imToastExists || offerExists) + { + make_ui_sound_deferred("UISndNewIncomingIMSession"); + } + //writes out empty .xml file (since LLCommunicationChannel::mHistory is empty) saveNotifications(); } @@ -196,6 +206,7 @@ void LLDoNotDisturbNotificationStorage::updateNotifications() LLNotifications& instance = LLNotifications::instance(); bool imToastExists = false; + bool offerExists = false; for (LLCommunicationChannel::history_list_t::const_iterator it = commChannel->beginHistory(); it != commChannel->endHistory(); @@ -208,6 +219,10 @@ void LLDoNotDisturbNotificationStorage::updateNotifications() { imToastExists = true; } + else if(notificationName == offerName) + { + offerExists = true; + } //Notification already exists in notification pipeline (same instance of app running) if (notification) @@ -222,6 +237,11 @@ void LLDoNotDisturbNotificationStorage::updateNotifications() LLFloaterReg::showInstance("im_container"); } + if(imToastExists || offerExists) + { + make_ui_sound("UISndNewIncomingIMSession"); + } + //When exit DND mode, write empty notifications file if(commChannel->getHistorySize()) { diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index da38c9063b..cde7bb18ce 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -120,7 +120,8 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) channel->addToast(p); //Will not play a notification sound for inventory and teleport offer based upon chat preference - bool playSound = !((notification->getName() == "UserGiveItem" + bool playSound = !((notification->isDND()) + && (notification->getName() == "UserGiveItem" && gSavedSettings.getBOOL("PlaySoundInventoryOffer") == FALSE) || notification->getName() == "TeleportOffered" && gSavedSettings.getBOOL("PlaySoundTeleportOffer") == FALSE); diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index f86e583b9e..989f0b0e60 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -96,7 +96,7 @@ BOOL LLProgressView::postBuild() getChild<LLTextBox>("message_text")->setClickedCallback(onClickMessage, this); // hidden initially, until we need it - LLPanel::setVisible(FALSE); + setVisible(FALSE); LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLProgressView::onAlertModal, this, _1)); @@ -265,7 +265,7 @@ void LLProgressView::draw() gFocusMgr.releaseFocusIfNeeded( this ); // turn off panel that hosts intro so we see the world - LLPanel::setVisible(FALSE); + setVisible(FALSE); // stop observing events since we no longer care mMediaCtrl->remObserver( this ); diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index 8d8c401dac..564bf7997a 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -30,6 +30,7 @@ #include "llagent.h" #include "llagentcamera.h" #include "llappviewer.h" +#include "lldeferredsounds.h" #include "llvieweraudio.h" #include "llviewercamera.h" #include "llviewercontrol.h" @@ -388,6 +389,12 @@ void audio_update_volume(bool force_update) gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff")); gAudiop->setMuted(mute_audio || progress_view_visible); + //Play any deferred sounds when unmuted + if(!gAudiop->getMuted()) + { + LLDeferredSounds::instance().playdeferredSounds(); + } + if (force_update) { audio_update_wind(true); -- cgit v1.2.3 From aa524b18e5486b19aede990cb30fb89a0b48c083 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Mon, 28 Jan 2013 14:57:51 +0200 Subject: CHUI-701 FIXED Don't show toasts and flashing, if conversation is opened but isn't focused. --- indra/newview/llfloaterimnearbychathandler.cpp | 8 ++++++++ indra/newview/llimview.cpp | 19 ++++++++----------- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index f64cfd0245..8870d54cd2 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -604,6 +604,14 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, toast_msg = chat_msg.mText; } + //Don't show nearby toast, if conversation is visible but not focused + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(LLUUID()); + if (session_floater + && session_floater->isInVisibleChain() && !session_floater->isMinimized() + && !(session_floater->getHost() && session_floater->getHost()->isMinimized())) + { + return; + } //Will show toast when chat preference is set if(gSavedSettings.getString("NotificationNearbyChatOptions") == "toast") diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cb03c1d234..433ddad35d 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -204,19 +204,16 @@ void on_new_message(const LLSD& msg) bool conversation_floater_not_focused = conversation_floater_is_closed || !im_box->hasFocus(); + // Skip toasting and flashing if we have open window of IM with this session id + if (session_floater + && session_floater->isInVisibleChain() + && !session_floater->isMinimized() + && !(session_floater->getHost() && session_floater->getHost()->isMinimized())) + { + return; + } if ("toast" == action) { - // Skip toasting and flashing if we have open window of IM with this session id - if (session_floater - && session_floater->isInVisibleChain() - && session_floater->hasFocus() - && !session_floater->isMinimized() - && !(session_floater->getHost() && session_floater->getHost()->isMinimized()) - ) - { - return; - } - //User is not focused on conversation containing the message if(session_floater_not_focused) { -- cgit v1.2.3 From 4a96941b73254538c27a83fe28c637065e93f2e2 Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Mon, 28 Jan 2013 18:06:27 +0200 Subject: CHUI-395 (Group moderators are not shown as Moderators in group conversation) --- indra/newview/llconversationmodel.cpp | 18 ++++++++++++++++++ indra/newview/llconversationmodel.h | 6 ++++-- indra/newview/llfloaterimsessiontab.cpp | 22 ++++++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index a8da4908ce..7184a70db5 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -35,6 +35,7 @@ #include "llsdutil.h" #include "llconversationmodel.h" #include "llimview.h" //For LLIMModel +#include "lltrans.h" // // Conversation items : common behaviors @@ -461,6 +462,7 @@ LLConversationItemParticipant::LLConversationItemParticipant(std::string display LLConversationItem(display_name,uuid,root_view_model), mIsMuted(false), mIsModerator(false), + mDisplayModeratorLabel(false), mDistToAgent(-1.0) { mDisplayName = display_name; @@ -471,6 +473,7 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, LLConversationItem(uuid,root_view_model), mIsMuted(false), mIsModerator(false), + mDisplayModeratorLabel(false), mDistToAgent(-1.0) { mConvType = CONV_PARTICIPANT; @@ -503,6 +506,12 @@ void LLConversationItemParticipant::updateName(const LLAvatarName& av_name) { mName = av_name.getUserName(); mDisplayName = av_name.getDisplayName(); + + if (mDisplayModeratorLabel) + { + mDisplayName += " " + LLTrans::getString("IM_moderator_label"); + } + renameItem(mDisplayName); if (mParent != NULL) { @@ -541,6 +550,15 @@ void LLConversationItemParticipant::dumpDebugData() llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", display name = " << mDisplayName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; } +void LLConversationItemParticipant::setDisplayModeratorRole(bool displayRole) +{ + if (displayRole != mDisplayModeratorLabel) + { + mDisplayModeratorLabel = displayRole; + updateName(); + } +} + // // LLConversationSort // diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 6aaea041e4..c907d1d6d2 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -205,13 +205,15 @@ public: void dumpDebugData(); void setModeratorOptionsVisible(bool visible) { mDisplayModeratorOptions = visible; } + void setDisplayModeratorRole(bool displayRole); private: void onAvatarNameCache(const LLAvatarName& av_name); // callback used by fetchAvatarName void updateName(const LLAvatarName& av_name); - bool mIsMuted; // default is false - bool mIsModerator; // default is false + bool mIsMuted; // default is false + bool mIsModerator; // default is false + bool mDisplayModeratorLabel; // default is false std::string mDisplayName; F64 mDistToAgent; // Distance to the agent. A negative (meaningless) value means the distance has not been set. boost::signals2::connection mAvatarNameCacheConnection; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 37404ab716..2f6a9d22c1 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -497,6 +497,28 @@ void LLFloaterIMSessionTab::refreshConversation() } updateSessionName(session_name); } + + LLParticipantList* participant_list = getParticipantList(); + if (participant_list) + { + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = participant_list->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = participant_list->getChildrenEnd(); + LLIMSpeakerMgr *speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + while (current_participant_model != end_participant_model) + { + LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); + if (speaker_mgr && participant_model) + { + LLSpeaker *participant_speaker = speaker_mgr->findSpeaker(participant_model->getUUID()); + LLSpeaker *agent_speaker = speaker_mgr->findSpeaker(gAgentID); + if (participant_speaker && agent_speaker) + { + participant_model->setDisplayModeratorRole(agent_speaker->mIsModerator && participant_speaker->mIsModerator); + } + } + current_participant_model++; + } + } mConversationViewModel.requestSortAll(); if(mConversationsRoot != NULL) -- cgit v1.2.3 From 57795d3c89b6eee3ff68f327d2a6c840350d8dcb Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Mon, 28 Jan 2013 18:53:46 +0200 Subject: CHUI-706 FIXED Appropriate function is now called in xml --- indra/newview/skins/default/xui/en/menu_url_group.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/menu_url_group.xml b/indra/newview/skins/default/xui/en/menu_url_group.xml index 2cb125ce09..c5eaf94d22 100644 --- a/indra/newview/skins/default/xui/en/menu_url_group.xml +++ b/indra/newview/skins/default/xui/en/menu_url_group.xml @@ -7,7 +7,7 @@ layout="topleft" name="show_group"> <menu_item_call.on_click - function="Url.ShowProfile" /> + function="Url.Execute" /> </menu_item_call> <menu_item_separator layout="topleft" /> -- cgit v1.2.3 From af969270990ca719277def274b8ebf20539cc435 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 28 Jan 2013 15:41:01 -0800 Subject: Fix test failure --- indra/viewer_components/updater/tests/llupdaterservice_test.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index a49bc4161e..de07beee7c 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -83,6 +83,7 @@ std::string LLDir::getSkinFolder() const { return "default"; } std::string LLDir::getLanguage() const { return "en"; } bool LLDir::setCacheDir(const std::string &path){ return true; } void LLDir::dumpCurrentDirectories() {} +void LLDir::updatePerAccountChatLogsDir() {} std::string LLDir::getExpandedFilename(ELLPath location, const std::string &filename) const -- cgit v1.2.3 From 44b681f5db9435f98d52525621aa98b0a8ed3063 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Tue, 29 Jan 2013 00:16:40 +0000 Subject: CHUI-644 FIX [CHUIBUG]Received IM's Don't Always Appear in Communication Console Immediately. Removed new code from on_new_message in LLIMView and instead, changed condition in LLFloaterIMSession::newIMCallback to update messages whenever the floater is visible --- indra/newview/llfloaterimsession.cpp | 2 +- indra/newview/llimview.cpp | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index a08479c7be..31d2c67e29 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -162,7 +162,7 @@ void LLFloaterIMSession::newIMCallback(const LLSD& data) LLFloaterIMSession* floater = LLFloaterReg::findTypedInstance<LLFloaterIMSession>("impanel", session_id); // update if visible, otherwise will be updated when opened - if (floater && (floater->getHost()? floater->hasFocus() : floater->getVisible())) + if (floater && floater->isInVisibleChain()) { floater->updateMessages(); } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index acbf5fcde4..ffbb8471c2 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -239,14 +239,8 @@ void on_new_message(const LLSD& msg) { LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); } - - // Make sure the message actually appears, without having to click on the conversation - if(!conversation_floater_is_closed) - { - im_box->selectConversation(session_id); - } } - } + } } else if ("flash" == action) -- cgit v1.2.3 From 4c5790d4bf24d80fd88f36e85a4aa51d4dc06c30 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 28 Jan 2013 18:27:54 -0800 Subject: CHUI-667: Post code review changes --- indra/llaudio/llaudioengine.cpp | 4 ++++ indra/llaudio/llaudioengine.h | 24 ++++++++++++++++++++++++ indra/newview/llappviewer.cpp | 8 +++----- indra/newview/lldeferredsounds.cpp | 12 ++++++------ indra/newview/lldeferredsounds.h | 6 ++++-- 5 files changed, 41 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index ef560cd7fc..06e752cf34 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -839,6 +839,10 @@ void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_i asp->play(audio_uuid); } +void LLAudioEngine::triggerSound(SoundData& soundData) +{ + triggerSound(soundData.audio_uuid, soundData.owner_id, soundData.gain, soundData.type, soundData.pos_global); +} void LLAudioEngine::setListenerPos(LLVector3 aVec) { diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index df1e4dc305..99b96c3c38 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -66,6 +66,7 @@ class LLAudioChannel; class LLAudioChannelOpenAL; class LLAudioBuffer; class LLStreamingAudioInterface; +struct SoundData; // @@ -144,6 +145,8 @@ public: void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE, const LLVector3d &pos_global = LLVector3d::zero); + void triggerSound(SoundData& soundData); + bool preloadSound(const LLUUID &id); void addAudioSource(LLAudioSource *asp); @@ -456,6 +459,27 @@ protected: LLFrameTimer mLastUseTimer; }; +struct SoundData +{ + LLUUID audio_uuid; + LLUUID owner_id; + F32 gain; + S32 type; + LLVector3d pos_global; + + SoundData(const LLUUID &audio_uuid, + const LLUUID& owner_id, + const F32 gain, + const S32 type = LLAudioEngine::AUDIO_TYPE_NONE, + const LLVector3d &pos_global = LLVector3d::zero) + { + this->audio_uuid = audio_uuid; + this->owner_id = owner_id; + this->gain = gain; + this->type = type; + this->pos_global = pos_global; + } +}; extern LLAudioEngine* gAudiop; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a291fac5a1..d09c835e41 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -221,8 +221,6 @@ #include "llmachineid.h" #include "llmainlooprepeater.h" -#include <queue> - // *FIX: These extern globals should be cleaned up. // The globals either represent state/config/resource-storage of either // this app, or another 'component' of the viewer. App globals should be @@ -458,11 +456,11 @@ void idle_afk_check() } // A callback set in LLAppViewer::init() -void ui_audio_callback(const LLUUID& uuid) +static void ui_audio_callback(const LLUUID& uuid) { if (gAudiop) { - gAudiop->triggerSound(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI); + gAudiop->triggerSound(SoundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI)); } } @@ -471,7 +469,7 @@ static void deferred_ui_audio_callback(const LLUUID& uuid) { if (gAudiop) { - LLDeferredSounds::instance().deferSound(uuid); + LLDeferredSounds::instance().deferSound(SoundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI)); } } diff --git a/indra/newview/lldeferredsounds.cpp b/indra/newview/lldeferredsounds.cpp index 2b2b493875..9416e7cd29 100644 --- a/indra/newview/lldeferredsounds.cpp +++ b/indra/newview/lldeferredsounds.cpp @@ -29,17 +29,17 @@ #include "lldeferredsounds.h" -void ui_audio_callback(const LLUUID& uuid); +#include "llaudioengine.h" -void LLDeferredSounds::deferSound(LLUUID sound) +void LLDeferredSounds::deferSound(SoundData& sound) { - soundQueue.push(sound); + soundVector.push_back(sound); } void LLDeferredSounds::playdeferredSounds() { - while(soundQueue.size()) + while(soundVector.size()) { - ui_audio_callback(soundQueue.front()); - soundQueue.pop(); + gAudiop->triggerSound(soundVector.back()); + soundVector.pop_back(); } } diff --git a/indra/newview/lldeferredsounds.h b/indra/newview/lldeferredsounds.h index 50da9acf2b..bf1eb62957 100644 --- a/indra/newview/lldeferredsounds.h +++ b/indra/newview/lldeferredsounds.h @@ -29,13 +29,15 @@ #include "llsingleton.h" +struct SoundData; + class LLDeferredSounds : public LLSingleton<LLDeferredSounds> { private: - std::queue<LLUUID> soundQueue; + std::vector<SoundData> soundVector; public: //Add sounds to be played once progress bar is hidden (such as after teleport or loading screen) - void deferSound(LLUUID sound); + void deferSound(SoundData& sound); void playdeferredSounds(); }; -- cgit v1.2.3 From e179add865fef30f6ad86ffd074f267fd01cb41d Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 29 Jan 2013 11:02:23 -0800 Subject: CHUI-667: Attempting to correct Mac/Linux build issue. --- indra/newview/llappviewer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index d09c835e41..2fd9dd0dce 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -460,7 +460,8 @@ static void ui_audio_callback(const LLUUID& uuid) { if (gAudiop) { - gAudiop->triggerSound(SoundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI)); + SoundData soundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI); + gAudiop->triggerSound(soundData); } } @@ -469,7 +470,8 @@ static void deferred_ui_audio_callback(const LLUUID& uuid) { if (gAudiop) { - LLDeferredSounds::instance().deferSound(SoundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI)); + SoundData soundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI); + LLDeferredSounds::instance().deferSound(soundData); } } -- cgit v1.2.3 From edb5be4ec0a88931933a27dc7e94d45ea249591d Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 29 Jan 2013 14:41:37 -0800 Subject: CHUI-88 I shouldn't see Conference IMs from people I muted. Fix: In order to mute a user who initiated a conference/group chat, the session must be created on the server side and then left. --- indra/newview/llimview.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 8f010850f7..3a5743f309 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -3454,12 +3454,10 @@ public: (time_t) message_params["timestamp"].asInteger(); BOOL is_do_not_disturb = gAgent.isDoNotDisturb(); - BOOL is_muted = LLMuteList::getInstance()->isMuted( - from_id, - name, - LLMute::flagTextChat); - if (is_do_not_disturb || is_muted) + //don't return if user is muted b/c proper way to ignore a muted user who + //initiated an adhoc/group conference is to create then leave the session (see STORM-1731) + if (is_do_not_disturb) { return; } -- cgit v1.2.3 From df84e3c1876c5d2b321f0a8596e7e2a936073156 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 29 Jan 2013 17:47:34 -0800 Subject: CHUI-436 : Fixed : Do not skip yourself or group chat when checked Only friends and groups can call or IM me pref. --- indra/newview/llimview.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 8f010850f7..4a1b15f82b 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2610,8 +2610,15 @@ void LLIMMgr::addMessage( } } - bool skip_message = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && - LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); + bool skip_message = false; + if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly")) + { + // Evaluate if we need to skip this message when that setting is true (default is false) + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); + skip_message = (LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); // Skip non friends... + skip_message &= !session->isGroupSessionType(); // Do not skip group chats... + skip_message &= !(other_participant_id == gAgentID); // You are your best friend... Don't skip yourself + } if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !skip_message) { -- cgit v1.2.3 From 4f0237007a3a21cc502a1a15b0530bceaf5217db Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Wed, 30 Jan 2013 02:54:59 +0000 Subject: CHUI-647 FIX "Conversations" floater is not opened when user wants to share something via "Conversation log" floater Added call to show conversations floater in LLAvatarActions::share --- indra/newview/llavataractions.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 83b2888ca8..d6e457887b 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -443,6 +443,7 @@ void LLAvatarActions::share(const LLUUID& id) { LLSD key; LLFloaterSidePanelContainer::showPanel("inventory", key); + LLFloaterReg::showInstance("im_container"); LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL,id); -- cgit v1.2.3 From b96f04a1bb0577d42059246d15c244702ff02f88 Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Wed, 30 Jan 2013 08:16:47 +0200 Subject: CHUI-704 (Entry in 'Conversation Log' floater with your avatar's name appears, after ejecting any member from group) --- indra/newview/llconversationlog.cpp | 2 +- indra/newview/llimview.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index ff1f819d7d..65374b67f8 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -237,7 +237,7 @@ void LLConversationLog::logConversation(const LLUUID& session_id, BOOL has_offli const LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); LLConversation* conversation = findConversation(session); - if (session) + if (session) { if (conversation) { diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cb03c1d234..4c3d385d2d 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2542,6 +2542,13 @@ void LLIMMgr::addMessage( bool link_name) // If this is true, then we insert the name and link it to a profile { LLUUID other_participant_id = target_id; + + // Agent can't create session with himself + if (other_participant_id == gAgentID) + { + return; + } + LLUUID new_session_id = session_id; if (new_session_id.isNull()) { -- cgit v1.2.3 From d2a17e20ca889851406f22907df35b17f5030279 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Thu, 31 Jan 2013 03:16:25 +0200 Subject: CHUI-612 FIXED Blank conversation names showing in conversation list --- indra/newview/llconversationmodel.cpp | 29 +++++++++++++++-------------- indra/newview/llfloaterimsessiontab.cpp | 29 ++++++++++++++++------------- indra/newview/llimview.cpp | 5 +++-- 3 files changed, 34 insertions(+), 29 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 7184a70db5..bfc564f407 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -37,6 +37,8 @@ #include "llimview.h" //For LLIMModel #include "lltrans.h" +#include <boost/foreach.hpp> + // // Conversation items : common behaviors // @@ -234,15 +236,19 @@ void LLConversationItemSession::updateName(LLConversationItemParticipant* partic } uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string - if (conversation_type == CONV_SESSION_AD_HOC) + if (conversation_type == CONV_SESSION_AD_HOC || conversation_type == CONV_SESSION_1_ON_1) { // Build a string containing the participants UUIDs (minus own agent) and check if ready for display (we don't want "(waiting)" in there) // Note: we don't bind ourselves to the LLAvatarNameCache event as updateParticipantName() is called by // onAvatarNameCache() which is itself attached to the same event. - child_list_t::iterator iter = mChildren.begin(); - while (iter != mChildren.end()) + + // In the case of a P2P conversation, we need to grab the name of the other participant in the session instance itself + // as we do not create participants for such a session. + + LLFolderViewModelItem * itemp; + BOOST_FOREACH(itemp, mChildren) { - LLConversationItemParticipant* current_participant = dynamic_cast<LLConversationItemParticipant*>(*iter); + LLConversationItem* current_participant = dynamic_cast<LLConversationItem*>(itemp); // Add the avatar uuid to the list (except if it's the own agent uuid) if (current_participant->getUUID() != gAgentID) { @@ -250,18 +256,13 @@ void LLConversationItemSession::updateName(LLConversationItemParticipant* partic if (LLAvatarNameCache::get(current_participant->getUUID(), &av_name)) { temp_uuids.push_back(current_participant->getUUID()); + + if (conversation_type == CONV_SESSION_1_ON_1) + { + break; + } } } - iter++; - } - } - else if (conversation_type == CONV_SESSION_1_ON_1) - { - // In the case of a P2P conversation, we need to grab the name of the other participant in the session instance itself - // as we do not create participants for such a session. - if (gAgentID != participant->getUUID()) - { - temp_uuids.push_back(participant->getUUID()); } } diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index f52cf3b8f0..6dbcdb4474 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -498,25 +498,28 @@ void LLFloaterIMSessionTab::refreshConversation() updateSessionName(session_name); } - LLParticipantList* participant_list = getParticipantList(); - if (participant_list) + if (mSessionID.notNull()) { - LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = participant_list->getChildrenBegin(); - LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = participant_list->getChildrenEnd(); - LLIMSpeakerMgr *speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - while (current_participant_model != end_participant_model) + LLParticipantList* participant_list = getParticipantList(); + if (participant_list) { - LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); - if (speaker_mgr && participant_model) + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = participant_list->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = participant_list->getChildrenEnd(); + LLIMSpeakerMgr *speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + while (current_participant_model != end_participant_model) { - LLSpeaker *participant_speaker = speaker_mgr->findSpeaker(participant_model->getUUID()); - LLSpeaker *agent_speaker = speaker_mgr->findSpeaker(gAgentID); - if (participant_speaker && agent_speaker) + LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); + if (speaker_mgr && participant_model) { - participant_model->setDisplayModeratorRole(agent_speaker->mIsModerator && participant_speaker->mIsModerator); + LLSpeaker *participant_speaker = speaker_mgr->findSpeaker(participant_model->getUUID()); + LLSpeaker *agent_speaker = speaker_mgr->findSpeaker(gAgentID); + if (participant_speaker && agent_speaker) + { + participant_model->setDisplayModeratorRole(agent_speaker->mIsModerator && participant_speaker->mIsModerator); + } } + current_participant_model++; } - current_participant_model++; } } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 5dd5704916..aaddcacbb5 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -847,8 +847,9 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, bool voice, bool has_offline_msg) { - uuid_vec_t no_ids; - return newSession(session_id, name, type, other_participant_id, no_ids, voice, has_offline_msg); + uuid_vec_t ids; + ids.push_back(other_participant_id); + return newSession(session_id, name, type, other_participant_id, ids, voice, has_offline_msg); } bool LLIMModel::clearSession(const LLUUID& session_id) -- cgit v1.2.3 From a12200b91b0ca20dfff2df8aa71c6f53ac0603ee Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Thu, 31 Jan 2013 10:04:15 +0200 Subject: CHUI-718 (User does not see own chat in conference IM) CHUI-704 (Entry in 'Conversation Log' floater with your avatar's name appears, after ejecting any member from group) --- indra/newview/llconversationlog.cpp | 2 +- indra/newview/llimview.cpp | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 772753e7d1..fb654985e5 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -229,7 +229,7 @@ void LLConversationLog::logConversation(const LLUUID& session_id, BOOL has_offli const LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); LLConversation* conversation = findConversation(session); - if (session) + if (session && session->mOtherParticipantID != gAgentID) { if (conversation) { diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 5dd5704916..3f9fb02368 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2545,12 +2545,6 @@ void LLIMMgr::addMessage( { LLUUID other_participant_id = target_id; - // Agent can't create session with himself - if (other_participant_id == gAgentID) - { - return; - } - LLUUID new_session_id = session_id; if (new_session_id.isNull()) { -- cgit v1.2.3 From 0aa68e46fb67db3c90ac3d193bfa99509dca8100 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Thu, 31 Jan 2013 14:57:09 +0200 Subject: CHUI-711 FIXED Load logs from file only once to avoid duplicating. This will also solve problem with chui-710. --- indra/newview/llconversationlog.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 772753e7d1..c68a96ef5d 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -194,6 +194,7 @@ LLConversationLog::LLConversationLog() : if (log_mode > 0) { + loadFromFile(getFileName()); keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); enableLogging(log_mode); } @@ -203,8 +204,6 @@ void LLConversationLog::enableLogging(S32 log_mode) { if (log_mode > 0) { - loadFromFile(getFileName()); - LLIMMgr::instance().addSessionObserver(this); mNewMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); -- cgit v1.2.3 From 8714b610149a5ae7b6f248023722f237c9336472 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" <maxim@mnikolenko> Date: Thu, 31 Jan 2013 19:05:15 +0200 Subject: CHUI-719 FIXED Font color was changed. --- indra/newview/skins/default/xui/en/panel_preferences_chat.xml | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 4f33699aa6..9b22c8c6dd 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -46,8 +46,7 @@ layout="topleft" name="voice_call_friends_only_check" top_pad="6" - width="350"> - <check_box.label_text text_color="White" /> + width="350"> </check_box> <text @@ -79,8 +78,7 @@ <item label="Large" name="Large" - value="2"/> - <combo_box.drop_down_button label_color="White" /> + value="2"/> </combo_box> <check_box @@ -107,7 +105,6 @@ height="12" name="notifications" left="0" - text_color="White" width="120"> Notifications </text> @@ -392,14 +389,12 @@ <item label="No log or transcripts" value="0"/> - <drop_down_button label_color="White" /> </combo_box> <button enabled="false" height="23" label="Clear log..." - label_color="White" layout="topleft" left_pad="5" top="0" @@ -413,7 +408,6 @@ enabled="false" height="23" label="Delete transcripts..." - label_color="White" layout="topleft" left_pad="5" top="0" @@ -452,7 +446,6 @@ follows="left|top" height="23" label="Browse..." - label_color="White" label_selected="Browse" layout="topleft" left_pad="5" -- cgit v1.2.3 From 97930c72b6f869e9bb47cda7d9ecfccf1a25a3fa Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Fri, 1 Feb 2013 15:11:43 +0200 Subject: CHUI-715 FIXED Disable Gear button if no conversation is selected --- indra/newview/llfloaterconversationlog.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index a44ebcf6ab..07723ce44d 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -72,6 +72,7 @@ BOOL LLFloaterConversationLog::postBuild() void LLFloaterConversationLog::draw() { + getChild<LLMenuButton>("conversations_gear_btn")->setEnabled(mConversationLogList->getSelectedItem() != NULL); LLFloater::draw(); } -- cgit v1.2.3 From 56b158e486f97f26c87ac37923f5dfbc2cc7548a Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Fri, 1 Feb 2013 18:54:15 +0000 Subject: CHUI-675 FIX You can select multiple users in people floater but can only drag and drop one name to conversation Moved drag and drop start in LLAvatarListItem instead of LLAvatarList, and made LLFloaterIMSession handle multiple dropped participants correctly --- indra/newview/llavatarlist.cpp | 52 ++++++++++++++++++++++++++++++++++ indra/newview/llavatarlist.h | 3 ++ indra/newview/llavatarlistitem.cpp | 55 ------------------------------------ indra/newview/llavatarlistitem.h | 3 -- indra/newview/llfloaterimsession.cpp | 17 ++++++++++- indra/newview/llfloaterimsession.h | 15 +++++----- 6 files changed, 79 insertions(+), 66 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index e54e47180f..9f02f301a1 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -46,6 +46,7 @@ #include "lluuid.h" #include "llvoiceclient.h" #include "llviewercontrol.h" // for gSavedSettings +#include "lltooldraganddrop.h" static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list"); @@ -462,6 +463,57 @@ BOOL LLAvatarList::handleRightMouseDown(S32 x, S32 y, MASK mask) return handled; } +BOOL LLAvatarList::handleMouseDown(S32 x, S32 y, MASK mask) +{ + gFocusMgr.setMouseCapture(this); + + S32 screen_x; + S32 screen_y; + localPointToScreen(x, y, &screen_x, &screen_y); + LLToolDragAndDrop::getInstance()->setDragStart(screen_x, screen_y); + + return LLFlatListViewEx::handleMouseDown(x, y, mask); +} + +BOOL LLAvatarList::handleMouseUp( S32 x, S32 y, MASK mask ) +{ + if(hasMouseCapture()) + { + gFocusMgr.setMouseCapture(NULL); + } + + return LLFlatListViewEx::handleMouseUp(x, y, mask); +} + +BOOL LLAvatarList::handleHover(S32 x, S32 y, MASK mask) +{ + bool handled = hasMouseCapture(); + if(handled) + { + S32 screen_x; + S32 screen_y; + localPointToScreen(x, y, &screen_x, &screen_y); + + if(LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y)) + { + // First, create the global drag and drop object + std::vector<EDragAndDropType> types; + uuid_vec_t cargo_ids; + getSelectedUUIDs(cargo_ids); + types.resize(cargo_ids.size(), DAD_PERSON); + LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_PEOPLE; + LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, src); + } + } + + if(!handled) + { + handled = LLFlatListViewEx::handleHover(x, y, mask); + } + + return handled; +} + bool LLAvatarList::isAvalineItemSelected() { std::vector<LLPanel*> selected_items; diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index 4814a88a79..3542577ae3 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -84,6 +84,9 @@ public: bool getIconsVisible() const { return mShowIcons; } const std::string getIconParamName() const{return mIconParamName;} virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); // Return true if filter has at least one match. bool filterHasMatches(); diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 3ed0c7c482..3e6c817dd6 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -368,61 +368,6 @@ BOOL LLAvatarListItem::handleDoubleClick(S32 x, S32 y, MASK mask) return LLPanel::handleDoubleClick(x, y, mask); } -BOOL LLAvatarListItem::handleMouseDown(S32 x, S32 y, MASK mask) -{ - if (LLUICtrl::handleMouseDown(x, y, mask)) - { - return TRUE; - } - - gFocusMgr.setMouseCapture(this); - - S32 screen_x; - S32 screen_y; - localPointToScreen(x, y, &screen_x, &screen_y); - LLToolDragAndDrop::getInstance()->setDragStart(screen_x, screen_y); - - return TRUE; -} - -BOOL LLAvatarListItem::handleMouseUp( S32 x, S32 y, MASK mask ) -{ - if (LLUICtrl::childrenHandleMouseUp(x, y, mask)) - { - return TRUE; - } - - if(hasMouseCapture()) - { - gFocusMgr.setMouseCapture(NULL); - } - return TRUE; -} - -BOOL LLAvatarListItem::handleHover(S32 x, S32 y, MASK mask) -{ - bool handled = hasMouseCapture(); - if(handled) - { - S32 screen_x; - S32 screen_y; - localPointToScreen(x, y, &screen_x, &screen_y); - - if(LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y)) - { - // First, create the global drag and drop object - std::vector<EDragAndDropType> types; - uuid_vec_t cargo_ids; - types.push_back(DAD_PERSON); - cargo_ids.push_back(mAvatarId); - LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_PEOPLE; - LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, src); - } - } - - return handled; -} - void LLAvatarListItem::setValue( const LLSD& value ) { if (!value.isMap()) return;; diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 96aed20016..7ef35a746e 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -115,9 +115,6 @@ public: void onProfileBtnClick(); /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); protected: /** diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index f754853b82..50b2ed8c51 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -1043,6 +1043,19 @@ void LLFloaterIMSession::processSessionUpdate(const LLSD& session_update) } } +// virtual +void LLFloaterIMSession::draw() +{ + // add people who were added via dropPerson() + if (!mPendingParticipants.empty()) + { + addSessionParticipants(mPendingParticipants); + mPendingParticipants.clear(); + } + + LLFloaterIMSessionTab::draw(); +} + // virtual BOOL LLFloaterIMSession::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, @@ -1081,7 +1094,9 @@ bool LLFloaterIMSession::dropPerson(LLUUID* person_id, bool drop) res = canAddSelectedToChat(ids); if(res && drop) { - addSessionParticipants(ids); + // these people will be added during the next draw() call + // (so they can be added all at once) + mPendingParticipants.push_back(*person_id); } } diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index e7fd6f9ff3..381b3cf721 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -69,6 +69,13 @@ public: /*virtual*/ BOOL getVisible(); // Check typing timeout timer. + /*virtual*/ void draw(); + /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + static LLFloaterIMSession* findInstance(const LLUUID& session_id); static LLFloaterIMSession* getInstance(const LLUUID& session_id); @@ -117,13 +124,6 @@ public: void processAgentListUpdates(const LLSD& body); void processSessionUpdate(const LLSD& session_update); - /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - - //used as a callback on receiving new IM message static void sRemoveTypingIndicator(const LLSD& data); static void onIMChicletCreated(const LLUUID& session_id); @@ -189,6 +189,7 @@ private: LLSD mQueuedMsgsForInit; uuid_vec_t mInvitedParticipants; + uuid_vec_t mPendingParticipants; // connection to voice channel state change signal boost::signals2::connection mVoiceChannelStateChangeConnection; -- cgit v1.2.3 From dde030e6cd8816bb7f99e0358a8c83eaccf1f8b9 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 1 Feb 2013 11:18:23 -0800 Subject: CHUI-689: When DND mode is enabled, making a direct delivery purchase results in an IM message from '(Nobody)'. Solution: Fixed a problem in process_improved_im that would falsy use system messages while in DND mode as an IM from a user. Also made it so that while in DND mode, SystemMessages and message with a high or greater priority are shown to the user as toasts (before a notification chiclet would just appear without the toast). --- indra/newview/llnotificationscripthandler.cpp | 5 +++++ indra/newview/llviewermessage.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index e2d4e9f8ce..19dd6d4ca0 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" // must be first include +#include "llagent.h" #include "llnotificationhandler.h" #include "lltoastnotifypanel.h" #include "llviewercontrol.h" @@ -95,6 +96,10 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) p.notification = notification; p.panel = notify_box; p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); + if(gAgent.isDoNotDisturb()) + { + p.force_show = notification->getName() == "SystemMessage" || notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; + } LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index caafb10e25..359819ec49 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2391,7 +2391,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // do nothing -- don't distract newbies in // Prelude with global IMs } - else if (offline == IM_ONLINE && is_do_not_disturb && name != SYSTEM_FROM) + else if (offline == IM_ONLINE && is_do_not_disturb && from_id.notNull()) { // return a standard "do not disturb" message, but only do it to online IM // (i.e. not other auto responses and not store-and-forward IM) -- cgit v1.2.3 From 1192abd7eb0dff000be69f21d4d7cc7e0ecef561 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Fri, 1 Feb 2013 21:55:03 +0000 Subject: CHUI-720 FIX User can open "Add friend" by pressing on a line in context menu for user that already is friend Added check for getVisible() and getEnabled() before passing along handleMouseDown() and handleMouseUp() callbacks to other menu items in LLMenuItemSeparatorGL --- indra/llui/llmenugl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index b7148bb91b..f7bf39c897 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -593,12 +593,12 @@ BOOL LLMenuItemSeparatorGL::handleMouseDown(S32 x, S32 y, MASK mask) { // the menu items are in the child list in bottom up order LLView* prev_menu_item = parent_menu->findNextSibling(this); - return prev_menu_item ? prev_menu_item->handleMouseDown(x, prev_menu_item->getRect().getHeight(), mask) : FALSE; + return (prev_menu_item && prev_menu_item->getVisible() && prev_menu_item->getEnabled()) ? prev_menu_item->handleMouseDown(x, prev_menu_item->getRect().getHeight(), mask) : FALSE; } else { LLView* next_menu_item = parent_menu->findPrevSibling(this); - return next_menu_item ? next_menu_item->handleMouseDown(x, 0, mask) : FALSE; + return (next_menu_item && next_menu_item->getVisible() && next_menu_item->getEnabled()) ? next_menu_item->handleMouseDown(x, 0, mask) : FALSE; } } @@ -608,12 +608,12 @@ BOOL LLMenuItemSeparatorGL::handleMouseUp(S32 x, S32 y, MASK mask) if (y > getRect().getHeight() / 2) { LLView* prev_menu_item = parent_menu->findNextSibling(this); - return prev_menu_item ? prev_menu_item->handleMouseUp(x, prev_menu_item->getRect().getHeight(), mask) : FALSE; + return (prev_menu_item && prev_menu_item->getVisible() && prev_menu_item->getEnabled()) ? prev_menu_item->handleMouseUp(x, prev_menu_item->getRect().getHeight(), mask) : FALSE; } else { LLView* next_menu_item = parent_menu->findPrevSibling(this); - return next_menu_item ? next_menu_item->handleMouseUp(x, 0, mask) : FALSE; + return (next_menu_item && next_menu_item->getVisible() && next_menu_item->getEnabled()) ? next_menu_item->handleMouseUp(x, 0, mask) : FALSE; } } -- cgit v1.2.3 From 7705b43889a6cc2c718077906c8dd778b0e877f8 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 1 Feb 2013 18:04:33 -0800 Subject: CHUI-691: Now when an estate message is received while in DND mode, a toast notification will appear. --- indra/newview/llnotificationscripthandler.cpp | 4 +++- indra/newview/llviewermessage.cpp | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 19dd6d4ca0..08c98e4f28 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -98,7 +98,9 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); if(gAgent.isDoNotDisturb()) { - p.force_show = notification->getName() == "SystemMessage" || notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; + p.force_show = notification->getName() == "SystemMessage" + || notification->getName() == "GodMessage" + || notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; } LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 359819ec49..6bbfd30794 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2371,7 +2371,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LLNotification::Params params; switch(dialog) - { + { case IM_CONSOLE_AND_CHAT_HISTORY: args["MESSAGE"] = message; payload["from_id"] = from_id; @@ -2391,7 +2391,10 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // do nothing -- don't distract newbies in // Prelude with global IMs } - else if (offline == IM_ONLINE && is_do_not_disturb && from_id.notNull()) + else if (offline == IM_ONLINE + && is_do_not_disturb + && from_id.notNull() //not a system message + && to_id.notNull()) //not global message { // return a standard "do not disturb" message, but only do it to online IM // (i.e. not other auto responses and not store-and-forward IM) -- cgit v1.2.3 From 2f6ffe2183250f3f71a8d502eed9cf9df9ff8b16 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Mon, 4 Feb 2013 14:37:29 +0200 Subject: CHUI-721 FIXED Delete transcripts when performing Clear log action. --- indra/newview/llconversationlog.cpp | 7 +++++++ indra/newview/llconversationlog.h | 1 + indra/newview/llfloaterpreference.cpp | 16 ++++++---------- 3 files changed, 14 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 7bd6ef8cd7..bfaffdd73b 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -531,7 +531,14 @@ void LLConversationLog::onClearLogResponse(const LLSD& notification, const LLSD& { if (0 == LLNotificationsUtil::getSelectedOption(notification, response)) { + deleteTranscripts(); mConversations.clear(); notifyObservers(); } } + +void LLConversationLog::deleteTranscripts() +{ + gDirUtilp->deleteFilesInDir(gDirUtilp->getPerAccountChatLogsDir(), "*." + LL_TRANSCRIPT_FILE_EXTENSION); + LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); +} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 65a18c02e5..88df17a8f7 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -140,6 +140,7 @@ public: void onClearLog(); void onClearLogResponse(const LLSD& notification, const LLSD& response); + void deleteTranscripts(); private: diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 7742e5b3c3..4f86c26a67 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -460,9 +460,6 @@ BOOL LLFloaterPreference::postBuild() // set 'enable' property for 'Clear log...' button changed(); - // set 'enable' property for 'Delete transcripts...' button - updateDeleteTranscriptsButton(); - LLLogChat::setSaveHistorySignal(boost::bind(&LLFloaterPreference::onLogChatHistorySaved, this)); return TRUE; @@ -1587,13 +1584,8 @@ void LLFloaterPreference::onDeleteTranscriptsResponse(const LLSD& notification, { if (0 == LLNotificationsUtil::getSelectedOption(notification, response)) { - gDirUtilp->deleteFilesInDir(gDirUtilp->getPerAccountChatLogsDir(), "*." + LL_TRANSCRIPT_FILE_EXTENSION); - - std::vector<std::string> list_of_transcriptions_file_names; - LLLogChat::getListOfTranscriptFiles(list_of_transcriptions_file_names); - getChild<LLButton>("delete_transcripts")->setEnabled(list_of_transcriptions_file_names.size() > 0); - - LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); + LLConversationLog::instance().deleteTranscripts(); + updateDeleteTranscriptsButton(); } } @@ -1668,6 +1660,10 @@ void LLFloaterPreference::selectChatPanel() void LLFloaterPreference::changed() { getChild<LLButton>("clear_log")->setEnabled(LLConversationLog::instance().getConversations().size() > 0); + + // set 'enable' property for 'Delete transcripts...' button + updateDeleteTranscriptsButton(); + } //------------------------------Updater--------------------------------------- -- cgit v1.2.3 From 85f7f43069ea7ea47b4461fa1d7700339985ab35 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Mon, 4 Feb 2013 19:11:17 +0200 Subject: CHUI-695 FIXED Viewer crashes after attempt to accept a friendship in IM --- indra/newview/lltoastnotifypanel.cpp | 142 ++------------------- indra/newview/lltoastpanel.cpp | 4 +- .../skins/default/xui/en/panel_notification.xml | 2 +- 3 files changed, 14 insertions(+), 134 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 0aab514531..bd6c42d474 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -223,104 +223,6 @@ void LLToastNotifyPanel::adjustPanelForTipNotice() } } -//typedef std::set<std::string> button_name_set_t; -//typedef std::map<std::string, button_name_set_t> disable_button_map_t; -// -//disable_button_map_t initUserGiveItemDisableButtonMap() -//{ -// // see EXT-5905 for disable rules -// -// disable_button_map_t disable_map; -// button_name_set_t buttons; -// -// buttons.insert("Show"); -// disable_map.insert(std::make_pair("Show", buttons)); -// -// buttons.insert("Discard"); -// disable_map.insert(std::make_pair("Discard", buttons)); -// -// buttons.insert("Mute"); -// disable_map.insert(std::make_pair("Mute", buttons)); -// -// return disable_map; -//} -// -//disable_button_map_t initTeleportOfferedDisableButtonMap() -//{ -// disable_button_map_t disable_map; -// button_name_set_t buttons; -// -// buttons.insert("Teleport"); -// buttons.insert("Cancel"); -// -// disable_map.insert(std::make_pair("Teleport", buttons)); -// disable_map.insert(std::make_pair("Cancel", buttons)); -// -// return disable_map; -//} -// -//disable_button_map_t initFriendshipOfferedDisableButtonMap() -//{ -// disable_button_map_t disable_map; -// button_name_set_t buttons; -// -// buttons.insert("Accept"); -// buttons.insert("Decline"); -// -// disable_map.insert(std::make_pair("Accept", buttons)); -// disable_map.insert(std::make_pair("Decline", buttons)); -// -// return disable_map; -//} -// -//button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) -//{ -// static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); -// static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); -// static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); -// -// disable_button_map_t::const_iterator it; -// disable_button_map_t::const_iterator it_end; -// disable_button_map_t search_map; -// -// if("UserGiveItem" == notification_name) -// { -// search_map = user_give_item_disable_map; -// } -// else if("TeleportOffered" == notification_name) -// { -// search_map = teleport_offered_disable_map; -// } -// else if("OfferFriendship" == notification_name) -// { -// search_map = friendship_offered_disable_map; -// } -// -// it = search_map.find(button_name); -// it_end = search_map.end(); -// -// if(it_end != it) -// { -// return it->second; -// } -// return button_name_set_t(); -//} - -//void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) -//{ - //button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); - - //std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); - //for ( ; it != mButtons.end(); it++) - //{ - // LLButton* btn = it->second; - // if(buttons.find(btn->getName()) != buttons.end()) - // { - // btn->setEnabled(FALSE); - // } - //} -//} - // static void LLToastNotifyPanel::onClickButton(void* data) { @@ -352,7 +254,17 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) mNumButtons = 0; mAddedDefaultBtn = false; - buildFromFile( "panel_notification.xml"); + LLRect current_rect = getRect(); + + setXMLFilename(""); + buildFromFile("panel_notification.xml"); + + // reshape the panel to its previous size + if (current_rect.notEmpty()) + { + reshape(current_rect.getWidth(), current_rect.getHeight()); + } + if(rect != LLRect::null) { this->setShape(rect); @@ -491,37 +403,9 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) } } - // adjust panel's height to the text size - mInfoPanel->setFollowsAll(); snapToMessageHeight(mTextBox, MAX_LENGTH); } - - -//void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) -//{ -// if(mNotification->getID() == notification_id) -// { -// disableButtons(mNotification->getName(), btn_name); -// } -//} - -//void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) -//{ -// LLSD response = notification->getResponse(); -// for (LLSD::map_const_iterator response_it = response.beginMap(); -// response_it != response.endMap(); ++response_it) -// { -// if (response_it->second.isBoolean() && response_it->second.asBoolean()) -// { -// // that after multiple responses there can be many pressed buttons -// // need to process them all -// disableButtons(notification->getName(), response_it->first); -// } -// } -//} - - ////////////////////////////////////////////////////////////////////////// LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect /* = LLRect::null */, @@ -538,13 +422,12 @@ LLIMToastNotifyPanel::~LLIMToastNotifyPanel() void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) { + LLToastPanel::reshape(width, height, called_from_parent); snapToMessageHeight(mTextBox, MAX_LENGTH); } void LLIMToastNotifyPanel::compactButtons() { - mTextBox->setFollowsAll(); - //we can't set follows in xml since it broke toasts behavior setFollows(FOLLOWS_LEFT|FOLLOWS_RIGHT|FOLLOWS_TOP); @@ -590,6 +473,5 @@ void LLIMToastNotifyPanel::init( LLRect rect, bool show_images ) compactButtons(); } - // EOF diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index 54d3912136..187aee207c 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -81,9 +81,7 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount) S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); heightDelta = newTextHeight - oldTextHeight; - S32 new_panel_height = llmin( - llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT), - maxTextHeight); + S32 new_panel_height = llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT); //reshape the panel with new height if (new_panel_height != getRect().getHeight()) diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml index 94c468e1bb..421ecf10a1 100644 --- a/indra/newview/skins/default/xui/en/panel_notification.xml +++ b/indra/newview/skins/default/xui/en/panel_notification.xml @@ -22,7 +22,7 @@ background_visible="true" bg_alpha_color="ToastBackground" bg_opaque_color="ToastBackground" - follows="left|right|top" + follows="all" height="100" label="info_panel" layout="topleft" -- cgit v1.2.3 From 3e73b107d37e293b4e4cde91734e1e8251ba6b72 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 4 Feb 2013 14:41:58 -0800 Subject: CHUI-677 : Added a warning printout in the log to capture context of this bug. --- indra/newview/llimview.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 5acb0b6374..1cceb68e2a 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -1591,6 +1591,11 @@ LLUUID LLIMMgr::computeSessionID( session_id = other_participant_id ^ agent_id; } } + + if (gAgent.isInGroup(session_id) && (session_id != other_participant_id)) + { + llwarns << "Group session id different from group id: IM type = " << dialog << ", session id = " << session_id << ", group id = " << other_participant_id << llendl; + } return session_id; } -- cgit v1.2.3 From 6a68f16f2e908838b89216543b36f07e2a71c360 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 4 Feb 2013 19:29:05 -0800 Subject: CHUI-732 : Fixed! Do not iterate through selection while modufying it at the same time, use a temp set. --- indra/llui/llfolderview.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 7c1ca017d7..c756ff84e1 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -924,23 +924,27 @@ void LLFolderView::cut() { // clear the inventory clipboard LLClipboard::instance().reset(); - S32 count = mSelectedItems.size(); - if(getVisible() && getEnabled() && (count > 0)) + if(getVisible() && getEnabled() && (mSelectedItems.size() > 0)) { + // Find out which item will be selected once the selection will be cut LLFolderViewItem* item_to_select = getNextUnselectedItem(); + + // Get the selection: removeItem() modified mSelectedItems and makes iterating on it unwise + std::set<LLFolderViewItem*> inventory_selected = getSelectionList(); - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + // Move each item to the clipboard and out of their folder + for (std::set<LLFolderViewItem*>::iterator item_it = inventory_selected.begin(); item_it != inventory_selected.end(); ++item_it) { LLFolderViewItem* item_to_cut = *item_it; LLFolderViewModelItem* listener = item_to_cut->getViewModelItem(); - if(listener) + if (listener) { listener->cutToClipboard(); listener->removeItem(); } } - + + // Update the selection setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel->hasFocus()); } mSearchString.clear(); -- cgit v1.2.3 From 2aee8f6fbe2be3196300dd1ee6e31039de089207 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 5 Feb 2013 21:11:33 -0800 Subject: CHUI-730 : Fixed! Only clear out More sub menus in inventory --- indra/newview/llinventorybridge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 5bfd63f3df..0ee78d57bd 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -571,7 +571,7 @@ void hide_context_entries(LLMenuGL& menu, // descend into split menus: LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(menu_item); - if (NULL != branchp) + if ((name == "More") && branchp) { hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries); } -- cgit v1.2.3 From 5b143ee2c70dab6a50c51da68d6b4c97196e2aed Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 5 Feb 2013 22:26:58 -0800 Subject: CHUI-677 : Fixed! Use the selected session for doToSelectedGroup(), not the selected item. --- indra/newview/llfloaterimcontainer.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 54e5085490..5a284cc7b7 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1118,19 +1118,18 @@ void LLFloaterIMContainer::doToSelected(const LLSD& userdata) void LLFloaterIMContainer::doToSelectedGroup(const LLSD& userdata) { std::string action = userdata.asString(); - LLUUID selected_group = getCurSelectedViewModelItem()->getUUID(); if (action == "group_profile") { - LLGroupActions::show(selected_group); + LLGroupActions::show(mSelectedSession); } else if (action == "activate_group") { - LLGroupActions::activate(selected_group); + LLGroupActions::activate(mSelectedSession); } else if (action == "leave_group") { - LLGroupActions::leave(selected_group); + LLGroupActions::leave(mSelectedSession); } } -- cgit v1.2.3 From 3781615afa6db7289f26f404885ac614c7f1cee0 Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Wed, 6 Feb 2013 10:03:42 +0200 Subject: CHUI-597 (Messages shown in Conversation Log are inaccurate) Added messages, for now they're displayed in two cases: 1) no log entries, logging disabled 2) no log entries, logging enabled Case when there are existing log entries and logging is disabled is still under discussion --- indra/newview/llconversationlog.cpp | 5 +++-- indra/newview/llconversationlog.h | 5 +++++ indra/newview/llconversationloglist.cpp | 24 +++++++++++++++++++++- indra/newview/llfloaterconversationlog.cpp | 9 -------- indra/newview/llfloaterconversationlog.h | 2 -- .../default/xui/en/floater_conversation_log.xml | 3 --- indra/newview/skins/default/xui/en/strings.xml | 11 ++++++++++ 7 files changed, 42 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 7bd6ef8cd7..5f037549ab 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -187,7 +187,8 @@ void LLConversationLogFriendObserver::changed(U32 mask) /************************************************************************/ LLConversationLog::LLConversationLog() : - mAvatarNameCacheConnection() + mAvatarNameCacheConnection(), + mLoggingEnabled(false) { LLControlVariable * keep_log_ctrlp = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); S32 log_mode = keep_log_ctrlp->getValue(); @@ -202,6 +203,7 @@ LLConversationLog::LLConversationLog() : void LLConversationLog::enableLogging(S32 log_mode) { + mLoggingEnabled = log_mode > 0; if (log_mode > 0) { LLIMMgr::instance().addSessionObserver(this); @@ -217,7 +219,6 @@ void LLConversationLog::enableLogging(S32 log_mode) LLIMMgr::instance().removeSessionObserver(this); mNewMessageSignalConnection.disconnect(); LLAvatarTracker::instance().removeObserver(mFriendObserver); - mConversations.clear(); } notifyObservers(); diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 65a18c02e5..d5b6eccb29 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -141,6 +141,9 @@ public: void onClearLog(); void onClearLogResponse(const LLSD& notification, const LLSD& response); + bool getIsLoggingEnabled() { return mLoggingEnabled; } + bool isLogEmpty() { return mConversations.empty(); } + private: LLConversationLog(); @@ -187,6 +190,8 @@ private: boost::signals2::connection mNewMessageSignalConnection; boost::signals2::connection mAvatarNameCacheConnection; + + bool mLoggingEnabled; }; class LLConversationLogObserver diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 6dbcb7bef7..96b225b841 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -33,6 +33,7 @@ #include "llconversationloglist.h" #include "llconversationloglistitem.h" #include "llviewermenu.h" +#include "lltrans.h" static LLDefaultChildRegistry::Register<LLConversationLogList> r("conversation_log_list"); @@ -200,8 +201,9 @@ void LLConversationLogList::rebuildList() clear(); bool have_filter = !mNameFilter.empty(); + LLConversationLog &log_instance = LLConversationLog::instance(); - const std::vector<LLConversation>& conversations = LLConversationLog::instance().getConversations(); + const std::vector<LLConversation>& conversations = log_instance.getConversations(); std::vector<LLConversation>::const_iterator iter = conversations.begin(); for (; iter != conversations.end(); ++iter) @@ -212,6 +214,26 @@ void LLConversationLogList::rebuildList() addNewItem(&*iter); } + + + bool logging_enabled = log_instance.getIsLoggingEnabled(); + bool log_empty = log_instance.isLogEmpty(); + if (!logging_enabled && log_empty) + { + setNoItemsCommentText(LLTrans::getString("logging_calls_disabled_log_empty")); + } + else if (!logging_enabled && !log_empty) + { + setNoItemsCommentText(LLTrans::getString("logging_calls_disabled_log_not_empty")); + } + else if (logging_enabled && log_empty) + { + setNoItemsCommentText(LLTrans::getString("logging_calls_enabled_log_empty")); + } + else if (logging_enabled && !log_empty) + { + setNoItemsCommentText(""); + } } void LLConversationLogList::onCustomAction(const LLSD& userdata) diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index 07723ce44d..4c910c5655 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -63,10 +63,6 @@ BOOL LLFloaterConversationLog::postBuild() getChild<LLFilterEditor>("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); - LLControlVariable * keep_log_ctrlp = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); - keep_log_ctrlp->getSignal()->connect(boost::bind(&LLFloaterConversationLog::onCallLoggingEnabledDisabled, this, _2)); - onCallLoggingEnabledDisabled(keep_log_ctrlp->getValue()); - return LLFloater::postBuild(); } @@ -136,8 +132,3 @@ bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) return false; } -void LLFloaterConversationLog::onCallLoggingEnabledDisabled(S32 log_mode) -{ - std::string no_items_msg = log_mode > 0 ? "" : getString("logging_calls_disabled"); - mConversationLogList->setNoItemsCommentText(no_items_msg); -} diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h index aa0f480aae..e971330f3d 100644 --- a/indra/newview/llfloaterconversationlog.h +++ b/indra/newview/llfloaterconversationlog.h @@ -49,8 +49,6 @@ private: bool isActionEnabled(const LLSD& userdata); bool isActionChecked(const LLSD& userdata); - void onCallLoggingEnabledDisabled(S32 log_mode); - LLConversationLogList* mConversationLogList; }; diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml index 256e03c4d7..7229292a14 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -13,9 +13,6 @@ reuse_instance="true" title="CONVERSATION LOG" width="300"> - <string name="logging_calls_disabled"> - Conversations are not being logged. To log conversations in the future, select "Save IM logs on my computer" under Preferences > Privacy. - </string> <panel follows="left|top|right" height="32" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index d6a2383e52..5aa743b32d 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3908,4 +3908,15 @@ Try enclosing path to the editor with double quotes. <!-- Spell check settings floater --> <string name="UserDictionary">[User]</string> + <!-- Conversation log messages --> + <string name="logging_calls_disabled_log_empty"> + Conversations are not being logged. To begin keeping a log, choose "Save: Log only" or "Save: Log and transcripts" under Preferences > Chat. + </string> + <string name="logging_calls_disabled_log_not_empty"> + No more conversations will be logged. To resume keeping a log, choose "Save: Log only" or "Save: Log and transcripts" under Preferences > Chat. + </string> + <string name="logging_calls_enabled_log_empty"> + There are no logged conversations. After you contact someone, or someone contacts you, a log entry will be shown here. + </string> + </strings> -- cgit v1.2.3 From 418b0334f2ee92ce8b8958218c8d6db5ccc855f2 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Wed, 6 Feb 2013 15:06:27 +0200 Subject: CHUI-716 FIXED Call onClickCloseBtn() to avoid complete disappearing of torn off Nearby chat. --- indra/newview/llfloaterimnearbychat.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index a2dd93e10d..345418bffc 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -260,6 +260,7 @@ void LLFloaterIMNearbyChat::onOpen(const LLSD& key) void LLFloaterIMNearbyChat::onClose(bool app_quitting) { // Override LLFloaterIMSessionTab::onClose() so that Nearby Chat is not removed from the conversation floater + onClickCloseBtn(); } // virtual -- cgit v1.2.3 From 302f57e47fdab9e043a72e6a83f0f2b1992f2a99 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Wed, 6 Feb 2013 20:17:35 +0200 Subject: CHUI-744 FIXED KeepConversationLogTranscripts setting is moved to settings_per_account.xml --- indra/newview/app_settings/settings.xml | 11 ----------- indra/newview/app_settings/settings_per_account.xml | 11 +++++++++++ indra/newview/llconversationlog.cpp | 4 ++-- indra/newview/llfloaterimcontainer.cpp | 4 ++-- indra/newview/llfloaterimnearbychat.cpp | 2 +- indra/newview/llimview.cpp | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index fb4cc6de62..79376f7467 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4667,17 +4667,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>KeepConversationLogTranscripts</key> - <map> - <key>Comment</key> - <string>Keep a conversation log and transcripts</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>2</integer> - </map> <key>LandBrushSize</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 6864328339..0b589e2da6 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -281,6 +281,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>KeepConversationLogTranscripts</key> + <map> + <key>Comment</key> + <string>Keep a conversation log and transcripts</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>2</integer> + </map> <key>ShowFavoritesOnLogin</key> <map> <key>Comment</key> diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 04abda1799..c5be2f59be 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -190,7 +190,7 @@ LLConversationLog::LLConversationLog() : mAvatarNameCacheConnection(), mLoggingEnabled(false) { - LLControlVariable * keep_log_ctrlp = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); + LLControlVariable * keep_log_ctrlp = gSavedPerAccountSettings.getControl("KeepConversationLogTranscripts").get(); S32 log_mode = keep_log_ctrlp->getValue(); if (log_mode > 0) @@ -369,7 +369,7 @@ void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string void LLConversationLog::cache() { - if (gSavedSettings.getS32("KeepConversationLogTranscripts") > 0) + if (gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0) { saveToFile(getFileName()); } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 5a284cc7b7..2b13ce6377 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1141,7 +1141,7 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) if ("conversation_log" == item) { - return gSavedSettings.getS32("KeepConversationLogTranscripts") > 0; + return gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0; } //Enable Chat history item for ad-hoc and group conversations @@ -1792,7 +1792,7 @@ void LLFloaterIMContainer::updateSpeakBtnState() bool LLFloaterIMContainer::isConversationLoggingAllowed() { - return gSavedSettings.getS32("KeepConversationLogTranscripts") > 0; + return gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0; } void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes) diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 345418bffc..430326203f 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -542,7 +542,7 @@ void LLFloaterIMNearbyChat::addMessage(const LLChat& chat,bool archive,const LLS } // logging - if (!args["do_not_log"].asBoolean() && gSavedSettings.getS32("KeepConversationLogTranscripts") > 1) + if (!args["do_not_log"].asBoolean() && gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 1) { std::string from_name = chat.mFromName; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 1cceb68e2a..d4c8d8c4f4 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -928,7 +928,7 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) { - if (gSavedSettings.getS32("KeepConversationLogTranscripts") > 1) + if (gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 1) { std::string from_name = from; -- cgit v1.2.3 From f944608ab93199a5588ec2c969268b094b8be7c8 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 6 Feb 2013 20:00:43 +0200 Subject: CHUI-707: "Chat" toolbar button stop flashing after setting toolbar buttons view to "Icons only": save/restore flashing states --- indra/llui/lltoolbar.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'indra') diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 071046fe6d..b9256dd890 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -872,8 +872,15 @@ void LLToolBar::reshape(S32 width, S32 height, BOOL called_from_parent) void LLToolBar::createButtons() { + std::set<LLUUID> set_flashing; + BOOST_FOREACH(LLToolBarButton* button, mButtons) { + if (button->getFlashTimer() && button->getFlashTimer()->isFlashingInProgress()) + { + set_flashing.insert(button->getCommandId().uuid()); + } + if (mButtonRemoveSignal) { (*mButtonRemoveSignal)(button); @@ -896,6 +903,11 @@ void LLToolBar::createButtons() { (*mButtonAddSignal)(button); } + + if (set_flashing.find(button->getCommandId().uuid()) != set_flashing.end()) + { + button->setFlashing(true); + } } mNeedsLayout = true; } -- cgit v1.2.3 From ec0ac12eba9d944ade7bd734226a03ea2eb47229 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 6 Feb 2013 20:51:14 +0200 Subject: CHUI-712 FIXED IM log files renamed with ll.txt will create double files for users --- indra/newview/llconversationlog.cpp | 8 +- indra/newview/llconversationlog.h | 1 - indra/newview/llfloaterpreference.cpp | 2 +- indra/newview/lllogchat.cpp | 147 ++++++++++++++++++---------------- indra/newview/lllogchat.h | 9 +-- 5 files changed, 82 insertions(+), 85 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index c5be2f59be..82176b3a06 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -532,14 +532,8 @@ void LLConversationLog::onClearLogResponse(const LLSD& notification, const LLSD& { if (0 == LLNotificationsUtil::getSelectedOption(notification, response)) { - deleteTranscripts(); + LLLogChat::deleteTranscripts(); mConversations.clear(); notifyObservers(); } } - -void LLConversationLog::deleteTranscripts() -{ - gDirUtilp->deleteFilesInDir(gDirUtilp->getPerAccountChatLogsDir(), "*." + LL_TRANSCRIPT_FILE_EXTENSION); - LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); -} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 5213c9b3ab..d5b6eccb29 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -140,7 +140,6 @@ public: void onClearLog(); void onClearLogResponse(const LLSD& notification, const LLSD& response); - void deleteTranscripts(); bool getIsLoggingEnabled() { return mLoggingEnabled; } bool isLogEmpty() { return mConversations.empty(); } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 4f86c26a67..da24bb3b8f 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1584,7 +1584,7 @@ void LLFloaterPreference::onDeleteTranscriptsResponse(const LLSD& notification, { if (0 == LLNotificationsUtil::getSelectedOption(notification, response)) { - LLConversationLog::instance().deleteTranscripts(); + LLLogChat::deleteTranscripts(); updateDeleteTranscriptsButton(); } } diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 545b44ef92..17b72c5023 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -33,6 +33,7 @@ #include "llviewercontrol.h" #include "lldiriterator.h" +#include "llfloaterimsessiontab.h" #include "llinstantmessage.h" #include "llsingleton.h" // for LLSingleton @@ -40,6 +41,7 @@ #include <boost/algorithm/string/replace.hpp> #include <boost/regex.hpp> #include <boost/regex/v4/match_results.hpp> +#include <boost/foreach.hpp> #if LL_MSVC #pragma warning(push) @@ -62,7 +64,7 @@ const std::string LL_IM_TIME("time"); const std::string LL_IM_TEXT("message"); const std::string LL_IM_FROM("from"); const std::string LL_IM_FROM_ID("from_id"); -const std::string LL_TRANSCRIPT_FILE_EXTENSION("ll.txt"); +const std::string LL_TRANSCRIPT_FILE_EXTENSION("txt"); const static std::string IM_SEPARATOR(": "); const static std::string NEW_LINE("\n"); @@ -85,6 +87,7 @@ const static std::string MULTI_LINE_PREFIX(" "); * Note: "You" was used as an avatar names in viewers of previous versions */ const static boost::regex TIMESTAMP_AND_STUFF("^(\\[\\d{4}/\\d{1,2}/\\d{1,2}\\s+\\d{1,2}:\\d{2}\\]\\s+|\\[\\d{1,2}:\\d{2}\\]\\s+)?(.*)$"); +const static boost::regex TIMESTAMP("^(\\[\\d{4}/\\d{1,2}/\\d{1,2}\\s+\\d{1,2}:\\d{2}\\]|\\[\\d{1,2}:\\d{2}\\]).*"); /** * Regular expression suitable to match names like @@ -328,69 +331,6 @@ void LLLogChat::saveHistory(const std::string& filename, } } -void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata) -{ - if(!filename.size()) - { - llwarns << "Filename is Empty!" << llendl; - return ; - } - - LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "r"); /*Flawfinder: ignore*/ - if (!fptr) - { - callback(LOG_EMPTY, LLSD(), userdata); - return; //No previous conversation with this name. - } - else - { - char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/ - char *bptr; - S32 len; - bool firstline=TRUE; - - if ( fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END) ) - { //File is smaller than recall size. Get it all. - firstline = FALSE; - if ( fseek(fptr, 0, SEEK_SET) ) - { - fclose(fptr); - return; - } - } - - while ( fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr) ) - { - len = strlen(buffer) - 1; /*Flawfinder: ignore*/ - for ( bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--) *bptr='\0'; - - if (!firstline) - { - LLSD item; - std::string line(buffer); - std::istringstream iss(line); - - if (!LLChatLogParser::parse(line, item)) - { - item["message"] = line; - callback(LOG_LINE, item, userdata); - } - else - { - callback(LOG_LLSD, item, userdata); - } - } - else - { - firstline = FALSE; - } - } - callback(LOG_END, LLSD(), userdata); - - fclose(fptr); - } -} - // static void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params) { @@ -506,19 +446,46 @@ std::string LLLogChat::oldLogFileName(std::string filename) void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_transcriptions) { // get Users log directory - std::string directory = gDirUtilp->getPerAccountChatLogsDir(); + std::string dirname = gDirUtilp->getPerAccountChatLogsDir(); // add final OS dependent delimiter - directory += gDirUtilp->getDirDelimiter(); + dirname += gDirUtilp->getDirDelimiter(); // create search pattern std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION; - LLDirIterator iter(directory, pattern); - std::string scanResult; - while (iter.next(scanResult)) + LLDirIterator iter(dirname, pattern); + std::string filename; + while (iter.next(filename)) { - list_of_transcriptions.push_back(scanResult); + std::string fullname = gDirUtilp->add(dirname, filename); + + LLFILE * filep = LLFile::fopen(fullname, "rb"); + if (NULL != filep) + { + char buffer[LOG_RECALL_SIZE]; + + fseek(filep, 0, SEEK_END); // seek to end of file + S32 bytes_to_read = ftell(filep); // get current file pointer + fseek(filep, 0, SEEK_SET); // seek back to beginning of file + + // limit the number characters to read from file + if (bytes_to_read >= LOG_RECALL_SIZE) + { + bytes_to_read = LOG_RECALL_SIZE - 1; + } + + if (bytes_to_read > 0 && NULL != fgets(buffer, bytes_to_read, filep)) + { + //matching a timestamp + boost::match_results<std::string::const_iterator> matches; + if (boost::regex_match(std::string(buffer), matches, TIMESTAMP)) + { + list_of_transcriptions.push_back(gDirUtilp->add(dirname, filename)); + } + } + LLFile::close(filep); + } } } @@ -533,6 +500,46 @@ boost::signals2::connection LLLogChat::setSaveHistorySignal(const save_history_s return sSaveHistorySignal->connect(cb); } +//static +void LLLogChat::deleteTranscripts() +{ + std::vector<std::string> list_of_transcriptions; + getListOfTranscriptFiles(list_of_transcriptions); + + BOOST_FOREACH(const std::string& fullpath, list_of_transcriptions) + { + S32 retry_count = 0; + while (retry_count < 5) + { + if (0 != LLFile::remove(fullpath)) + { + retry_count++; + S32 result = errno; + LL_WARNS("LLLogChat::deleteTranscripts") << "Problem removing " << fullpath << " - errorcode: " + << result << " attempt " << retry_count << LL_ENDL; + + if(retry_count >= 5) + { + LL_WARNS("LLLogChat::deleteTranscripts") << "Failed to remove " << fullpath << LL_ENDL; + return; + } + + ms_sleep(100); + } + else + { + if (retry_count) + { + LL_WARNS("LLLogChat::deleteTranscripts") << "Successfully removed " << fullpath << LL_ENDL; + } + break; + } + } + } + + LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); +} + //*TODO mark object's names in a special way so that they will be distinguishable form avatar name //which are more strict by its nature (only firstname and secondname) //Example, an object's name can be written like "Object <actual_object's_name>" diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index b35a94b4b3..5fbb4ade96 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -51,16 +51,13 @@ public: const std::string& line); static void getListOfTranscriptFiles(std::vector<std::string>& list); - /** @deprecated @see loadChatHistory() */ - static void loadHistory(const std::string& filename, - void (*callback)(ELogLineType, const LLSD&, void*), - void* userdata); - static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD()); typedef boost::signals2::signal<void ()> save_history_signal_t; static boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb); + static void deleteTranscripts(); + private: static std::string cleanFileName(std::string filename); static save_history_signal_t * sSaveHistorySignal; @@ -123,6 +120,6 @@ extern const std::string LL_IM_TIME; //("time"); extern const std::string LL_IM_TEXT; //("message"); extern const std::string LL_IM_FROM; //("from"); extern const std::string LL_IM_FROM_ID; //("from_id"); -extern const std::string LL_TRANSCRIPT_FILE_EXTENSION; //("ll.txt"); +extern const std::string LL_TRANSCRIPT_FILE_EXTENSION; //("txt"); #endif -- cgit v1.2.3 From 7ed270ff9dfdbc905dbee70907d3057a5ae490e7 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 6 Feb 2013 18:11:52 -0800 Subject: CHUI-735 : Fixed! Move the delete key handling from the llfolderview to the llinventorypanel level. --- indra/llui/llfolderview.cpp | 23 ----------------------- indra/llui/llfolderview.h | 3 --- indra/newview/llinventorypanel.cpp | 8 ++++++++ 3 files changed, 8 insertions(+), 26 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index c756ff84e1..dca14cc48f 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1336,29 +1336,6 @@ BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) } -BOOL LLFolderView::canDoDelete() const -{ - if (mSelectedItems.size() == 0) return FALSE; - - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - if (!(*item_it)->getViewModelItem()->isItemRemovable()) - { - return FALSE; - } - } - return TRUE; -} - -void LLFolderView::doDelete() -{ - if(mSelectedItems.size() > 0) - { - removeSelectedItems(); - } -} - - BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) { mKeyboardSelection = FALSE; diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 05b2abb9d3..11fccdace4 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -180,9 +180,6 @@ public: virtual BOOL canPaste() const; virtual void paste(); - virtual BOOL canDoDelete() const; - virtual void doDelete(); - LLFolderViewItem* getNextUnselectedItem(); // Public rename functionality - can only start the process diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 019ba8f5b2..0653a097f5 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1365,6 +1365,14 @@ BOOL LLInventoryPanel::handleKeyHere( KEY key, MASK mask ) LLInventoryAction::doToSelected(mInventory, mFolderRoot, "open"); handled = TRUE; } + break; + case KEY_DELETE: + if (mask == MASK_NONE) + { + LLInventoryAction::doToSelected(mInventory, mFolderRoot, "delete"); + handled = TRUE; + } + break; } return handled; } -- cgit v1.2.3 From b356bbb6a5930e8900250c6654688ae2e6d25ecf Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Thu, 7 Feb 2013 10:48:49 +0200 Subject: CHUI-713 "Conversations" floater size doesn't persist between sessions --- indra/newview/llfloaterimcontainer.cpp | 9 +++++++-- indra/newview/llfloaterimsessiontab.cpp | 5 ++++- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 5a284cc7b7..27e579a68c 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -273,14 +273,19 @@ void LLFloaterIMContainer::addFloater(LLFloater* floaterp, openFloater(floaterp->getKey()); return; } + + LLUUID session_id = floaterp->getKey(); // Make sure the message panel is open when adding a floater or it stays mysteriously hidden - collapseMessagesPane(false); + if (session_id != LLUUID()) + { + collapseMessagesPane(false); + } // Add the floater LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); - LLUUID session_id = floaterp->getKey(); + LLIconCtrl* icon = 0; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 6dbcdb4474..526eeef869 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -769,7 +769,10 @@ void LLFloaterIMSessionTab::onOpen(const LLSD& key) { LLFloaterIMContainer* host_floater = dynamic_cast<LLFloaterIMContainer*>(getHost()); // Show the messages pane when opening a floater hosted in the Conversations - host_floater->collapseMessagesPane(false); + if (!isNearbyChat()) + { + host_floater->collapseMessagesPane(false); + } } } -- cgit v1.2.3 From 68a4a8402ccd614f5cdb40cb53efa85166c12598 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 7 Feb 2013 19:39:46 +0200 Subject: CHUI-722 Fixed! Add ? button to titlebar on floaters: Conversation Log, Nearby Chat History, and IM History --- indra/newview/skins/default/xui/en/floater_conversation_log.xml | 1 + indra/newview/skins/default/xui/en/floater_conversation_preview.xml | 1 + 2 files changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml index 7229292a14..19a4cbc119 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -3,6 +3,7 @@ <floater can_resize="true" positioning="cascading" + help_topic="conversation_log" height="200" min_height="100" min_width="230" diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml index 6f1ddaaf4f..764b9d8385 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -3,6 +3,7 @@ legacy_header_height="18" can_resize="true" default_tab_group="1" + help_topic="conversation_preview" height="391" layout="topleft" min_height="243" -- cgit v1.2.3 From dac026a7d6ad932ef185b4e5c5b5efd7b059e911 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 7 Feb 2013 13:27:32 -0800 Subject: CHUI-735 : Fixed! Handle the backspace case, suppress the search string handling from LLFolderView (it's in the search edit field now). --- indra/llui/llfolderview.cpp | 14 -------------- indra/newview/llinventorypanel.cpp | 3 +++ 2 files changed, 3 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index dca14cc48f..8feaf654f0 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1275,20 +1275,6 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) break; } - if (!handled && mParentPanel->hasFocus()) - { - if (key == KEY_BACKSPACE) - { - mSearchTimer.reset(); - if (mSearchString.size()) - { - mSearchString.erase(mSearchString.size() - 1, 1); - } - search(getCurSelectedItem(), mSearchString, FALSE); - handled = TRUE; - } - } - return handled; } diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 0653a097f5..578b83fd28 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1367,6 +1367,9 @@ BOOL LLInventoryPanel::handleKeyHere( KEY key, MASK mask ) } break; case KEY_DELETE: + case KEY_BACKSPACE: + // Delete selected items if delete or backspace key hit on the inventory panel + // Note: on Mac laptop keyboards, backspace and delete are one and the same if (mask == MASK_NONE) { LLInventoryAction::doToSelected(mInventory, mFolderRoot, "delete"); -- cgit v1.2.3 From 29a57c16c976eb39b3a0e82872435e0228044ba9 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 7 Feb 2013 14:41:38 -0800 Subject: CHUI-736: When auto-exit DND mode upon startup, stored conversations are not highlighted. When the dnd im is processed, now flash the conversation line item. --- indra/newview/llimview.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d4c8d8c4f4..2eaef48049 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -107,6 +107,7 @@ void process_dnd_im(const LLSD& notification) { LLSD data = notification["substitutions"]; LLUUID sessionID = data["SESSION_ID"].asUUID(); + LLUUID fromID = data["FROM_ID"].asUUID(); //re-create the IM session if needed //(when coming out of DND mode upon app restart) @@ -119,14 +120,22 @@ void process_dnd_im(const LLSD& notification) { name = av_name.getDisplayName(); } - + LLIMModel::getInstance()->newSession(sessionID, name, IM_NOTHING_SPECIAL, - data["FROM_ID"], + fromID, false, false); //will need slight refactor to retrieve whether offline message or not (assume online for now) + + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + + if (im_box) + { + im_box->flashConversationItemWidget(sessionID, true); + } + } } -- cgit v1.2.3 From c55e4a61242cd3cf94e0a28398fd33a4eb8ea683 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Fri, 8 Feb 2013 02:03:28 +0000 Subject: CHUI-703 FIX Notification buttons: "Join","Decline","Info" are duplicated after relogin while group invitation Changed LLPersistentNotificationStorage::saveNotification() to use notification->asLLSD(true) to skip duplicates Changed LLDockControl::mDockWidget to be a LLHandle<LLView> instead of a LLView* to fix crash (from accessing deleted LLView) --- indra/llui/lldockcontrol.cpp | 31 +++++++++++++---------- indra/llui/lldockcontrol.h | 4 +-- indra/newview/llpersistentnotificationstorage.cpp | 2 +- 3 files changed, 21 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index af39e41fa6..602113432e 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -31,7 +31,6 @@ LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) : - mDockWidget(dockWidget), mDockableFloater(dockableFloater), mDockTongue(dockTongue), mDockTongueX(0), @@ -39,6 +38,11 @@ LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, { mDockAt = dockAt; + if (dockWidget != NULL) + { + mDockWidget = dockWidget->getHandle(); + } + if (dockableFloater->isDocked()) { on(); @@ -62,7 +66,7 @@ LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, repositionDockable(); } - if (mDockWidget != NULL) + if (getDock() != NULL) { mDockWidgetVisible = isDockVisible(); } @@ -78,14 +82,15 @@ LLDockControl::~LLDockControl() void LLDockControl::setDock(LLView* dockWidget) { - mDockWidget = dockWidget; - if (mDockWidget != NULL) + if (dockWidget != NULL) { + mDockWidget = dockWidget->getHandle(); repositionDockable(); mDockWidgetVisible = isDockVisible(); } else { + mDockWidget = LLHandle<LLView>(); mDockWidgetVisible = false; } } @@ -97,8 +102,8 @@ void LLDockControl::getAllowedRect(LLRect& rect) void LLDockControl::repositionDockable() { - if (!mDockWidget) return; - LLRect dockRect = mDockWidget->calcScreenRect(); + if (!getDock()) return; + LLRect dockRect = getDock()->calcScreenRect(); LLRect rootRect; LLRect floater_rect = mDockableFloater->calcScreenRect(); mGetAllowedRectCallback(rootRect); @@ -150,13 +155,13 @@ bool LLDockControl::isDockVisible() { bool res = true; - if (mDockWidget != NULL) + if (getDock() != NULL) { //we should check all hierarchy - res = mDockWidget->isInVisibleChain(); + res = getDock()->isInVisibleChain(); if (res) { - LLRect dockRect = mDockWidget->calcScreenRect(); + LLRect dockRect = getDock()->calcScreenRect(); switch (mDockAt) { @@ -169,7 +174,7 @@ bool LLDockControl::isDockVisible() // assume that parent for all dockable floaters // is the root view LLRect dockParentRect = - mDockWidget->getRootView()->calcScreenRect(); + getDock()->getRootView()->calcScreenRect(); if (dockRect.mRight <= dockParentRect.mLeft || dockRect.mLeft >= dockParentRect.mRight) { @@ -189,7 +194,7 @@ bool LLDockControl::isDockVisible() void LLDockControl::moveDockable() { // calculate new dockable position - LLRect dockRect = mDockWidget->calcScreenRect(); + LLRect dockRect = getDock()->calcScreenRect(); LLRect rootRect; mGetAllowedRectCallback(rootRect); @@ -263,7 +268,7 @@ void LLDockControl::moveDockable() // calculate dock tongue position - dockParentRect = mDockWidget->getParent()->calcScreenRect(); + dockParentRect = getDock()->getParent()->calcScreenRect(); if (dockRect.getCenterX() < dockParentRect.mLeft) { mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2; @@ -299,7 +304,7 @@ void LLDockControl::moveDockable() } // calculate dock tongue position - dockParentRect = mDockWidget->getParent()->calcScreenRect(); + dockParentRect = getDock()->getParent()->calcScreenRect(); if (dockRect.getCenterX() < dockParentRect.mLeft) { mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2; diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h index c9602011f6..a1cfa0072c 100644 --- a/indra/llui/lldockcontrol.h +++ b/indra/llui/lldockcontrol.h @@ -63,7 +63,7 @@ public: void setDock(LLView* dockWidget); LLView* getDock() { - return mDockWidget; + return mDockWidget.get(); } void repositionDockable(); void drawToungue(); @@ -83,7 +83,7 @@ private: bool mRecalculateDockablePosition; bool mDockWidgetVisible; DocAt mDockAt; - LLView* mDockWidget; + LLHandle<LLView> mDockWidget; LLRect mPrevDockRect; LLRect mRootRect; LLRect mFloaterRect; diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index 224aaa2146..11c12e6c10 100644 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -75,7 +75,7 @@ void LLPersistentNotificationStorage::saveNotifications() continue; } - data.append(notification->asLLSD()); + data.append(notification->asLLSD(true)); } writeNotifications(output); -- cgit v1.2.3 From 64fe330620459be18ee4dd54866386a8f6a76ab8 Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Sat, 9 Feb 2013 00:10:09 +0200 Subject: CHUI-713 "Conversations" floater size doesn't persist between sessions additional fix --- indra/newview/llfloaterimcontainer.cpp | 12 ++++++++++-- indra/newview/llfloaterimcontainer.h | 1 + indra/newview/llfloaterimsessiontab.cpp | 5 +---- 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 27e579a68c..312f70fe30 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -62,7 +62,8 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param mExpandCollapseBtn(NULL), mConversationsRoot(NULL), mConversationsEventStream("ConversationsEvents"), - mInitialized(false) + mInitialized(false), + mIsFirstLaunch(false) { mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2)); mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction, this, _2)); @@ -243,6 +244,7 @@ BOOL LLFloaterIMContainer::postBuild() mGeneralTitle = getTitle(); mInitialized = true; + mIsFirstLaunch = true; // Add callbacks: // We'll take care of view updates on idle @@ -277,7 +279,7 @@ void LLFloaterIMContainer::addFloater(LLFloater* floaterp, LLUUID session_id = floaterp->getKey(); // Make sure the message panel is open when adding a floater or it stays mysteriously hidden - if (session_id != LLUUID()) + if (!mIsFirstLaunch) { collapseMessagesPane(false); } @@ -635,6 +637,12 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse) return; } + if (mIsFirstLaunch) + { + mIsFirstLaunch = false; + return; + } + // Save current width of panels before collapsing/expanding right pane. S32 conv_pane_width = mConversationsPane->getRect().getWidth(); S32 msg_pane_width = mMessagesPane->getRect().getWidth(); diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 06af6c7b51..a28dba3b98 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -167,6 +167,7 @@ private: LLLayoutStack* mConversationsStack; bool mInitialized; + bool mIsFirstLaunch; LLUUID mSelectedSession; std::string mGeneralTitle; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 526eeef869..6dbcdb4474 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -769,10 +769,7 @@ void LLFloaterIMSessionTab::onOpen(const LLSD& key) { LLFloaterIMContainer* host_floater = dynamic_cast<LLFloaterIMContainer*>(getHost()); // Show the messages pane when opening a floater hosted in the Conversations - if (!isNearbyChat()) - { - host_floater->collapseMessagesPane(false); - } + host_floater->collapseMessagesPane(false); } } -- cgit v1.2.3 From 46294bdcaca5ea259dee95256179653779697e21 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Fri, 8 Feb 2013 19:54:34 +0200 Subject: CHUI-731 FIXED Viewer crashed while deleting text from IM message --- indra/llui/lltextbase.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 8839afb60d..4c9c2781f2 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -605,7 +605,8 @@ void LLTextBase::drawText() // Find the start of the first word U32 word_start = seg_start, word_end = -1; - while ( (word_start < wstrText.length()) && (!LLStringOps::isAlpha(wstrText[word_start])) ) + U32 text_length = wstrText.length(); + while ( (word_start < text_length) && (!LLStringOps::isAlpha(wstrText[word_start])) ) { word_start++; } @@ -627,11 +628,15 @@ void LLTextBase::drawText() break; } - // Don't process words shorter than 3 characters - std::string word = wstring_to_utf8str(wstrText.substr(word_start, word_end - word_start)); - if ( (word.length() >= 3) && (!LLSpellChecker::instance().checkSpelling(word)) ) + if (word_start < text_length && word_end <= text_length && word_end > word_start) { - mMisspellRanges.push_back(std::pair<U32, U32>(word_start, word_end)); + std::string word = wstring_to_utf8str(wstrText.substr(word_start, word_end - word_start)); + + // Don't process words shorter than 3 characters + if ( (word.length() >= 3) && (!LLSpellChecker::instance().checkSpelling(word)) ) + { + mMisspellRanges.push_back(std::pair<U32, U32>(word_start, word_end)); + } } // Find the start of the next word -- cgit v1.2.3 From 4a0dd9ec76bfc9a3207b0e75608343f29fb26358 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Fri, 8 Feb 2013 19:16:38 +0000 Subject: CHUI-703 FIX Notification buttons: "Join","Decline","Info" are duplicated after relogin while group invitation Renamed LLDockControl::mDockWidget to mDockWidgetHandle for clarity --- indra/llui/lldockcontrol.cpp | 6 +++--- indra/llui/lldockcontrol.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index 602113432e..bd42497cb6 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -40,7 +40,7 @@ LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, if (dockWidget != NULL) { - mDockWidget = dockWidget->getHandle(); + mDockWidgetHandle = dockWidget->getHandle(); } if (dockableFloater->isDocked()) @@ -84,13 +84,13 @@ void LLDockControl::setDock(LLView* dockWidget) { if (dockWidget != NULL) { - mDockWidget = dockWidget->getHandle(); + mDockWidgetHandle = dockWidget->getHandle(); repositionDockable(); mDockWidgetVisible = isDockVisible(); } else { - mDockWidget = LLHandle<LLView>(); + mDockWidgetHandle = LLHandle<LLView>(); mDockWidgetVisible = false; } } diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h index a1cfa0072c..98a9c7236d 100644 --- a/indra/llui/lldockcontrol.h +++ b/indra/llui/lldockcontrol.h @@ -63,7 +63,7 @@ public: void setDock(LLView* dockWidget); LLView* getDock() { - return mDockWidget.get(); + return mDockWidgetHandle.get(); } void repositionDockable(); void drawToungue(); @@ -83,7 +83,7 @@ private: bool mRecalculateDockablePosition; bool mDockWidgetVisible; DocAt mDockAt; - LLHandle<LLView> mDockWidget; + LLHandle<LLView> mDockWidgetHandle; LLRect mPrevDockRect; LLRect mRootRect; LLRect mFloaterRect; -- cgit v1.2.3 From a034c272c3d8d526a70998aae7ee816070481c39 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 8 Feb 2013 18:12:26 -0800 Subject: CHUI-747: Script buttons in a toast overlap message text. Problem was due to the message container not being shifted upward when buttons were added to the control buttons container (which is beneath the message container). A small change in CHUI-695 caused this. --- indra/newview/lltoastnotifypanel.cpp | 3 +++ indra/newview/skins/default/xui/en/panel_notification.xml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index bd6c42d474..3fd056ea31 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -403,6 +403,9 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) } } + //.xml file intially makes info panel only follow left/right/top. This is so that when control buttons are added the info panel + //can shift upward making room for the buttons inside mControlPanel. After the buttons are added, the info panel can then be set to follow 'all'. + mInfoPanel->setFollowsAll(); snapToMessageHeight(mTextBox, MAX_LENGTH); } diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml index 421ecf10a1..94c468e1bb 100644 --- a/indra/newview/skins/default/xui/en/panel_notification.xml +++ b/indra/newview/skins/default/xui/en/panel_notification.xml @@ -22,7 +22,7 @@ background_visible="true" bg_alpha_color="ToastBackground" bg_opaque_color="ToastBackground" - follows="all" + follows="left|right|top" height="100" label="info_panel" layout="topleft" -- cgit v1.2.3 From 2e2026a4f8359aba26e330fc8ec9ce4a3d40e666 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 8 Feb 2013 20:51:02 -0800 Subject: CHUI-746 : Fixed! Undid the MAINT-2276 hack now that submenus do work thanks to CHUI-682 --- indra/newview/llpaneloutfitedit.cpp | 13 +++---------- indra/newview/skins/default/xui/en/menu_cof_gear.xml | 2 +- 2 files changed, 4 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 30f137bdba..c09d4393c8 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -186,11 +186,8 @@ private: // Populate the menu with items like "New Skin", "New Pants", etc. static void populateCreateWearableSubmenus(LLMenuGL* menu) { - // MAINT-2276...these menus are created as dummies because they are not available - // when this function is called. This prevents their parent from popping up later. - // - //LLView* menu_clothes = gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE); - //LLView* menu_bp = gMenuHolder->getChildView("COF.Geear.New_Body_Parts", FALSE); + LLView* menu_clothes = gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE); + LLView* menu_bp = gMenuHolder->getChildView("COF.Gear.New_Body_Parts", FALSE); for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i) { @@ -203,11 +200,7 @@ private: p.on_click.function_name = "Wearable.Create"; p.on_click.parameter = LLSD(type_name); - //LLView* parent = LLWearableType::getAssetType(type) == LLAssetType::AT_CLOTHING ? menu_clothes : menu_bp; - // This is a work-around for MAINT-2276 wherein the parent toggleable menu does not appear - // It puts everything under one menu, but that menu appears, which is better than not. - // - LLView* parent = menu; + LLView* parent = LLWearableType::getAssetType(type) == LLAssetType::AT_CLOTHING ? menu_clothes : menu_bp; LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent); } } diff --git a/indra/newview/skins/default/xui/en/menu_cof_gear.xml b/indra/newview/skins/default/xui/en/menu_cof_gear.xml index a6e9a40e31..45cf780557 100644 --- a/indra/newview/skins/default/xui/en/menu_cof_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_cof_gear.xml @@ -9,5 +9,5 @@ <menu label="New Body Parts" layout="topleft" - name="COF.Geear.New_Body_Parts" /> + name="COF.Gear.New_Body_Parts" /> </toggleable_menu> -- cgit v1.2.3 From 5ecac2e900054526c5e9e2fe5610f470ad06df32 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 8 Feb 2013 22:38:54 -0800 Subject: CHUI-735 : Fixed! Refactor the code to move isSelectionRemovable() to the LLInventoryPanel level. Use it when using the delete key. --- indra/newview/llinventorypanel.cpp | 32 +++++++++++++++++++++++++++++++- indra/newview/llinventorypanel.h | 1 + indra/newview/llpanelmaininventory.cpp | 22 +--------------------- 3 files changed, 33 insertions(+), 22 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 578b83fd28..1357b613bb 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1370,7 +1370,7 @@ BOOL LLInventoryPanel::handleKeyHere( KEY key, MASK mask ) case KEY_BACKSPACE: // Delete selected items if delete or backspace key hit on the inventory panel // Note: on Mac laptop keyboards, backspace and delete are one and the same - if (mask == MASK_NONE) + if (isSelectionRemovable() && (mask == MASK_NONE)) { LLInventoryAction::doToSelected(mInventory, mFolderRoot, "delete"); handled = TRUE; @@ -1380,6 +1380,36 @@ BOOL LLInventoryPanel::handleKeyHere( KEY key, MASK mask ) return handled; } +bool LLInventoryPanel::isSelectionRemovable() +{ + bool can_delete = false; + if (mFolderRoot) + { + std::set<LLFolderViewItem*> selection_set = mFolderRoot->getSelectionList(); + if (!selection_set.empty()) + { + can_delete = true; + for (std::set<LLFolderViewItem*>::iterator iter = selection_set.begin(); + iter != selection_set.end(); + ++iter) + { + LLFolderViewItem *item = *iter; + const LLFolderViewModelItemInventory *listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); + if (!listener) + { + can_delete = false; + } + else + { + can_delete &= listener->isItemRemovable(); + can_delete &= !listener->isItemInTrash(); + } + } + } + } + return can_delete; +} + /************************************************************************/ /* Recent Inventory Panel related class */ /************************************************************************/ diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 6eb85fbad2..00a90325ad 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -162,6 +162,7 @@ public: void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus); void setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb); void clearSelection(); + bool isSelectionRemovable(); LLInventoryFilter& getFilter(); const LLInventoryFilter& getFilter() const; void setFilterTypes(U64 filter, LLInventoryFilter::EFilterType = LLInventoryFilter::FILTERTYPE_OBJECT); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 82b79db60a..d6535c88e9 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -1112,27 +1112,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) const std::string command_name = userdata.asString(); if (command_name == "delete") { - BOOL can_delete = FALSE; - LLFolderView* root = getActivePanel()->getRootFolder(); - if (root) - { - can_delete = TRUE; - std::set<LLFolderViewItem*> selection_set = root->getSelectionList(); - if (selection_set.empty()) return FALSE; - for (std::set<LLFolderViewItem*>::iterator iter = selection_set.begin(); - iter != selection_set.end(); - ++iter) - { - LLFolderViewItem *item = *iter; - const LLFolderViewModelItemInventory *listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); - llassert(listener); - if (!listener) return FALSE; - can_delete &= listener->isItemRemovable(); - can_delete &= !listener->isItemInTrash(); - } - return can_delete; - } - return FALSE; + return getActivePanel()->isSelectionRemovable(); } if (command_name == "save_texture") { -- cgit v1.2.3 From 9a75eeb67e9d768ad925c5d1f0e7ab180be8ee71 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Mon, 11 Feb 2013 14:39:05 +0200 Subject: Fix for build issue under windows --- indra/newview/llinventorypanel.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 1357b613bb..fabcd50c7d 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1401,8 +1401,7 @@ bool LLInventoryPanel::isSelectionRemovable() } else { - can_delete &= listener->isItemRemovable(); - can_delete &= !listener->isItemInTrash(); + can_delete &= listener->isItemRemovable() && !listener->isItemInTrash(); } } } -- cgit v1.2.3 From 4b4367269058c8ba10d284b48ffae9e24fd086ce Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Mon, 11 Feb 2013 15:22:24 +0200 Subject: CHUI-751 FIXED Triple click is now handled. --- indra/llui/lltextbase.cpp | 9 +++++++++ indra/llui/lltextbase.h | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 4c9c2781f2..7cee9f5b46 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -46,6 +46,7 @@ const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds const S32 CURSOR_THICKNESS = 2; +const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click. LLTextBase::line_info::line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num) : mDocIndexStart(index_start), @@ -1004,6 +1005,13 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert) BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask) { + // handle triple click + if (!mTripleClickTimer.hasExpired()) + { + selectAll(); + return TRUE; + } + LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); if (cur_segment && cur_segment->handleMouseDown(x, y, mask)) { @@ -1078,6 +1086,7 @@ BOOL LLTextBase::handleRightMouseUp(S32 x, S32 y, MASK mask) BOOL LLTextBase::handleDoubleClick(S32 x, S32 y, MASK mask) { + mTripleClickTimer.setTimerExpirySec(TRIPLE_CLICK_INTERVAL); LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); if (cur_segment && cur_segment->handleDoubleClick(x, y, mask)) { diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 629b304b25..ad566a36d3 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -598,7 +598,8 @@ protected: // selection S32 mSelectionStart; S32 mSelectionEnd; - + LLTimer mTripleClickTimer; + BOOL mIsSelecting; // Are we in the middle of a drag-select? // spell checking -- cgit v1.2.3 From 5066e850df6e44e65bf7760ac990fdd5ed1c7b8e Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Mon, 11 Feb 2013 15:26:17 +0200 Subject: CHUI-728 FIXED Don't display Nearby chat participants if Conversation pane is collapsed. --- indra/newview/llfloaterimcontainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 05db0e93e6..cef45a5b56 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1769,7 +1769,7 @@ void LLFloaterIMContainer::openNearbyChat() { // If there's only one conversation in the container and that conversation is the nearby chat //(which it should be...), open it so to make the list of participants visible. This happens to be the most common case when opening the Chat floater. - if(mConversationsItems.size() == 1) + if((mConversationsItems.size() == 1)&&(!mConversationsPane->isCollapsed())) { LLConversationViewSession* nearby_chat = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,LLUUID())); if (nearby_chat) -- cgit v1.2.3 From 33d49d15693de15527960476b816845f8b3d6d54 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Mon, 11 Feb 2013 20:02:19 +0000 Subject: CHUI-755 FIX Conversation log changes in a session are lost if viewer crashes Added call to LLConversationLog::instance().cache() after LLLogChat::SaveHistory() in LLIMView::logToFile() --- indra/newview/llconversationlog.cpp | 2 +- indra/newview/llconversationlog.h | 2 +- indra/newview/llimview.cpp | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 82176b3a06..4e707ac76e 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -276,7 +276,7 @@ void LLConversationLog::updateConversationName(const LLIMModel::LLIMSession* ses LLConversation* conversation = findConversation(session); if (conversation) { - conversation->setConverstionName(name); + conversation->setConversationName(name); notifyParticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_NAME); } } diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index d5b6eccb29..fd38556131 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -58,7 +58,7 @@ public: const time_t& getTime() const { return mTime; } bool hasOfflineMessages() const { return mHasOfflineIMs; } - void setConverstionName(std::string conv_name) { mConversationName = conv_name; } + void setConversationName(std::string conv_name) { mConversationName = conv_name; } void setOfflineMessages(bool new_messages) { mHasOfflineIMs = new_messages; } bool isOlderThan(U32 days) const; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 2eaef48049..cdf6cb6252 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -66,6 +66,7 @@ #include "lltoolbarview.h" #include "llviewercontrol.h" #include "llviewerparcelmgr.h" +#include "llconversationlog.h" #include "message.h" @@ -950,6 +951,7 @@ bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, } LLLogChat::saveHistory(file_name, from_name, from_id, utf8_text); + LLConversationLog::instance().cache(); // update the conversation log too return true; } else -- cgit v1.2.3 From f6b9d2bce45818f15e2882a7cb34ce9ea7a2e4ba Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Mon, 11 Feb 2013 20:39:03 +0000 Subject: CHUI-760 FIX Conversation.log file not saved in user specified location Changed LLConversationLog::getFileName() to use LL_PATH_PER_ACCOUNT_CHAT_LOGS instead of LL_PATH_PER_SL_ACCOUNT --- indra/newview/llconversationlog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 4e707ac76e..15d61e978d 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -378,7 +378,7 @@ void LLConversationLog::cache() std::string LLConversationLog::getFileName() { std::string filename = "conversation"; - return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, filename) + ".log"; + return gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename) + ".log"; } bool LLConversationLog::saveToFile(const std::string& filename) -- cgit v1.2.3 From 279d4a95ea84ddeb32efc54deb6923202fe638a7 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Mon, 11 Feb 2013 16:08:45 -0800 Subject: CHUI-690 : Fixed! Prevent xml parsing error when building Places panel providing an option menu to the LLFolderView constructor --- indra/newview/llplacesinventorypanel.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index 01586a4d91..4c2213c198 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -82,6 +82,7 @@ LLFolderView * LLPlacesInventoryPanel::createFolderRoot(LLUUID root_id ) p.show_item_link_overlays = mShowItemLinkOverlays; p.root = NULL; p.use_ellipses = mParams.folder_view.use_ellipses; + p.options_menu = "menu_inventory.xml"; return LLUICtrlFactory::create<LLPlacesFolderView>(p); } -- cgit v1.2.3 From 5a92a7700666f40883b72deed8429e7e06164623 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Tue, 12 Feb 2013 01:12:47 +0000 Subject: CHUI-740 FIX Incorrect option shown in group Moderator tools "Toggle mute this participant" Reverted changes in menu_conversation.xml, llconversationmodel.cpp, and llfloaterimcontainer.cpp --- indra/newview/llconversationmodel.cpp | 3 ++- indra/newview/llfloaterimcontainer.cpp | 12 ++++++++++-- indra/newview/skins/default/xui/en/menu_conversation.xml | 13 ++++++++++--- 3 files changed, 22 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index bfc564f407..0977056b2a 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -151,7 +151,8 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32 items.push_back(std::string("Moderator Options")); items.push_back(std::string("AllowTextChat")); items.push_back(std::string("moderate_voice_separator")); - items.push_back(std::string("ModerateVoiceToggleMuteSelected")); + items.push_back(std::string("ModerateVoiceMuteSelected")); + items.push_back(std::string("ModerateVoiceUnMuteSelected")); items.push_back(std::string("ModerateVoiceMute")); items.push_back(std::string("ModerateVoiceUnmute")); } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index cef45a5b56..30ea9f10c0 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1245,7 +1245,7 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v { return LLAvatarActions::canOfferTeleport(uuids); } - else if (("can_moderate_voice" == item) || ("can_allow_text_chat" == item) || ("can_mute_unmute" == item)) + else if (("can_moderate_voice" == item) || ("can_allow_text_chat" == item) || ("can_mute" == item) || ("can_unmute" == item)) { // *TODO : get that out of here... return enableModerateContextMenuItem(item); @@ -1589,10 +1589,18 @@ bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& user bool voice_channel = speakerp->isInVoiceChannel(); - if ("can_moderate_voice" == userdata || "can_mute_unmute" == userdata) + if ("can_moderate_voice" == userdata) { return voice_channel; } + else if ("can_mute" == userdata) + { + return voice_channel && !isMuted(getCurSelectedViewModelItem()->getUUID()); + } + else if ("can_unmute" == userdata) + { + return voice_channel && isMuted(getCurSelectedViewModelItem()->getUUID()); + } // The last invoke is used to check whether the "can_allow_text_chat" will enabled return LLVoiceClient::getInstance()->isParticipantAvatar(getCurSelectedViewModelItem()->getUUID()); diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index 46c6e19fa5..8583747da0 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -163,11 +163,18 @@ </menu_item_check> <menu_item_separator layout="topleft" name="moderate_voice_separator" /> <menu_item_call - label="Toggle mute this participant" + label="Mute this participant" layout="topleft" - name="ModerateVoiceToggleMuteSelected"> + name="ModerateVoiceMuteSelected"> <on_click function="Avatar.DoToSelected" parameter="selected" /> - <on_enable function="Avatar.EnableItem" parameter="can_mute_unmute" /> + <on_enable function="Avatar.EnableItem" parameter="can_mute" /> + </menu_item_call> + <menu_item_call + label="Unmute this participant" + layout="topleft" + name="ModerateVoiceUnMuteSelected"> + <on_click function="Avatar.DoToSelected" parameter="selected" /> + <on_enable function="Avatar.EnableItem" parameter="can_unmute" /> </menu_item_call> <menu_item_call label="Mute everyone" -- cgit v1.2.3 From 8aaedd0a5fc73f45684c029ca9f349d793e61e93 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Tue, 12 Feb 2013 14:27:52 +0200 Subject: CHUI-742 FIXED Update log location when closing Preference floater. --- indra/newview/llfloaterpreference.cpp | 13 ++++++++++--- indra/newview/llfloaterpreference.h | 3 ++- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index da24bb3b8f..662d2df5d2 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -646,6 +646,9 @@ void LLFloaterPreference::cancel() LLFloaterPathfindingConsole* pPathfindingConsole = pathfindingConsoleHandle.get(); pPathfindingConsole->onRegionBoundaryCross(); } + + std::string dir_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); + updateLogLocation(dir_name); } void LLFloaterPreference::onOpen(const LLSD& key) @@ -1443,16 +1446,20 @@ void LLFloaterPreference::onClickLogPath() std::string dir_name = picker.getDirName(); gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); + updateLogLocation(dir_name); + // enable/disable 'Delete transcripts button + updateDeleteTranscriptsButton(); +} + +void LLFloaterPreference::updateLogLocation(const std::string& dir_name) +{ gDirUtilp->setChatLogsDir(dir_name); gDirUtilp->updatePerAccountChatLogsDir(); LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); // refresh IM floaters with new logs from files from new selected directory LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); - - // enable/disable 'Delete transcripts button - updateDeleteTranscriptsButton(); } void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im_via_email) diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index f9f1d52244..dbd87f74a1 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -142,7 +142,8 @@ public: void onClickDisablePopup(); void resetAllIgnored(); void setAllIgnored(); - void onClickLogPath(); + void onClickLogPath(); + void updateLogLocation(const std::string& dir_name); void enableHistory(); void setPersonalInfo(const std::string& visibility, bool im_via_email); void refreshEnabledState(); -- cgit v1.2.3 From b1d03f940d4682db3e9866888d6f00f9300a55ed Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 12 Feb 2013 12:31:59 -0800 Subject: CHUI-758: Group notice received in DND mode causes crash on startup when auto-exiting DND mode. Crash occurred because two instances of the Group Notice notification were trying to be added from the persistent storage and then the DND storage. --- .../newview/lldonotdisturbnotificationstorage.cpp | 32 ++++++++++++++-------- indra/newview/llviewermessage.cpp | 5 +++- 2 files changed, 25 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index f7af447a57..22f35752bd 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -164,22 +164,32 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() { offerExists = true; } - - //New notification needs to be added - notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true)); - LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]); - if (responder == NULL) + + //Notification already exists due to persistent storage adding it first into the notification system + if(notification) { - LL_WARNS("LLDoNotDisturbNotificationStorage") << "cannot create responder for notification of type '" - << notification->getType() << "'" << LL_ENDL; + notification->setDND(true); + instance.update(instance.find(notificationID)); } + //New notification needs to be added else { - LLNotificationResponderPtr responderPtr(responder); - notification->setResponseFunctor(responderPtr); + notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true)); + LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]); + if (responder == NULL) + { + LL_WARNS("LLDoNotDisturbNotificationStorage") << "cannot create responder for notification of type '" + << notification->getType() << "'" << LL_ENDL; + } + else + { + LLNotificationResponderPtr responderPtr(responder); + notification->setResponseFunctor(responderPtr); + } + + instance.add(notification); } - - instance.add(notification); + } if(imToastExists) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 6bbfd30794..2340436a01 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2615,7 +2615,10 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) payload["sender_name"] = name; payload["group_id"] = group_id; payload["inventory_name"] = item_name; - payload["inventory_offer"] = info ? info->asLLSD() : LLSD(); + if(info && info->asLLSD()) + { + payload["inventory_offer"] = info->asLLSD(); + } LLSD args; args["SUBJECT"] = subj; -- cgit v1.2.3 From 649a191c4fd7880e41aff5aae07b31b2a6fa840a Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Wed, 13 Feb 2013 00:12:04 +0000 Subject: CHUI-740 FIX Incorrect option shown in group Moderator tools "Toggle mute this participant" Made mute and unmute invisible instead of disabled when not available --- indra/newview/skins/default/xui/en/menu_conversation.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index 8583747da0..cbd2343a3c 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -167,14 +167,14 @@ layout="topleft" name="ModerateVoiceMuteSelected"> <on_click function="Avatar.DoToSelected" parameter="selected" /> - <on_enable function="Avatar.EnableItem" parameter="can_mute" /> + <on_visible function="Avatar.EnableItem" parameter="can_mute" /> </menu_item_call> <menu_item_call label="Unmute this participant" layout="topleft" name="ModerateVoiceUnMuteSelected"> <on_click function="Avatar.DoToSelected" parameter="selected" /> - <on_enable function="Avatar.EnableItem" parameter="can_unmute" /> + <on_visible function="Avatar.EnableItem" parameter="can_unmute" /> </menu_item_call> <menu_item_call label="Mute everyone" -- cgit v1.2.3 From d818252528aa68a387dc237d1c5a74d366c5a120 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Wed, 13 Feb 2013 01:38:24 +0000 Subject: CHUI-740 FIX Incorrect option shown in group Moderator tools "Toggle mute this participant" Added new LLFloaterIMContainer::visibleContextMenuItem() connected to "Avatar.VisibleItem" --- indra/newview/llfloaterimcontainer.cpp | 21 +++++++++++++++++++-- indra/newview/llfloaterimcontainer.h | 5 +++-- .../skins/default/xui/en/menu_conversation.xml | 6 ++++-- 3 files changed, 26 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 30ea9f10c0..52e153a15e 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -68,8 +68,9 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2)); mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction, this, _2)); - mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMContainer::checkContextMenuItem, this, _2)); - mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMContainer::enableContextMenuItem, this, _2)); + mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMContainer::checkContextMenuItem, this, _2)); + mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMContainer::enableContextMenuItem, this, _2)); + mEnableCallbackRegistrar.add("Avatar.VisibleItem", boost::bind(&LLFloaterIMContainer::visibleContextMenuItem, this, _2)); mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMContainer::doToSelected, this, _2)); mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&LLFloaterIMContainer::doToSelectedGroup, this, _2)); @@ -1290,6 +1291,22 @@ bool LLFloaterIMContainer::checkContextMenuItem(const std::string& item, uuid_ve return false; } +bool LLFloaterIMContainer::visibleContextMenuItem(const LLSD& userdata) +{ + const std::string& item = userdata.asString(); + + if ("show_mute" == item) + { + return !isMuted(getCurSelectedViewModelItem()->getUUID()); + } + else if ("show_unmute" == item) + { + return isMuted(getCurSelectedViewModelItem()->getUUID()); + } + + return true; +} + void LLFloaterIMContainer::showConversation(const LLUUID& session_id) { setVisibleAndFrontmost(false); diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index a28dba3b98..265ae8df4c 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -140,8 +140,9 @@ private: const LLConversationItem * getCurSelectedViewModelItem(); void getParticipantUUIDs(uuid_vec_t& selected_uuids); void doToSelected(const LLSD& userdata); - bool checkContextMenuItem(const LLSD& userdata); - bool enableContextMenuItem(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); + bool enableContextMenuItem(const LLSD& userdata); + bool visibleContextMenuItem(const LLSD& userdata); void doToSelectedConversation(const std::string& command, uuid_vec_t& selectedIDS); void doToSelectedGroup(const LLSD& userdata); diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index cbd2343a3c..fd5c86b3ca 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -167,14 +167,16 @@ layout="topleft" name="ModerateVoiceMuteSelected"> <on_click function="Avatar.DoToSelected" parameter="selected" /> - <on_visible function="Avatar.EnableItem" parameter="can_mute" /> + <on_enable function="Avatar.EnableItem" parameter="can_mute" /> + <on_visible function="Avatar.VisibleItem" parameter="show_mute" /> </menu_item_call> <menu_item_call label="Unmute this participant" layout="topleft" name="ModerateVoiceUnMuteSelected"> <on_click function="Avatar.DoToSelected" parameter="selected" /> - <on_visible function="Avatar.EnableItem" parameter="can_unmute" /> + <on_enable function="Avatar.EnableItem" parameter="can_unmute" /> + <on_visible function="Avatar.VisibleItem" parameter="show_unmute" /> </menu_item_call> <menu_item_call label="Mute everyone" -- cgit v1.2.3 From a33104ec5522352e23cdb788c003f830cd03cc1a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 12 Feb 2013 19:26:24 -0800 Subject: CHUI-695: Viewer crash when accepting friend offer in conversations window. Problem was that LLIMToastNotifyPanel::snapToMessageHeight was calling LLToastPanel::reshape, which would then call LLIMToastNotifyPanel::reshape again. Resolution: Modified LLIMToastNotifyPanel::snapToMessageHeight to cleanly replicate what LLToastPanel::reshape was doing. --- indra/newview/lltoastnotifypanel.cpp | 22 +++++++++++++++++++++- indra/newview/lltoastnotifypanel.h | 3 +++ indra/newview/lltoastpanel.cpp | 33 ++++++++++++++++++++------------- indra/newview/lltoastpanel.h | 1 + 4 files changed, 45 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 3fd056ea31..c5a8d85392 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -426,7 +426,27 @@ LLIMToastNotifyPanel::~LLIMToastNotifyPanel() void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) { LLToastPanel::reshape(width, height, called_from_parent); - snapToMessageHeight(mTextBox, MAX_LENGTH); + snapToMessageHeight(); +} + +void LLIMToastNotifyPanel::snapToMessageHeight() +{ + if(!mTextBox) + { + return; + } + + //Add message height if it is visible + if (mTextBox->getVisible()) + { + S32 new_panel_height = computeSnappedToMessageHeight(mTextBox, MAX_LENGTH); + + //reshape the panel with new height + if (new_panel_height != getRect().getHeight()) + { + LLToastNotifyPanel::reshape( getRect().getWidth(), new_panel_height); + } + } } void LLIMToastNotifyPanel::compactButtons() diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index f93c7745af..d02171b512 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -157,6 +157,9 @@ public: protected: LLTextBase* mParentText; LLUUID mSessionID; + +private: + void snapToMessageHeight(); }; #endif /* LLTOASTNOTIFYPANEL_H_ */ diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index 187aee207c..a30f841980 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -58,6 +58,25 @@ const LLUUID& LLToastPanel::getID() return mNotification->id(); } +S32 LLToastPanel::computeSnappedToMessageHeight(LLTextBase* message, S32 maxLineCount) +{ + S32 heightDelta = 0; + S32 maxTextHeight = message->getFont()->getLineHeight() * maxLineCount; + + LLRect messageRect = message->getRect(); + S32 oldTextHeight = messageRect.getHeight(); + + //Knowing the height is set to max allowed, getTextPixelHeight returns needed text height + //Perhaps we need to pass maxLineCount as parameter to getTextPixelHeight to avoid previous reshape. + S32 requiredTextHeight = message->getTextBoundingRect().getHeight(); + S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); + + heightDelta = newTextHeight - oldTextHeight; + S32 new_panel_height = llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT); + + return new_panel_height; +} + //snap to the message height if it is visible void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount) { @@ -69,19 +88,7 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount) //Add message height if it is visible if (message->getVisible()) { - S32 heightDelta = 0; - S32 maxTextHeight = message->getFont()->getLineHeight() * maxLineCount; - - LLRect messageRect = message->getRect(); - S32 oldTextHeight = messageRect.getHeight(); - - //Knowing the height is set to max allowed, getTextPixelHeight returns needed text height - //Perhaps we need to pass maxLineCount as parameter to getTextPixelHeight to avoid previous reshape. - S32 requiredTextHeight = message->getTextBoundingRect().getHeight(); - S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); - - heightDelta = newTextHeight - oldTextHeight; - S32 new_panel_height = llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT); + S32 new_panel_height = computeSnappedToMessageHeight(message, maxLineCount); //reshape the panel with new height if (new_panel_height != getRect().getHeight()) diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h index c22557206b..e4ab95007e 100644 --- a/indra/newview/lltoastpanel.h +++ b/indra/newview/lltoastpanel.h @@ -59,6 +59,7 @@ public: protected: LLNotificationPtr mNotification; void snapToMessageHeight(LLTextBase* message, S32 maxLineCount); + S32 computeSnappedToMessageHeight(LLTextBase* message, S32 maxLineCount); }; #endif /* LL_TOASTPANEL_H */ -- cgit v1.2.3 From 5f08b0553328c3811eb7de3390d2b92a193294c8 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 13 Feb 2013 12:10:21 +0200 Subject: CHUI-743 FIXED CHUI viewer ignores pre chui users Privacy settings to not keep IM logs and nearby chat logs --- indra/newview/app_settings/settings_per_account.xml | 11 ----------- indra/newview/llstartup.cpp | 7 +++++++ 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 0b589e2da6..363713f2f4 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -176,17 +176,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>LogInstantMessages</key> - <map> - <key>Comment</key> - <string>Log Instant Messages</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>LogShowHistory</key> <map> <key>Comment</key> diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index ab86f752c1..37e6ded986 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -917,6 +917,13 @@ bool idle_startup() // Overwrite default user settings with user settings LLAppViewer::instance()->loadSettingsFromDirectory("Account"); + // Convert 'LogInstantMessages' into 'KeepConversationLogTranscripts' for backward compatibility (CHUI-743). + LLControlVariablePtr logInstantMessagesControl = gSavedPerAccountSettings.getControl("LogInstantMessages"); + if (logInstantMessagesControl.notNull()) + { + gSavedPerAccountSettings.setS32("KeepConversationLogTranscripts", logInstantMessagesControl->getValue() ? 2 : 1); + } + // Need to set the LastLogoff time here if we don't have one. LastLogoff is used for "Recent Items" calculation // and startup time is close enough if we don't have a real value. if (gSavedPerAccountSettings.getU32("LastLogoff") == 0) -- cgit v1.2.3 From f8e43b6f6682eb613b0dc1f257b47008c09cd7f1 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Wed, 13 Feb 2013 15:08:49 +0200 Subject: CHUI-765 FIXED User's name is added to the list in Nearby tab. --- indra/newview/llpanelpeople.cpp | 4 ++++ indra/newview/llpanelpeoplemenus.cpp | 9 +++++++++ indra/newview/llworld.cpp | 2 +- indra/newview/skins/default/xui/en/menu_people_nearby.xml | 15 +++++++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 90e857265d..6667706333 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -1032,6 +1032,10 @@ void LLPanelPeople::onAvatarListDoubleClicked(LLUICtrl* ctrl) } LLUUID clicked_id = item->getAvatarId(); + if(gAgent.getID() == clicked_id) + { + return; + } #if 0 // SJB: Useful for testing, but not currently functional or to spec LLAvatarActions::showProfile(clicked_id); diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index 899771f3b9..61e9468ce5 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -99,6 +99,10 @@ LLContextMenu* NearbyMenu::createMenu() bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) { + if(gAgent.getID() == mUUIDs.front()) + { + return false; + } std::string item = userdata.asString(); // Note: can_block and can_delete is used only for one person selected menu @@ -176,6 +180,11 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) { return LLAvatarActions::canOfferTeleport(mUUIDs); } + else if (item == std::string("can_im") || item == std::string("can_callog") || item == std::string("can_invite") || + item == std::string("can_share") || item == std::string("can_pay")) + { + return true; + } return false; } diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 09d17b3701..793becf0c8 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -1192,7 +1192,7 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi { LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter; - if (!pVOAvatar->isDead() && !pVOAvatar->isSelf() && !pVOAvatar->mIsDummy) + if (!pVOAvatar->isDead() && !pVOAvatar->mIsDummy) { LLVector3d pos_global = pVOAvatar->getPositionGlobal(); LLUUID uuid = pVOAvatar->getID(); diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index 8014e81469..60a6c98514 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -15,6 +15,9 @@ name="IM"> <menu_item_call.on_click function="Avatar.IM" /> + <menu_item_call.on_enable + function="Avatar.EnableItem" + parameter="can_im"/> </menu_item_call> <menu_item_call label="Offer Teleport" @@ -42,6 +45,9 @@ name="Chat history"> <menu_item_call.on_click function="Avatar.Calllog" /> + <menu_item_call.on_enable + function="Avatar.EnableItem" + parameter="can_callog"/> </menu_item_call> <menu_item_separator /> <menu_item_call @@ -70,6 +76,9 @@ name="Invite"> <menu_item_call.on_click function="Avatar.InviteToGroup" /> + <menu_item_call.on_enable + function="Avatar.EnableItem" + parameter="can_invite"/> </menu_item_call> <menu_item_separator /> <menu_item_call @@ -88,6 +97,9 @@ name="Share"> <menu_item_call.on_click function="Avatar.Share" /> + <menu_item_call.on_enable + function="Avatar.EnableItem" + parameter="can_share"/> </menu_item_call> <menu_item_call label="Pay" @@ -95,6 +107,9 @@ name="Pay"> <menu_item_call.on_click function="Avatar.Pay" /> + <menu_item_call.on_enable + function="Avatar.EnableItem" + parameter="can_pay"/> </menu_item_call> <menu_item_check label="Block/Unblock" -- cgit v1.2.3 From ab6eca089e2d2a0dceba284ba68eba16fcf2a875 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Wed, 13 Feb 2013 15:14:15 +0200 Subject: CHUI-737 FIXED Reselect current conversation when floater is opened. --- indra/newview/llfloaterimcontainer.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index cef45a5b56..869e5992ca 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -259,6 +259,7 @@ void LLFloaterIMContainer::onOpen(const LLSD& key) { LLMultiFloater::onOpen(key); openNearbyChat(); + reSelectConversation(); assignResizeLimits(); } -- cgit v1.2.3 From ca676a7175405495aa10a55586fab4dc5dcc6476 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Wed, 13 Feb 2013 19:05:40 +0200 Subject: CHUI-761 FIXED Clear log button will not clear transcripts. --- indra/newview/llconversationlog.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 15d61e978d..22277e6421 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -532,7 +532,6 @@ void LLConversationLog::onClearLogResponse(const LLSD& notification, const LLSD& { if (0 == LLNotificationsUtil::getSelectedOption(notification, response)) { - LLLogChat::deleteTranscripts(); mConversations.clear(); notifyObservers(); } -- cgit v1.2.3 From a9f7c0089fe0a94879e5a9ad31cd6f8b5fb51c36 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Wed, 13 Feb 2013 19:12:25 +0200 Subject: CHUI-769 FIXED The text of the dialog is changed. --- indra/newview/skins/default/xui/en/notifications.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index f8a35337ed..3ae9b206a4 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -10006,7 +10006,7 @@ Cannot create large prims that intersect other players. Please re-try when othe icon="alertmodal.tga" name="PreferenceChatClearLog" type="alertmodal"> - This will delete the log of previous conversations, and all transcripts of those conversations. Proceed? + This will delete the log of previous conversations. Proceed? <tag>confirm</tag> <usetemplate ignoretext="Confirm before I delete the log of previous conversations." @@ -10019,7 +10019,7 @@ Cannot create large prims that intersect other players. Please re-try when othe icon="alertmodal.tga" name="PreferenceChatDeleteTranscripts" type="alertmodal"> - This will delete transcripts for all previous conversations. The list of conversations will not be affected. Proceed? + This will delete transcripts for all previous conversations. The list of conversations will not be affected. If you run scripts on your chat transcript files, you may want to proceed with caution. Proceed? <tag>confirm</tag> <usetemplate ignoretext="Confirm before I delete transcripts." -- cgit v1.2.3 From a536cf5f4b3a850ebcab566b814c39ed9da03ceb Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 14 Feb 2013 17:44:43 +0200 Subject: CHUI-771 Fixed! Conversation not scrolled to in conversation list when clicking on toast: add scrolling to selected widget --- indra/newview/llfloaterimcontainer.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 21bd8ab1d2..4a19440caa 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1345,6 +1345,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool if (widget && widget->getParentFolder()) { widget->getParentFolder()->setSelection(widget, FALSE, FALSE); + mConversationsRoot->scrollToShowSelection(); } //When in DND mode, remove stored IM notifications -- cgit v1.2.3 From c7cac7896ee4ccdd71dad432f1314b85987e78cf Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 13 Feb 2013 20:44:38 +0200 Subject: CHUI-739 Fixed! FUI toolbars not displayed when switching between CHUI and release viewer : parsing declare values of Enums --- indra/llcommon/llinitparam.h | 26 +++++++++++++++++++++----- indra/newview/lltoolbarview.cpp | 8 +++++--- 2 files changed, 26 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index 75c87c4bdb..695403e3f4 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -439,7 +439,7 @@ namespace LLInitParam {} void operator ()(const std::string& name) - { + { *this = name; } @@ -516,14 +516,30 @@ namespace LLInitParam { static bool read(T& param, Parser* parser) { - // read all enums as ints + std::string value_string; + //TypeValues<T>::value_t v; + + // trying to get the declare value + parser_read_func_map_t::iterator string_func = parser->mParserReadFuncs->find(&typeid(std::string)); + if (string_func != parser->mParserReadFuncs->end()) + { + if (string_func->second(*parser, (void*)&value_string)) + { + if (TypeValues<T>::getValueFromName(value_string, param)) + { + return true; + } + } + } + + // read enums as ints if it not declared as string parser_read_func_map_t::iterator found_it = parser->mParserReadFuncs->find(&typeid(S32)); if (found_it != parser->mParserReadFuncs->end()) { - S32 value; - if (found_it->second(*parser, (void*)&value)) + S32 value_S32; + if (found_it->second(*parser, (void*)&value_S32)) { - param = (T)value; + param = (T)value_S32; return true; } } diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp index de07ad510b..b2318f9158 100644 --- a/indra/newview/lltoolbarview.cpp +++ b/indra/newview/lltoolbarview.cpp @@ -241,8 +241,9 @@ bool LLToolBarView::loadToolbars(bool force_default) LLXUIParser parser; if (!err) { - parser.readXUI(root, toolbar_set, toolbar_file); + parser.readXUI(root, toolbar_set, toolbar_file); } + if (!err && !toolbar_set.validateBlock()) { llwarns << "Unable to validate toolbars from file: " << toolbar_file << llendl; @@ -254,8 +255,9 @@ bool LLToolBarView::loadToolbars(bool force_default) if (force_default) { llerrs << "Unable to load toolbars from default file : " << toolbar_file << llendl; - return false; - } + return false; + } + // Try to load the default toolbars return loadToolbars(true); } -- cgit v1.2.3 From 2f49f5ed0e03375df97c877f139f2283f1a1376d Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 13 Feb 2013 15:35:23 -0800 Subject: CHUI-770 : Fixed! Need to use the User Name and not the Account Name to save the favorites. --- indra/newview/llfavoritesbar.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index ba3d4036c9..e30dd51acb 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -1520,8 +1520,10 @@ void LLFavoritesOrderStorage::saveFavoritesSLURLs() LLAvatarName av_name; LLAvatarNameCache::get( gAgentID, &av_name ); - lldebugs << "Saved favorites for " << av_name.getAccountName() << llendl; - fav_llsd[av_name.getAccountName()] = user_llsd; + // Note : use the "John Doe" and not the "john.doe" version of the name + // as we'll compare it with the stored credentials in the login panel. + lldebugs << "Saved favorites for " << av_name.getUserName() << llendl; + fav_llsd[av_name.getUserName()] = user_llsd; llofstream file; file.open(filename); @@ -1539,10 +1541,12 @@ void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() LLAvatarName av_name; LLAvatarNameCache::get( gAgentID, &av_name ); - lldebugs << "Removed favorites for " << av_name.getAccountName() << llendl; - if (fav_llsd.has(av_name.getAccountName())) + // Note : use the "John Doe" and not the "john.doe" version of the name. + // See saveFavoritesSLURLs() here above for the reason why. + lldebugs << "Removed favorites for " << av_name.getUserName() << llendl; + if (fav_llsd.has(av_name.getUserName())) { - fav_llsd.erase(av_name.getAccountName()); + fav_llsd.erase(av_name.getUserName()); } llofstream out_file; -- cgit v1.2.3 From 30248c2049f6e20fa20e5b9f61cbd1402905d9b8 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 13 Feb 2013 17:01:26 -0800 Subject: CHUI-695: When the 'Accept' button is pressed the toast panel will be resized to the conversation floater dimensions after all buttons and text has been added to the toast panel --- indra/newview/lltoastnotifypanel.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index c5a8d85392..4ef5ad845c 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -259,12 +259,6 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) setXMLFilename(""); buildFromFile("panel_notification.xml"); - // reshape the panel to its previous size - if (current_rect.notEmpty()) - { - reshape(current_rect.getWidth(), current_rect.getHeight()); - } - if(rect != LLRect::null) { this->setShape(rect); @@ -407,6 +401,12 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) //can shift upward making room for the buttons inside mControlPanel. After the buttons are added, the info panel can then be set to follow 'all'. mInfoPanel->setFollowsAll(); snapToMessageHeight(mTextBox, MAX_LENGTH); + + // reshape the panel to its previous size + if (current_rect.notEmpty()) + { + reshape(current_rect.getWidth(), current_rect.getHeight()); + } } ////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 638d94eef75799d47f8b913e0909b4079e55c03b Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 14 Feb 2013 18:51:13 +0200 Subject: CHUI-739 : Clean up : FUI toolbars not displayed when switching between CHUI and release viewer --- indra/llcommon/llinitparam.h | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index 695403e3f4..eb4d84d835 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -517,7 +517,6 @@ namespace LLInitParam static bool read(T& param, Parser* parser) { std::string value_string; - //TypeValues<T>::value_t v; // trying to get the declare value parser_read_func_map_t::iterator string_func = parser->mParserReadFuncs->find(&typeid(std::string)); -- cgit v1.2.3 From 96bc3d206d890255300d367a70493f93cd0dc5f8 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 14 Feb 2013 17:27:05 -0800 Subject: CHUI-753 : Fixed (temptative) : Added some defensive coding in bringToFront() to make safer or avoid pointer casting. --- indra/llui/llfloater.cpp | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 05b2a1b7c6..734e2cfda7 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2357,7 +2357,6 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) { if (mFrontChild == child) { - if (give_focus && !gFocusMgr.childHasKeyboardFocus(child)) { child->setFocus(TRUE); @@ -2374,15 +2373,14 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) // this floater is hosted elsewhere and hence not one of our children, abort return; } - std::vector<LLView*> floaters_to_move; + std::vector<LLFloater*> floaters_to_move; // Look at all floaters...tab - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + for (child_list_const_iter_t child_it = beginChild(); child_it != endChild(); ++child_it) { - LLView* viewp = *child_it; - LLFloater *floater = (LLFloater *)viewp; + LLFloater* floater = dynamic_cast<LLFloater*>(*child_it); // ...but if I'm a dependent floater... - if (child->isDependent()) + if (floater && child->isDependent()) { // ...look for floaters that have me as a dependent... LLFloater::handle_set_iter_t found_dependent = floater->mDependents.find(child->getHandle()); @@ -2390,15 +2388,14 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) if (found_dependent != floater->mDependents.end()) { // ...and make sure all children of that floater (including me) are brought to front... - for(LLFloater::handle_set_iter_t dependent_it = floater->mDependents.begin(); - dependent_it != floater->mDependents.end(); ) + for (LLFloater::handle_set_iter_t dependent_it = floater->mDependents.begin(); + dependent_it != floater->mDependents.end(); ++dependent_it) { LLFloater* sibling = dependent_it->get(); if (sibling) { floaters_to_move.push_back(sibling); } - ++dependent_it; } //...before bringing my parent to the front... floaters_to_move.push_back(floater); @@ -2406,10 +2403,10 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) } } - std::vector<LLView*>::iterator view_it; - for(view_it = floaters_to_move.begin(); view_it != floaters_to_move.end(); ++view_it) + std::vector<LLFloater*>::iterator floater_it; + for(floater_it = floaters_to_move.begin(); floater_it != floaters_to_move.end(); ++floater_it) { - LLFloater* floaterp = (LLFloater*)(*view_it); + LLFloater* floaterp = *floater_it; sendChildToFront(floaterp); // always unminimize dependee, but allow dependents to stay minimized @@ -2421,23 +2418,19 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) floaters_to_move.clear(); // ...then bringing my own dependents to the front... - for(LLFloater::handle_set_iter_t dependent_it = child->mDependents.begin(); - dependent_it != child->mDependents.end(); ) + for (LLFloater::handle_set_iter_t dependent_it = child->mDependents.begin(); + dependent_it != child->mDependents.end(); ++dependent_it) { LLFloater* dependent = dependent_it->get(); if (dependent) { sendChildToFront(dependent); - //don't un-minimize dependent windows automatically - // respect user's wishes - //dependent->setMinimized(FALSE); } - ++dependent_it; } // ...and finally bringing myself to front // (do this last, so that I'm left in front at end of this call) - if( *getChildList()->begin() != child ) + if (*beginChild() != child) { sendChildToFront(child); } -- cgit v1.2.3 From c0433f1460b5cd96c093e3955ecf4ddcb6376f92 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Fri, 15 Feb 2013 13:15:14 +0200 Subject: CHUI-774 Fixed condition of the checking. Also the sound for Teleport offer will be played correctly now. --- indra/newview/llnotificationofferhandler.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index cde7bb18ce..a2bd96f35a 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -120,11 +120,11 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) channel->addToast(p); //Will not play a notification sound for inventory and teleport offer based upon chat preference - bool playSound = !((notification->isDND()) - && (notification->getName() == "UserGiveItem" - && gSavedSettings.getBOOL("PlaySoundInventoryOffer") == FALSE) - || notification->getName() == "TeleportOffered" - && gSavedSettings.getBOOL("PlaySoundTeleportOffer") == FALSE); + bool playSound = (!notification->isDND() + && ((notification->getName() == "UserGiveItem" + && gSavedSettings.getBOOL("PlaySoundInventoryOffer")) + || (notification->getName() == "TeleportOffered" + && gSavedSettings.getBOOL("PlaySoundTeleportOffer")))); if(playSound) { -- cgit v1.2.3 From eb8611de12abebb30c4d4f1d418165486cd59faa Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Fri, 15 Feb 2013 13:27:37 +0200 Subject: CHUI-755 FIXED cache() is called to update conversation.log file after deleting conversations. --- indra/newview/llconversationlog.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 22277e6421..23a98fa136 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -333,6 +333,7 @@ void LLConversationLog::removeConversation(const LLConversation& conversation) { mConversations.erase(conv_it); notifyObservers(); + cache(); return; } } @@ -534,5 +535,6 @@ void LLConversationLog::onClearLogResponse(const LLSD& notification, const LLSD& { mConversations.clear(); notifyObservers(); + cache(); } } -- cgit v1.2.3 From 8c20b1e002e2056b27b3bc4613cf077a4a6d3774 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 14 Feb 2013 18:33:07 +0200 Subject: CHUI-773 Conversation line item does not flash for unselected conversation when Flash Toolbar Button preference is selected: add flashing in "toast" case when session floater is open but not selected --- indra/newview/llimview.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cdf6cb6252..cf6a215970 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -213,16 +213,14 @@ void on_new_message(const LLSD& msg) //conversation floater not focused (visible or not) bool conversation_floater_not_focused = conversation_floater_is_closed || !im_box->hasFocus(); - - // Skip toasting and flashing if we have open window of IM with this session id - if (session_floater - && session_floater->isInVisibleChain() - && !session_floater->isMinimized() - && !(session_floater->getHost() && session_floater->getHost()->isMinimized())) - { - return; - } - if ("toast" == action) + // sess. floater is open + bool session_floater_is_open = + session_floater + && session_floater->isInVisibleChain() + && !session_floater->isMinimized() + && !(session_floater->getHost() && session_floater->getHost()->isMinimized()); + + if ("toast" == action && !session_floater_is_open) { //User is not focused on conversation containing the message if(session_floater_not_focused) @@ -254,7 +252,7 @@ void on_new_message(const LLSD& msg) { if (conversation_floater_not_focused) { - if(session_floater_not_focused && !gAgent.isDoNotDisturb()) + if(!session_floater_is_open && !gAgent.isDoNotDisturb()) { //User is not focused on conversation containing the message gToolBarView->flashCommand(LLCommandId("chat"), true); @@ -273,7 +271,7 @@ void on_new_message(const LLSD& msg) } } - else if("openconversations" == action) + else if("openconversations" == action && !session_floater_is_open) { //User is not focused on conversation containing the message if(session_floater_not_focused) -- cgit v1.2.3 From fdd55c279e303ffe86d715c697db595c89071703 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Mon, 18 Feb 2013 14:59:03 +0200 Subject: CHUI-742 FIXED Do not update Log locations immediately after selecting a new location. --- indra/newview/llfloaterpreference.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 662d2df5d2..b1b22efc56 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1446,7 +1446,6 @@ void LLFloaterPreference::onClickLogPath() std::string dir_name = picker.getDirName(); gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); - updateLogLocation(dir_name); // enable/disable 'Delete transcripts button updateDeleteTranscriptsButton(); -- cgit v1.2.3 From 7f63b36977107f5bbfc1a1682cb91fea3985fef4 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Mon, 18 Feb 2013 15:01:36 +0200 Subject: CHUI-775 FIXED We should always handle changing of preferences. --- indra/newview/llconversationlog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 23a98fa136..fc3bc8551c 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -192,11 +192,11 @@ LLConversationLog::LLConversationLog() : { LLControlVariable * keep_log_ctrlp = gSavedPerAccountSettings.getControl("KeepConversationLogTranscripts").get(); S32 log_mode = keep_log_ctrlp->getValue(); - + keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); if (log_mode > 0) { loadFromFile(getFileName()); - keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); + enableLogging(log_mode); } } -- cgit v1.2.3 From 2928789484c9eb88e9970af1ce5d5e42320c97bd Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 15 Feb 2013 22:35:25 +0200 Subject: CHUI-767 First click on << icon in a session to collapse message panel has no action : delete an obsolete (after the changeset 1cbf27ea0b4e) code --- indra/newview/llfloaterimcontainer.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 4a19440caa..2f2b09b589 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -639,11 +639,7 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse) return; } - if (mIsFirstLaunch) - { - mIsFirstLaunch = false; - return; - } + mIsFirstLaunch = false; // Save current width of panels before collapsing/expanding right pane. S32 conv_pane_width = mConversationsPane->getRect().getWidth(); -- cgit v1.2.3 From e4ea94b62226aebb4408360a033b2c1c71aa4ef6 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Mon, 18 Feb 2013 18:56:22 +0200 Subject: CHUI-779 FIXED Chat log preferences are disabled before login. --- indra/newview/llfloaterpreference.cpp | 1 + indra/newview/skins/default/xui/en/panel_preferences_chat.xml | 2 ++ 2 files changed, 3 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index b1b22efc56..3d8d0e15ec 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1491,6 +1491,7 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im getChildView("favorites_on_login_check")->setEnabled(TRUE); getChildView("log_path_string")->setEnabled(FALSE);// LineEditor becomes readonly in this case. getChildView("log_path_button")->setEnabled(TRUE); + getChildView("chat_font_size")->setEnabled(TRUE); } void LLFloaterPreference::onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name) diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 9b22c8c6dd..9db3816c92 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -373,6 +373,7 @@ </text> <combo_box + enabled="false" control_name="KeepConversationLogTranscripts" height="23" layout="topleft" @@ -428,6 +429,7 @@ </text> <line_editor + enabled="false" control_name="InstantMessageLogPath" border_style="line" border_thickness="1" -- cgit v1.2.3 From 45849294cefd33c4875b5fe5b3fc8f04745452cf Mon Sep 17 00:00:00 2001 From: Richard Linden <none@none> Date: Mon, 18 Feb 2013 20:30:22 -0800 Subject: CHUI-739 FIX FUI toolbars not displayed when switching between CHUI and release viewer param blocks no longer write enums as ints --- indra/llcommon/llinitparam.h | 94 +++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 59 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index 75c87c4bdb..66aac4f549 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -485,62 +485,6 @@ namespace LLInitParam typedef std::map<const std::type_info*, parser_write_func_t> parser_write_func_map_t; typedef std::map<const std::type_info*, parser_inspect_func_t> parser_inspect_func_map_t; - private: - template<typename T, bool is_enum = boost::is_enum<T>::value> - struct ReaderWriter - { - static bool read(T& param, Parser* parser) - { - parser_read_func_map_t::iterator found_it = parser->mParserReadFuncs->find(&typeid(T)); - if (found_it != parser->mParserReadFuncs->end()) - { - return found_it->second(*parser, (void*)¶m); - } - return false; - } - - static bool write(const T& param, Parser* parser, name_stack_t& name_stack) - { - parser_write_func_map_t::iterator found_it = parser->mParserWriteFuncs->find(&typeid(T)); - if (found_it != parser->mParserWriteFuncs->end()) - { - return found_it->second(*parser, (const void*)¶m, name_stack); - } - return false; - } - }; - - // read enums as ints - template<typename T> - struct ReaderWriter<T, true> - { - static bool read(T& param, Parser* parser) - { - // read all enums as ints - parser_read_func_map_t::iterator found_it = parser->mParserReadFuncs->find(&typeid(S32)); - if (found_it != parser->mParserReadFuncs->end()) - { - S32 value; - if (found_it->second(*parser, (void*)&value)) - { - param = (T)value; - return true; - } - } - return false; - } - - static bool write(const T& param, Parser* parser, name_stack_t& name_stack) - { - parser_write_func_map_t::iterator found_it = parser->mParserWriteFuncs->find(&typeid(S32)); - if (found_it != parser->mParserWriteFuncs->end()) - { - return found_it->second(*parser, (const void*)¶m, name_stack); - } - return false; - } - }; - public: Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map) @@ -552,14 +496,46 @@ namespace LLInitParam virtual ~Parser(); - template <typename T> bool readValue(T& param) + template <typename T> bool readValue(T& param, typename boost::disable_if<boost::is_enum<T> >::type* dummy = 0) { - return ReaderWriter<T>::read(param, this); + parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); + if (found_it != mParserReadFuncs->end()) + { + return found_it->second(*this, (void*)¶m); + } + + return false; } + template <typename T> bool readValue(T& param, typename boost::enable_if<boost::is_enum<T> >::type* dummy = 0) + { + parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); + if (found_it != mParserReadFuncs->end()) + { + return found_it->second(*this, (void*)¶m); + } + else + { + found_it = mParserReadFuncs->find(&typeid(S32)); + if (found_it != mParserReadFuncs->end()) + { + S32 int_value; + bool parsed = found_it->second(*this, (void*)&int_value); + param = (T)int_value; + return parsed; + } + } + return false; + } + template <typename T> bool writeValue(const T& param, name_stack_t& name_stack) { - return ReaderWriter<T>::write(param, this, name_stack); + parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T)); + if (found_it != mParserWriteFuncs->end()) + { + return found_it->second(*this, (const void*)¶m, name_stack); + } + return false; } // dispatch inspection to registered inspection functions, for each parameter in a param block -- cgit v1.2.3 From 927fcf5d0b6eac067e40ac415b3a5ce10dbc4903 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 18 Feb 2013 16:36:55 +0200 Subject: CHUI-768 Conversation panel resize issue with message panel collapsed : manually resize of the conversations panel --- indra/newview/llfloaterimcontainer.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 2f2b09b589..c1959729d1 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -535,6 +535,13 @@ void LLFloaterIMContainer::draw() setTitle(conversation_floaterp && conversation_floaterp->needsTitleOverwrite() ? conversation_floaterp->getTitle() : mGeneralTitle); } + // "Manually" resize of mConversationsPane: same as temporarity cancellation of the flag "auto_resize=false" for it + if (!mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed()) + { + LLRect stack_rect = mConversationsStack->getRect(); + mConversationsPane->reshape(stack_rect.getWidth(), stack_rect.getHeight(), true); + } + LLFloater::draw(); } @@ -654,6 +661,8 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse) gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", mConversationsPane->isCollapsed()); } + mConversationsPane->setIgnoreReshape(collapse); + // Show/hide the messages pane. mConversationsStack->collapsePanel(mMessagesPane, collapse); -- cgit v1.2.3 From 7b2cbf254ae102738d9e7b41e9cec55a867ec755 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Tue, 19 Feb 2013 15:45:36 +0200 Subject: CHUI-702 FIXED Call requestArrange() after showing Voice indicator to avoid overlapping. --- indra/newview/llconversationview.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 5ff013ccc4..5ac6353daa 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -340,6 +340,7 @@ LLConversationViewParticipant* LLConversationViewSession::findParticipant(const void LLConversationViewSession::showVoiceIndicator(bool visible) { mCallIconLayoutPanel->setVisible(visible && LLVoiceChannel::getCurrentVoiceChannel()->getSessionID().isNull()); + requestArrange(); } void LLConversationViewSession::refresh() -- cgit v1.2.3 From 50d50019d8b8350bc7b04b0b49c6107cde62f4b0 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Mon, 18 Feb 2013 20:02:43 +0200 Subject: CHUI-729 FIXED Messages pane displays incorrect after changing size and relogin --- indra/llui/llfloater.h | 2 +- indra/newview/llfloaterimcontainer.cpp | 14 ++++++++++++++ indra/newview/llfloaterimcontainer.h | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index a6a85fc7d1..157b9b0113 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -224,7 +224,7 @@ public: void openFloater(const LLSD& key = LLSD()); // If allowed, close the floater cleanly, releasing focus. - void closeFloater(bool app_quitting = false); + virtual void closeFloater(bool app_quitting = false); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c1959729d1..86d205a920 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1851,4 +1851,18 @@ void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, } } +void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/) +{ + // Always unminimize before trying to close. + // Most of the time the user will never see this state. + setMinimized(FALSE); + + S32 conv_pane_width = mConversationsPane->getRect().getWidth(); + + // Save the conversations pane width before collapsing it. + gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", conv_pane_width); + + LLFloater::closeFloater(app_quitting); +} + // EOF diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 265ae8df4c..569fa9faab 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -109,6 +109,8 @@ public: void assignResizeLimits(); + /*virtual*/ void closeFloater(bool app_quitting = false); + private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; avatarID_panel_map_t mSessions; -- cgit v1.2.3 From becf7f8b605dfde99045e48274cb4cb3107443f5 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Tue, 19 Feb 2013 23:34:34 +0200 Subject: CHUI-729 FIXED Messages pane displays incorrect after changing size and relogin --- indra/newview/llfloaterimcontainer.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 86d205a920..5213413aea 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -230,12 +230,10 @@ BOOL LLFloaterIMContainer::postBuild() mMicroChangedSignal = LLVoiceClient::getInstance()->MicroChangedCallback(boost::bind(&LLFloaterIMContainer::updateSpeakBtnState, this)); if (! mMessagesPane->isCollapsed()) { - S32 list_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"); - LLRect list_size = mConversationsPane->getRect(); - S32 left_pad = mConversationsListPanel->getRect().mLeft; - list_size.mRight = list_size.mLeft + list_width - left_pad; - - mConversationsPane->handleReshape(list_size, TRUE); + S32 conversations_panel_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"); + LLRect conversations_panel_rect = mConversationsPane->getRect(); + conversations_panel_rect.mRight = conversations_panel_rect.mLeft + conversations_panel_width; + mConversationsPane->handleReshape(conversations_panel_rect, TRUE); } // Init the sort order now that the root had been created -- cgit v1.2.3 From 3ae9124ce555dada3d14ede28a6658cddcfa53b8 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 20 Feb 2013 19:06:49 -0800 Subject: CHUI-395 : Fixed! Check the moderator status in the group data when loading the group list --- indra/newview/llspeakers.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index a2d8874cea..05df7261e1 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -557,7 +557,8 @@ void LLSpeakerMgr::updateSpeakerList() // Add only the members who are online if (member->getOnlineStatus() == "Online") { - setSpeaker(member_it->first, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + LLPointer<LLSpeaker> speakerp = setSpeaker(member_it->first, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + speakerp->mIsModerator = ((member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR); } ++member_it; } -- cgit v1.2.3 From c48e644220ad1708a93987faf9ac96bcdd097dec Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 20 Feb 2013 17:11:50 +0200 Subject: CHUI-773 ADD FIX Conversation line item does not flash for unselected conversation when Flash Toolbar Button preference is selected : repair case "open and not on top" --- indra/newview/llimview.cpp | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cf6a215970..d69bd89f13 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -199,8 +199,14 @@ void on_new_message(const LLSD& msg) // execution of the action LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); - LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); + if (im_box->isFrontmost() && im_box->getSelectedSession() == session_id) + { + return; + } + + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); + //session floater not focused (visible or not) bool session_floater_not_focused = session_floater && !session_floater->hasFocus(); @@ -250,25 +256,21 @@ void on_new_message(const LLSD& msg) else if ("flash" == action) { - if (conversation_floater_not_focused) + if (!gAgent.isDoNotDisturb()) { - if(!session_floater_is_open && !gAgent.isDoNotDisturb()) - { - //User is not focused on conversation containing the message - gToolBarView->flashCommand(LLCommandId("chat"), true); - } - - im_box->flashConversationItemWidget(session_id, true); - - //If a DND message, allow notification to be stored so upon DND exit - //useMostItrusiveIMNotification will be called to notify user a message exists - if(session_id.notNull() - && participant_id.notNull() - && gAgent.isDoNotDisturb()) - { - LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); - } - } + im_box->flashConversationItemWidget(session_id, true); + if(conversation_floater_not_focused) + { + //User is not focused on conversation containing the message + gToolBarView->flashCommand(LLCommandId("chat"), true); + } + } + else if(session_id.notNull() && participant_id.notNull()) + { + //If a DND message, allow notification to be stored so upon DND exit + //useMostItrusiveIMNotification will be called to notify user a message exists + LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); + } } else if("openconversations" == action && !session_floater_is_open) -- cgit v1.2.3 From 8ed2072aa25a99d1da6c18de990bf155e65dc1ca Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 20 Feb 2013 13:47:20 +0200 Subject: CHUI-768 ADD FIX Conversation panel resize issue with message panel collapse : correctly assign of a left panel resize limits --- indra/newview/llfloaterimcontainer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 5213413aea..72febcf431 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -758,7 +758,9 @@ void LLFloaterIMContainer::assignResizeLimits() // between the panels are merged into one S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3); S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH; - S32 conv_pane_current_width = is_conv_pane_expanded? mConversationsPane->getRect().getWidth() : mConversationsPane->getMinDim(); + S32 conv_pane_current_width = is_msg_pane_expanded + ? mConversationsPane->getRect().getWidth() + : (is_conv_pane_expanded? mConversationsPane->getExpandedMinDim() : mConversationsPane->getMinDim()); S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0; S32 new_min_width = conv_pane_current_width + msg_pane_min_width + summary_width_of_visible_borders; -- cgit v1.2.3 From bfdd9b2e134110c7ed7b68925f78aac721e66905 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 19 Feb 2013 23:38:57 +0200 Subject: CHUI-756 Minimized chat opens when start new conversation : saving of the minimized state of an session floater --- indra/newview/llfloaterimcontainer.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 72febcf431..60e306eef4 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1384,7 +1384,9 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool // Set the focus on the selected floater if (!session_floater->hasFocus()) { + BOOL is_minimized = session_floater->isMinimized(); session_floater->setFocus(TRUE); + session_floater->setMinimized(is_minimized); } } -- cgit v1.2.3 From 4eba77e7db0b60a9d422409521162ef4cd541128 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 20 Feb 2013 01:17:58 +0200 Subject: CHUI-590 FIXED Put voice volume control back into avatar inspector. --- indra/newview/llinspectavatar.cpp | 100 +++++++++++++++++++++ .../skins/default/xui/en/inspect_avatar.xml | 30 ++++++- 2 files changed, 128 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 26d3a2bd12..1e15dc832c 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -28,13 +28,17 @@ #include "llinspectavatar.h" // viewer files +#include "llagent.h" +#include "llavataractions.h" #include "llavatariconctrl.h" #include "llavatarnamecache.h" #include "llavatarpropertiesprocessor.h" #include "lldateutil.h" #include "llinspect.h" +#include "llmutelist.h" #include "llslurl.h" #include "llstartup.h" +#include "llvoiceclient.h" #include "lltransientfloatermgr.h" // Linden libraries @@ -63,6 +67,8 @@ public: // Inspector will be positioned relative to current mouse position LLInspectAvatar(const LLSD& avatar_id); virtual ~LLInspectAvatar(); + + /*virtual*/ BOOL postBuild(void); // Because floater is single instance, need to re-parse data on each spawn // (for example, inspector about same avatar but in different position) @@ -77,6 +83,14 @@ private: // Make network requests for all the data to display in this view. // Used on construction and if avatar id changes. void requestUpdate(); + + // Set the volume slider to this user's current client-side volume setting, + // hiding/disabling if the user is not nearby. + void updateVolumeSlider(); + + // Button callbacks + void onClickMuteVolume(); + void onVolumeChange(const LLSD& data); void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); @@ -165,6 +179,18 @@ LLInspectAvatar::~LLInspectAvatar() LLTransientFloaterMgr::getInstance()->removeControlView(this); } +/*virtual*/ +BOOL LLInspectAvatar::postBuild(void) +{ + getChild<LLUICtrl>("mute_btn")->setCommitCallback( + boost::bind(&LLInspectAvatar::onClickMuteVolume, this) ); + + getChild<LLUICtrl>("volume_slider")->setCommitCallback( + boost::bind(&LLInspectAvatar::onVolumeChange, this, _2)); + + return TRUE; +} + // Multiple calls to showInstance("inspect_avatar", foo) will provide different // LLSD for foo, which we will catch here. //virtual @@ -193,6 +219,8 @@ void LLInspectAvatar::onOpen(const LLSD& data) // can't call from constructor as widgets are not built yet requestUpdate(); + + updateVolumeSlider(); } void LLInspectAvatar::requestUpdate() @@ -265,6 +293,78 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data) mPropertiesRequest = NULL; } +void LLInspectAvatar::updateVolumeSlider() +{ + bool voice_enabled = LLVoiceClient::getInstance()->getVoiceEnabled(mAvatarID); + + // Do not display volume slider and mute button if it + // is ourself or we are not in a voice channel together + if (!voice_enabled || (mAvatarID == gAgent.getID())) + { + getChild<LLUICtrl>("mute_btn")->setVisible(false); + getChild<LLUICtrl>("volume_slider")->setVisible(false); + } + + else + { + getChild<LLUICtrl>("mute_btn")->setVisible(true); + getChild<LLUICtrl>("volume_slider")->setVisible(true); + + // By convention, we only display and toggle voice mutes, not all mutes + bool is_muted = LLAvatarActions::isVoiceMuted(mAvatarID); + + LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); + + bool is_linden = LLStringUtil::endsWith(mAvatarName.getDisplayName(), " Linden"); + + mute_btn->setEnabled( !is_linden); + mute_btn->setValue( is_muted ); + + LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); + volume_slider->setEnabled( !is_muted ); + + F32 volume; + + if (is_muted) + { + // it's clearer to display their volume as zero + volume = 0.f; + } + else + { + // actual volume + volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); + } + volume_slider->setValue( (F64)volume ); + } + +} + +void LLInspectAvatar::onClickMuteVolume() +{ + // By convention, we only display and toggle voice mutes, not all mutes + LLMuteList* mute_list = LLMuteList::getInstance(); + bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat); + + LLMute mute(mAvatarID, mAvatarName.getDisplayName(), LLMute::AGENT); + if (!is_muted) + { + mute_list->add(mute, LLMute::flagVoiceChat); + } + else + { + mute_list->remove(mute, LLMute::flagVoiceChat); + } + + updateVolumeSlider(); +} + +void LLInspectAvatar::onVolumeChange(const LLSD& data) +{ + F32 volume = (F32)data.asReal(); + LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); +} + void LLInspectAvatar::onAvatarNameCache( const LLUUID& agent_id, const LLAvatarName& av_name) diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml index c3481e6d4c..ef4f19cd4c 100644 --- a/indra/newview/skins/default/xui/en/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml @@ -2,14 +2,14 @@ <!-- Not can_close / no title to avoid window chrome Single instance - only have one at a time, recycle it each spawn ---> +--> <floater legacy_header_height="25" bevel_style="in" bg_opaque_image="Inspector_Background" can_close="false" can_minimize="false" - height="130" + height="160" layout="topleft" name="inspect_avatar" single_instance="true" @@ -94,6 +94,32 @@ use_ellipses="true" width="220">This is my second life description and I really think it is great. But for some reason my description is super extra long because I like to talk a whole lot </text> + <slider + follows="top|left" + height="23" + increment="0.01" + left="10" + max_val="0.95" + min_val="0.05" + name="volume_slider" + show_text="false" + tool_tip="Voice volume" + top_pad="5" + value="0.5" + width="200" /> + <button + follows="top|left" + height="16" + image_disabled="Audio_Off" + image_disabled_selected="AudioMute_Off" + image_hover_selected="AudioMute_Over" + image_selected="AudioMute_Off" + image_unselected="Audio_Off" + is_toggle="true" + left_pad="5" + top_delta="4" + name="mute_btn" + width="16" /> <text follows="top|left" height="16" -- cgit v1.2.3 From 61c1b2fe2bde94a5f77597725e446a5345219ebe Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 19 Feb 2013 16:38:22 -0800 Subject: CHUI-778 (Saving preferences updates text in all open message panels in conversation floater to show as old messages) Problem was that closing the preferences floater was always acting as if the conversation transcripts/log files path had changed. If the path did not change then the user's conversations would be cleared and re-loaded as if they were part of the user's history (causing text to be grey). Solution: Now keep track of when the path was changed and only load up the transcripts/log upon change. --- indra/newview/llfloaterpreference.cpp | 28 ++++++++++++++++++++-------- indra/newview/llfloaterpreference.h | 1 + 2 files changed, 21 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 3d8d0e15ec..b3e3a0678b 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -647,8 +647,12 @@ void LLFloaterPreference::cancel() pPathfindingConsole->onRegionBoundaryCross(); } - std::string dir_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); - updateLogLocation(dir_name); + if(mInstantMessageLogPathChanged) + { + std::string dir_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); + updateLogLocation(dir_name); + mInstantMessageLogPathChanged = false; + } } void LLFloaterPreference::onOpen(const LLSD& key) @@ -1436,19 +1440,27 @@ void LLFloaterPreference::setAllIgnored() void LLFloaterPreference::onClickLogPath() { - std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); + std::string original_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); + std::string proposed_name(original_name); + mInstantMessageLogPathChanged = false; LLDirPicker& picker = LLDirPicker::instance(); + //Launches a directory picker and waits for feedback if (!picker.getDir(&proposed_name ) ) { return; //Canceled! } - std::string dir_name = picker.getDirName(); - gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); - - // enable/disable 'Delete transcripts button - updateDeleteTranscriptsButton(); + //Path changed + if(original_name != proposed_name) + { + std::string dir_name = picker.getDirName(); + gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); + mInstantMessageLogPathChanged = true; + + // enable/disable 'Delete transcripts button + updateDeleteTranscriptsButton(); + } } void LLFloaterPreference::updateLogLocation(const std::string& dir_name) diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index dbd87f74a1..c72346c3b6 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -186,6 +186,7 @@ private: bool mGotPersonalInfo; bool mOriginalIMViaEmail; bool mLanguageChanged; + bool mInstantMessageLogPathChanged; bool mAvatarDataInitialized; bool mOriginalHideOnlineStatus; -- cgit v1.2.3 From 2dfdd050d487df6aaa7a169208e02b30a313127f Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 20 Feb 2013 16:47:54 +0200 Subject: CHUI-784 FIXED Crash when closing expanded group chat --- indra/newview/llfloaterimcontainer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 60e306eef4..c8088588da 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1526,10 +1526,10 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c if (widget) { is_widget_selected = widget->isSelected(); - new_selection = mConversationsRoot->getNextFromChild(widget); + new_selection = mConversationsRoot->getNextFromChild(widget, FALSE); if (!new_selection) { - new_selection = mConversationsRoot->getPreviousFromChild(widget); + new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE); } widget->destroyView(); } -- cgit v1.2.3 From 10dfe2d53413d2522038e79d4921a2305762dd63 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 20 Feb 2013 15:51:44 -0800 Subject: CHUI-778: Minor changes, prior commit was not changing the file path correctly due to logic error. Also clicking the 'Cancel' in preferences would still cause the file location to be saved instead of ignore the save. --- indra/newview/llfloaterpreference.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index b3e3a0678b..e5444583d6 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -646,13 +646,6 @@ void LLFloaterPreference::cancel() LLFloaterPathfindingConsole* pPathfindingConsole = pathfindingConsoleHandle.get(); pPathfindingConsole->onRegionBoundaryCross(); } - - if(mInstantMessageLogPathChanged) - { - std::string dir_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); - updateLogLocation(dir_name); - mInstantMessageLogPathChanged = false; - } } void LLFloaterPreference::onOpen(const LLSD& key) @@ -802,6 +795,14 @@ void LLFloaterPreference::onBtnOK() apply(); closeFloater(false); + //Conversation transcript and log path changed so reload conversations based on new location + if(mInstantMessageLogPathChanged) + { + std::string dir_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); + updateLogLocation(dir_name); + mInstantMessageLogPathChanged = false; + } + LLUIColorTable::instance().saveUserSettings(); gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); } @@ -1440,8 +1441,7 @@ void LLFloaterPreference::setAllIgnored() void LLFloaterPreference::onClickLogPath() { - std::string original_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); - std::string proposed_name(original_name); + std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); mInstantMessageLogPathChanged = false; LLDirPicker& picker = LLDirPicker::instance(); @@ -1451,10 +1451,12 @@ void LLFloaterPreference::onClickLogPath() return; //Canceled! } + //Gets the path from the directory picker + std::string dir_name = picker.getDirName(); + //Path changed - if(original_name != proposed_name) + if(proposed_name != dir_name) { - std::string dir_name = picker.getDirName(); gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); mInstantMessageLogPathChanged = true; -- cgit v1.2.3 From 1b464fae878550c22c98d9773e33be289447b503 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Thu, 21 Feb 2013 15:06:06 +0200 Subject: CHUI-783 FIXED Load logs from conversation.log file after changing preferences. --- indra/newview/llconversationlog.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index fc3bc8551c..b777edba77 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -206,6 +206,8 @@ void LLConversationLog::enableLogging(S32 log_mode) mLoggingEnabled = log_mode > 0; if (log_mode > 0) { + mConversations.clear(); + loadFromFile(getFileName()); LLIMMgr::instance().addSessionObserver(this); mNewMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); -- cgit v1.2.3 From f79f9f111b0db67cacfe9bbe453737f3979b3ba9 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Thu, 21 Feb 2013 15:11:32 +0200 Subject: CHUI-774 FIXED Play a sound even if the conversation floater is open and conversation with user is the active. --- indra/newview/llnotificationofferhandler.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index a2bd96f35a..2657b84ef3 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -96,8 +96,21 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) LLUUID from_id = notification->getPayload()["from_id"]; + //Will not play a notification sound for inventory and teleport offer based upon chat preference + bool playSound = (!notification->isDND() + && ((notification->getName() == "UserGiveItem" + && gSavedSettings.getBOOL("PlaySoundInventoryOffer")) + || (notification->getName() == "TeleportOffered" + && gSavedSettings.getBOOL("PlaySoundTeleportOffer")))); + + if(playSound) + { + notification->playSound(); + } + LLHandlerUtil::spawnIMSession(name, from_id); LLHandlerUtil::addNotifPanelToIM(notification); + } if (!notification->canShowToast()) @@ -119,17 +132,6 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) if(channel) channel->addToast(p); - //Will not play a notification sound for inventory and teleport offer based upon chat preference - bool playSound = (!notification->isDND() - && ((notification->getName() == "UserGiveItem" - && gSavedSettings.getBOOL("PlaySoundInventoryOffer")) - || (notification->getName() == "TeleportOffered" - && gSavedSettings.getBOOL("PlaySoundTeleportOffer")))); - - if(playSound) - { - notification->playSound(); - } } if (notification->canLogToIM()) -- cgit v1.2.3 From 86150b4019d1a84b4af73f0ea18c47baff955562 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Thu, 21 Feb 2013 19:15:48 -0800 Subject: CHUI-568 : WIP : Introduced Ctrl-T and Ctrl-H for conversations and nearby chat --- indra/llui/llfloater.cpp | 33 ++++++++++++++++++++-- indra/llui/llfloater.h | 3 ++ indra/llui/llfloaterreg.cpp | 30 ++++++++++++-------- indra/newview/llfloaterimnearbychat.cpp | 21 ++++++++++++++ indra/newview/llfloaterimnearbychat.h | 2 ++ indra/newview/skins/default/xui/en/menu_viewer.xml | 8 +++--- 6 files changed, 79 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 734e2cfda7..bf424883b3 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -812,6 +812,22 @@ void LLFloater::closeFloater(bool app_quitting) } } +/*virtual*/ +void LLFloater::closeHostedFloater() +{ + // When toggling *visibility*, close the host instead of the floater when hosted + if (getHost()) + { + llinfos << "Merov debug : closeHostedFloater : host " << llendl; + getHost()->closeFloater(); + } + else + { + llinfos << "Merov debug : closeHostedFloater : floater " << llendl; + closeFloater(); + } +} + /*virtual*/ void LLFloater::reshape(S32 width, S32 height, BOOL called_from_parent) { @@ -1609,8 +1625,19 @@ void LLFloater::bringToFront( S32 x, S32 y ) // virtual void LLFloater::setVisibleAndFrontmost(BOOL take_focus) { - setVisible(TRUE); - setFrontmost(take_focus); + LLMultiFloater* hostp = getHost(); + if (hostp) + { + llinfos << "Merov debug : setVisibleAndFrontmost : hostp->setFrontmost " << llendl; + hostp->setVisible(TRUE); + hostp->setFrontmost(take_focus); + } + else + { + llinfos << "Merov debug : setVisibleAndFrontmost : setFrontmost " << llendl; + setVisible(TRUE); + setFrontmost(take_focus); + } } void LLFloater::setFrontmost(BOOL take_focus) @@ -1618,12 +1645,14 @@ void LLFloater::setFrontmost(BOOL take_focus) LLMultiFloater* hostp = getHost(); if (hostp) { + llinfos << "Merov debug : setFrontmost : hostp->showFloater " << llendl; // this will bring the host floater to the front and select // the appropriate panel hostp->showFloater(this); } else { + llinfos << "Merov debug : setFrontmost : bringToFront " << llendl; // there are more than one floater view // so we need to query our parent directly ((LLFloaterView*)getParent())->bringToFront(this, take_focus); diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 157b9b0113..cb5bf28db3 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -226,6 +226,9 @@ public: // If allowed, close the floater cleanly, releasing focus. virtual void closeFloater(bool app_quitting = false); + // Close the floater or its host. Use when hidding or toggling a floater instance. + virtual void closeHostedFloater(); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); // Release keyboard and mouse focus diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 306caf2b91..c0be086671 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -264,11 +264,7 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key) LLFloater* instance = findInstance(name, key); if (instance) { - // When toggling *visibility*, close the host instead of the floater when hosted - if (instance->getHost()) - instance->getHost()->closeFloater(); - else - instance->closeFloater(); + instance->closeHostedFloater(); return true; } else @@ -281,18 +277,17 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key) // returns true if the instance is visible when completed bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key) { + llinfos << "Merov debug : toggleInstance, name = " << name << ", key = " << key.asString() << llendl; LLFloater* instance = findInstance(name, key); if (LLFloater::isShown(instance)) { - // When toggling *visibility*, close the host instead of the floater when hosted - if (instance->getHost()) - instance->getHost()->closeFloater(); - else - instance->closeFloater(); + llinfos << "Merov debug : call closeHostedFloater " << llendl; + instance->closeHostedFloater(); return false; } else { + llinfos << "Merov debug : call show instance " << llendl; return showInstance(name, key, TRUE) ? true : false; } } @@ -481,31 +476,42 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& // * Also, if it is not on top, bring it forward when focus is given. // * Else the target floater is open, close it. // + llinfos << "Merov debug : toggleInstanceOrBringToFront, name = " << sdname.asString() << ", key = " << key.asString() << llendl; std::string name = sdname.asString(); LLFloater* instance = getInstance(name, key); + if (!instance) { lldebugs << "Unable to get instance of floater '" << name << "'" << llendl; + return; } - else if (instance->isMinimized()) + + // If hosted, we need to take that into account + //LLFloater* host = instance->getHost(); + + if (instance->isMinimized()) { + llinfos << "Merov debug : unminimize, make visible and set to front " << llendl; instance->setMinimized(FALSE); instance->setVisibleAndFrontmost(); } else if (!instance->isShown()) { + llinfos << "Merov debug : open, make visible and set to front " << llendl; instance->openFloater(key); instance->setVisibleAndFrontmost(); } else if (!instance->isFrontmost()) { + llinfos << "Merov debug : make visible and set to front " << llendl; instance->setVisibleAndFrontmost(); } else { - instance->closeFloater(); + llinfos << "Merov debug : closeHostedFloater " << llendl; + instance->closeHostedFloater(); } } diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 430326203f..80051eb7f1 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -135,6 +135,27 @@ BOOL LLFloaterIMNearbyChat::postBuild() return result; } +// virtual +void LLFloaterIMNearbyChat::closeFloater(bool app_quitting) +{ + llinfos << "Merov debug : LLFloaterIMNearbyChat::closeFloater! " << llendl; + LLFloater::closeFloater(app_quitting); +} + +// virtual +void LLFloaterIMNearbyChat::closeHostedFloater() +{ + if (getHost()) + { + llinfos << "Merov debug : LLFloaterIMNearbyChat::closeHostedFloater : hosted -> do nothing" << llendl; + } + else + { + llinfos << "Merov debug : LLFloaterIMNearbyChat::closeHostedFloater : close floater " << llendl; + LLFloater::closeFloater(); + } +} + // virtual void LLFloaterIMNearbyChat::refresh() { diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index 14c7d01ecd..2d32bb3fc9 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -54,6 +54,8 @@ public: /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ void closeFloater(bool app_quitting = false); + /*virtual*/ void closeHostedFloater(); void loadHistory(); void reloadMessages(bool clean_messages = false); diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b50deb7d7a..544f06ac0c 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -183,8 +183,7 @@ </menu_item_call> <menu_item_call label="Toolbar buttons..." - name="Toolbars" - shortcut="control|T"> + name="Toolbars"> <menu_item_call.on_click function="Floater.Toggle" parameter="toybox" /> @@ -223,7 +222,8 @@ tear_off="true"> <menu_item_check label="Conversations..." - name="Conversations"> + name="Conversations" + shortcut="control|T"> <menu_item_check.on_check function="Floater.IsOpen" parameter="im_container" /> @@ -240,7 +240,7 @@ function="Floater.Visible" parameter="nearby_chat" /> <menu_item_check.on_click - function="Floater.Toggle" + function="Floater.ToggleOrBringToFront" parameter="nearby_chat" /> </menu_item_check> <menu_item_check -- cgit v1.2.3 From 3f71eabbbbe4ee54c29b0e3598569cc484505258 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Fri, 22 Feb 2013 14:02:14 +0200 Subject: CHUI-702 FIXED Calling requestArrange() in refresh() has to fix the problem. --- indra/newview/llconversationview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 5ac6353daa..5ff6841646 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -375,7 +375,7 @@ void LLConversationViewSession::refresh() } } } - + requestArrange(); // Do the regular upstream refresh LLFolderViewFolder::refresh(); } -- cgit v1.2.3 From 5284da1acee1c92f2d465088cee7488d5de2c8b3 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Fri, 22 Feb 2013 14:23:10 +0200 Subject: CHUI-781 FIXED Select conversation if user selects participant that belongs to this conversation. --- indra/newview/llconversationview.cpp | 48 +++++++++++++++++++++++++++--------- indra/newview/llconversationview.h | 2 +- 2 files changed, 37 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 5ff6841646..441de2e1a5 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -241,20 +241,23 @@ void LLConversationViewSession::draw() BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) { - LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem()); - LLUUID session_id = item? item->getUUID() : LLUUID(); - //Will try to select a child node and then itself (if a child was not selected) + //Will try to select a child node and then itself (if a child was not selected) BOOL result = LLFolderViewFolder::handleMouseDown(x, y, mask); //This node (conversation) was selected and a child (participant) was not - if(result && getRoot()->getCurSelectedItem() == this) - { - LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); - im_container->flashConversationItemWidget(session_id,false); - im_container->selectConversationPair(session_id, false); - im_container->collapseMessagesPane(false); - } - + if(result && getRoot()) + { + if(getRoot()->getCurSelectedItem() == this) + { + LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem()); + LLUUID session_id = item? item->getUUID() : LLUUID(); + + LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + im_container->flashConversationItemWidget(session_id,false); + im_container->selectConversationPair(session_id, false); + im_container->collapseMessagesPane(false); + } + } return result; } @@ -536,7 +539,7 @@ void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder) LLFolderViewItem::addToFolder(folder); // Retrieve the folder (conversation) UUID, which is also the speaker session UUID - LLConversationItem* vmi = this->getParentFolder() ? dynamic_cast<LLConversationItem*>(this->getParentFolder()->getViewModelItem()) : NULL; + LLConversationItem* vmi = getParentFolder() ? dynamic_cast<LLConversationItem*>(getParentFolder()->getViewModelItem()) : NULL; if (vmi) { addToSession(vmi->getUUID()); @@ -557,6 +560,27 @@ void LLConversationViewParticipant::onInfoBtnClick() LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", mUUID)); } +BOOL LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + BOOL result = LLFolderViewItem::handleMouseDown(x, y, mask); + + if(result && getRoot()) + { + if(getRoot()->getCurSelectedItem() == this) + { + LLConversationItem* vmi = getParentFolder() ? dynamic_cast<LLConversationItem*>(getParentFolder()->getViewModelItem()) : NULL; + LLUUID session_id = vmi? vmi->getUUID() : LLUUID(); + + LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); + im_container->flashConversationItemWidget(session_id,false); + im_container->selectFloater(session_floater); + im_container->collapseMessagesPane(false); + } + } + return result; +} + void LLConversationViewParticipant::onMouseEnter(S32 x, S32 y, MASK mask) { mInfoBtn->setVisible(true); diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index f2fa2fb042..f9b45073f4 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -138,7 +138,7 @@ public: void onMouseLeave(S32 x, S32 y, MASK mask); /*virtual*/ S32 getLabelXPos(); - + /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); void hideSpeakingIndicator(); protected: -- cgit v1.2.3 From 4b6e1c26f05d89aa130a899803553940069457c0 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Fri, 22 Feb 2013 17:08:33 +0200 Subject: CHUI-633 FIXED User is not able to open chat history by 'View chat history' menu item from pop-up menu of People floater --- indra/newview/llavataractions.cpp | 14 +++++++++++++- indra/newview/llfloaterconversationpreview.cpp | 17 ++++++++++++++--- indra/newview/llfloaterconversationpreview.h | 5 +++++ indra/newview/lllogchat.cpp | 26 ++++++++++++++++++++++++++ indra/newview/lllogchat.h | 1 + indra/newview/llpanelpeoplemenus.cpp | 7 ++++++- 6 files changed, 65 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index d6e457887b..ce063a9887 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -44,6 +44,7 @@ #include "llcallingcard.h" // for LLAvatarTracker #include "llconversationlog.h" #include "llfloateravatarpicker.h" // for LLFloaterAvatarPicker +#include "llfloaterconversationpreview.h" #include "llfloatergroupinvite.h" #include "llfloatergroups.h" #include "llfloaterreg.h" @@ -926,9 +927,20 @@ void LLAvatarActions::viewChatHistory(const LLUUID& id) if (iter->getParticipantID() == id) { LLFloaterReg::showInstance("preview_conversation", iter->getSessionID(), true); - break; + return; } } + + if (LLLogChat::isTranscriptExist(id)) + { + LLAvatarName avatar_name; + LLSD extended_id(id); + + LLAvatarNameCache::get(id, &avatar_name); + extended_id[LL_FCP_COMPLETE_NAME] = avatar_name.getCompleteName(); + extended_id[LL_FCP_ACCOUNT_NAME] = avatar_name.getAccountName(); + LLFloaterReg::showInstance("preview_conversation", extended_id, true); + } } //== private methods ======================================================================================== diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index 48e0caa0ce..a3d715530d 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -33,13 +33,19 @@ #include "llspinctrl.h" #include "lltrans.h" +const std::string LL_FCP_COMPLETE_NAME("complete_name"); +const std::string LL_FCP_ACCOUNT_NAME("user_name"); + LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id) : LLFloater(session_id), mChatHistory(NULL), mSessionID(session_id.asUUID()), mCurrentPage(0), - mPageSize(gSavedSettings.getS32("ConversationHistoryPageSize")) -{} + mPageSize(gSavedSettings.getS32("ConversationHistoryPageSize")), + mAccountName(session_id[LL_FCP_ACCOUNT_NAME]), + mCompleteName(session_id[LL_FCP_COMPLETE_NAME]) +{ +} BOOL LLFloaterConversationPreview::postBuild() { @@ -49,7 +55,12 @@ BOOL LLFloaterConversationPreview::postBuild() std::string name; std::string file; - if (mSessionID != LLUUID::null && conv) + if (mAccountName != "") + { + name = mCompleteName; + file = mAccountName; + } + else if (mSessionID != LLUUID::null && conv) { name = conv->getConversationName(); file = conv->getHistoryFileName(); diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h index 0341e5d2a0..b17ae84b63 100644 --- a/indra/newview/llfloaterconversationpreview.h +++ b/indra/newview/llfloaterconversationpreview.h @@ -29,6 +29,9 @@ #include "llchathistory.h" #include "llfloater.h" +extern const std::string LL_FCP_COMPLETE_NAME; //"complete_name" +extern const std::string LL_FCP_ACCOUNT_NAME; //"user_name" + class LLSpinCtrl; class LLFloaterConversationPreview : public LLFloater @@ -54,6 +57,8 @@ private: int mPageSize; std::list<LLSD> mMessages; + std::string mAccountName; + std::string mCompleteName; }; #endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */ diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 17b72c5023..09f816a4e6 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -28,6 +28,7 @@ #include "llagent.h" #include "llagentui.h" +#include "llavatarnamecache.h" #include "lllogchat.h" #include "lltrans.h" #include "llviewercontrol.h" @@ -540,6 +541,31 @@ void LLLogChat::deleteTranscripts() LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); } +// static +bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id) +{ + std::vector<std::string> list_of_transcriptions; + LLLogChat::getListOfTranscriptFiles(list_of_transcriptions); + + if (list_of_transcriptions.size() > 0) + { + LLAvatarName avatar_name; + LLAvatarNameCache::get(avatar_id, &avatar_name); + std::string avatar_user_name = avatar_name.getAccountName(); + std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_'); + + BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) + { + if (std::string::npos != transcript_file_name.find(avatar_user_name)) + { + return true; + } + } + } + + return false; +} + //*TODO mark object's names in a special way so that they will be distinguishable form avatar name //which are more strict by its nature (only firstname and secondname) //Example, an object's name can be written like "Object <actual_object's_name>" diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index 5fbb4ade96..b981d9ce04 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -57,6 +57,7 @@ public: static boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb); static void deleteTranscripts(); + static bool isTranscriptExist(const LLUUID& avatar_id); private: static std::string cleanFileName(std::string filename); diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index 61e9468ce5..47d6b49a50 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -37,6 +37,7 @@ #include "llagentdata.h" // for gAgentID #include "llavataractions.h" #include "llcallingcard.h" // for LLAvatarTracker +#include "lllogchat.h" #include "llviewermenu.h" // for gMenuHolder namespace LLPanelPeopleMenus @@ -180,7 +181,11 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) { return LLAvatarActions::canOfferTeleport(mUUIDs); } - else if (item == std::string("can_im") || item == std::string("can_callog") || item == std::string("can_invite") || + else if (item == std::string("can_callog")) + { + return LLLogChat::isTranscriptExist(mUUIDs.front()); + } + else if (item == std::string("can_im") || item == std::string("can_invite") || item == std::string("can_share") || item == std::string("can_pay")) { return true; -- cgit v1.2.3 From 6185c16a0af02c90625dec71119d12dec07bb056 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Fri, 22 Feb 2013 20:54:58 +0000 Subject: CHUI-772 FIX User sees no notification of conversation activity not visible in long scrolling conversation list Added LLFLoaterIMContainer::isConversationItemWidgetvisible() which is now used in LLConversationViewSession::startFlashing() to flash chat toolbar button if out of view --- indra/newview/llconversationview.cpp | 12 ++++++++++++ indra/newview/llfloaterimcontainer.cpp | 16 ++++++++++++++++ indra/newview/llfloaterimcontainer.h | 1 + 3 files changed, 29 insertions(+) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 441de2e1a5..850668388f 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -39,6 +39,7 @@ #include "llfloaterreg.h" #include "llgroupiconctrl.h" #include "lluictrlfactory.h" +#include "lltoolbarview.h" // // Implementation of conversations list session widgets @@ -114,6 +115,17 @@ void LLConversationViewSession::startFlashing() { mFlashStarted = true; mFlashTimer->startFlashing(); + + // get session id + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); + if (vmi) + { + // flash chat toolbar button if scrolled out of view (because flashing will not be visible) + if (!mContainer->isConversationItemWidgetVisible(vmi->getUUID())) + { + gToolBarView->flashCommand(LLCommandId("chat"), true); + } + } } } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c8088588da..0260f2b89e 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1853,6 +1853,22 @@ void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, } } +bool LLFloaterIMContainer::isConversationItemWidgetVisible(const LLUUID& session_id) +{ + // find the conversation line item using the session_id + LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets, session_id)); + + if (widget) + { + // check whether the widget is in the visible portion of the scroll container + LLRect widget_rect; + widget->localRectToOtherView(widget->getLocalRect(), &widget_rect, mConversationsRoot); + return (mConversationsRoot->getVisibleRect().overlaps(widget_rect)); + } + + return false; +} + void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/) { // Always unminimize before trying to close. diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 569fa9faab..156f11f14e 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -185,6 +185,7 @@ public: void updateSpeakBtnState(); static bool isConversationLoggingAllowed(); void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes); + bool isConversationItemWidgetVisible(const LLUUID& session_id); boost::signals2::connection mMicroChangedSignal; private: -- cgit v1.2.3 From 6194302a849431e84c046325d3cd19e92f62aa6f Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Fri, 22 Feb 2013 21:42:08 +0000 Subject: CHUI-772 FIX User sees no notification of conversation activity not visible in long scrolling conversation list Renamed LLFLoaterIMContainer::isConversationItemWidgetvisible() to isScrolledOutOfView() with opposite return value --- indra/newview/llconversationview.cpp | 11 +++-------- indra/newview/llfloaterimcontainer.cpp | 18 ++++++------------ indra/newview/llfloaterimcontainer.h | 2 +- 3 files changed, 10 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 850668388f..73b2c6f88c 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -116,15 +116,10 @@ void LLConversationViewSession::startFlashing() mFlashStarted = true; mFlashTimer->startFlashing(); - // get session id - LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); - if (vmi) + // flash chat toolbar button if scrolled out of sight (because flashing will not be visible) + if (mContainer->isScrolledOutOfSight(this)) { - // flash chat toolbar button if scrolled out of view (because flashing will not be visible) - if (!mContainer->isConversationItemWidgetVisible(vmi->getUUID())) - { - gToolBarView->flashCommand(LLCommandId("chat"), true); - } + gToolBarView->flashCommand(LLCommandId("chat"), true); } } } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 0260f2b89e..2d12d4ec21 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1853,20 +1853,14 @@ void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, } } -bool LLFloaterIMContainer::isConversationItemWidgetVisible(const LLUUID& session_id) +bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget) { - // find the conversation line item using the session_id - LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets, session_id)); + llassert(conversation_item_widget != NULL); - if (widget) - { - // check whether the widget is in the visible portion of the scroll container - LLRect widget_rect; - widget->localRectToOtherView(widget->getLocalRect(), &widget_rect, mConversationsRoot); - return (mConversationsRoot->getVisibleRect().overlaps(widget_rect)); - } - - return false; + // check whether the widget is in the visible portion of the scroll container + LLRect widget_rect; + conversation_item_widget->localRectToOtherView(conversation_item_widget->getLocalRect(), &widget_rect, mConversationsRoot); + return !mConversationsRoot->getVisibleRect().overlaps(widget_rect); } void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/) diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 156f11f14e..5ba29b8cfb 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -185,7 +185,7 @@ public: void updateSpeakBtnState(); static bool isConversationLoggingAllowed(); void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes); - bool isConversationItemWidgetVisible(const LLUUID& session_id); + bool isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget); boost::signals2::connection mMicroChangedSignal; private: -- cgit v1.2.3 From 05f4e8a10517b3b341359a210aeb0af06c44d43a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 22 Feb 2013 18:53:40 -0800 Subject: CHUI-778 (Saving preferences updates text in all open message panels in conversation floater to show as old messages) Now changing the log/transcripts file location actually moves the files to the new location. Prior behavior just started a new history at that location. Also a fix was made so that if the user changed the log/transcripts path then after pressing the Preferences 'OK' button the new location will be saved to the corresponding .xml file. --- indra/llvfs/lldir.cpp | 5 ++ indra/llvfs/lldir.h | 1 + indra/newview/llconversationlog.cpp | 21 ++++++ indra/newview/llconversationlog.h | 13 ++-- indra/newview/llfloaterpreference.cpp | 86 +++++++++++++++++++--- indra/newview/llfloaterpreference.h | 4 +- indra/newview/lllogchat.cpp | 60 +++++++++++++++ indra/newview/lllogchat.h | 4 + .../newview/skins/default/xui/en/notifications.xml | 11 +++ 9 files changed, 186 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index f7bc19574a..6899e9a44a 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -347,6 +347,11 @@ const std::string &LLDir::getLLPluginDir() const return mLLPluginDir; } +const std::string &LLDir::getUserName() const +{ + return mUserName; +} + static std::string ELLPathToString(ELLPath location) { typedef std::map<ELLPath, const char*> ELLPathMap; diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 95cab65149..cc10ed5bbd 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -104,6 +104,7 @@ class LLDir const std::string &getUserSkinDir() const; // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin const std::string getSkinBaseDir() const; // folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins const std::string &getLLPluginDir() const; // Directory containing plugins and plugin shell + const std::string &getUserName() const; // Expanded filename std::string getExpandedFilename(ELLPath location, const std::string &filename) const; diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index fc3bc8551c..88671a789f 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -376,6 +376,27 @@ void LLConversationLog::cache() } } +bool LLConversationLog::moveLog(const std::string &originDirectory, const std::string &targetDirectory) +{ + //Does the file exist in the current path + if(LLFile::isfile(originDirectory)) + { + //Does same file exist in the destination path, if so try to remove it + if(LLFile::isfile(targetDirectory)) + { + LLFile::remove(targetDirectory); + } + + //Move the file from the current path to destination path + if(LLFile::rename(originDirectory, targetDirectory) != 0) + { + return false; + } + } + + return true; +} + std::string LLConversationLog::getFileName() { std::string filename = "conversation"; diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index fd38556131..58e698de25 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -137,6 +137,7 @@ public: * public method which is called on viewer exit to save conversation log */ void cache(); + bool moveLog(const std::string &originDirectory, const std::string &targetDirectory); void onClearLog(); void onClearLogResponse(const LLSD& notification, const LLSD& response); @@ -144,6 +145,12 @@ public: bool getIsLoggingEnabled() { return mLoggingEnabled; } bool isLogEmpty() { return mConversations.empty(); } + /** + * constructs file name in which conversations log will be saved + * file name is conversation.log + */ + std::string getFileName(); + private: LLConversationLog(); @@ -164,12 +171,6 @@ private: void notifyParticularConversationObservers(const LLUUID& session_id, U32 mask); - /** - * constructs file name in which conversations log will be saved - * file name is conversation.log - */ - std::string getFileName(); - bool saveToFile(const std::string& filename); bool loadFromFile(const std::string& filename); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index e5444583d6..b9239b544f 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -796,15 +796,25 @@ void LLFloaterPreference::onBtnOK() closeFloater(false); //Conversation transcript and log path changed so reload conversations based on new location - if(mInstantMessageLogPathChanged) + if(mPriorInstantMessageLogPath.length()) { - std::string dir_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); - updateLogLocation(dir_name); - mInstantMessageLogPathChanged = false; + //Couldn't move files so restore the old path and show a notification + if(!moveTranscriptsAndLog()) + { + gSavedPerAccountSettings.setString("InstantMessageLogPath", mPriorInstantMessageLogPath); + LLNotificationsUtil::add("PreferenceChatPathChanged"); + } + mPriorInstantMessageLogPath.clear(); } LLUIColorTable::instance().saveUserSettings(); gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); + + //Only save once logged in and loaded per account settings + if(mGotPersonalInfo) + { + gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); + } } else { @@ -1442,7 +1452,7 @@ void LLFloaterPreference::setAllIgnored() void LLFloaterPreference::onClickLogPath() { std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); - mInstantMessageLogPathChanged = false; + mPriorInstantMessageLogPath.clear(); LLDirPicker& picker = LLDirPicker::instance(); //Launches a directory picker and waits for feedback @@ -1458,21 +1468,75 @@ void LLFloaterPreference::onClickLogPath() if(proposed_name != dir_name) { gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); - mInstantMessageLogPathChanged = true; + mPriorInstantMessageLogPath = proposed_name; // enable/disable 'Delete transcripts button updateDeleteTranscriptsButton(); } } -void LLFloaterPreference::updateLogLocation(const std::string& dir_name) +bool LLFloaterPreference::moveTranscriptsAndLog() { - gDirUtilp->setChatLogsDir(dir_name); + std::string instantMessageLogPath(gSavedPerAccountSettings.getString("InstantMessageLogPath")); + std::string chatLogPath = gDirUtilp->add(instantMessageLogPath, gDirUtilp->getUserName()); + + bool madeDirectory = false; + + //Does the directory really exist, if not then make it + if(!LLFile::isdir(chatLogPath)) + { + //mkdir success is defined as zero + if(LLFile::mkdir(chatLogPath) != 0) + { + return false; + } + madeDirectory = true; + } + + std::string originalConversationLogDir = LLConversationLog::instance().getFileName(); + std::string targetConversationLogDir = gDirUtilp->add(chatLogPath, "conversation.log"); + //Try to move the conversation log + if(!LLConversationLog::instance().moveLog(originalConversationLogDir, targetConversationLogDir)) + { + //Couldn't move the log and created a new directory so remove the new directory + if(madeDirectory) + { + LLFile::rmdir(chatLogPath); + } + return false; + } + + //Attempt to move transcripts + std::vector<std::string> listOfTranscripts; + std::vector<std::string> listOfFilesMoved; + + LLLogChat::getListOfTranscriptFiles(listOfTranscripts); + + if(!LLLogChat::moveTranscripts(gDirUtilp->getChatLogsDir(), + instantMessageLogPath, + listOfTranscripts, + listOfFilesMoved)) + { + //Couldn't move all the transcripts so restore those that moved back to their old location + LLLogChat::moveTranscripts(instantMessageLogPath, + gDirUtilp->getChatLogsDir(), + listOfFilesMoved); + + //Move the conversation log back + LLConversationLog::instance().moveLog(targetConversationLogDir, originalConversationLogDir); + + if(madeDirectory) + { + LLFile::rmdir(chatLogPath); + } + + return false; + } + + gDirUtilp->setChatLogsDir(instantMessageLogPath); gDirUtilp->updatePerAccountChatLogsDir(); - LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); - // refresh IM floaters with new logs from files from new selected directory - LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); + return true; } void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im_via_email) diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index c72346c3b6..22e80a21cb 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -143,7 +143,7 @@ public: void resetAllIgnored(); void setAllIgnored(); void onClickLogPath(); - void updateLogLocation(const std::string& dir_name); + bool moveTranscriptsAndLog(); void enableHistory(); void setPersonalInfo(const std::string& visibility, bool im_via_email); void refreshEnabledState(); @@ -186,8 +186,8 @@ private: bool mGotPersonalInfo; bool mOriginalIMViaEmail; bool mLanguageChanged; - bool mInstantMessageLogPathChanged; bool mAvatarDataInitialized; + std::string mPriorInstantMessageLogPath; bool mOriginalHideOnlineStatus; std::string mDirectoryVisibility; diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 17b72c5023..b60e2aa44e 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -500,6 +500,66 @@ boost::signals2::connection LLLogChat::setSaveHistorySignal(const save_history_s return sSaveHistorySignal->connect(cb); } +//static +bool LLLogChat::moveTranscripts(const std::string originDirectory, + const std::string targetDirectory, + std::vector<std::string>& listOfFilesToMove, + std::vector<std::string>& listOfFilesMoved) +{ + std::string newFullPath; + bool movedAllTranscripts = true; + + BOOST_FOREACH(const std::string& fullpath, listOfFilesToMove) + { + newFullPath = targetDirectory + fullpath.substr(originDirectory.length(), std::string::npos); + + S32 retry_count = 0; + while (retry_count < 5) + { + //success is zero + if (LLFile::rename(fullpath, newFullPath) != 0) + { + retry_count++; + S32 result = errno; + LL_WARNS("LLLogChat::moveTranscripts") << "Problem renaming " << fullpath << " - errorcode: " + << result << " attempt " << retry_count << LL_ENDL; + + if(retry_count >= 5) + { + LL_WARNS("LLLogChat::moveTranscripts") << "Failed to rename " << fullpath << LL_ENDL; + return false; + } + + //If the file already exists in the new location, remove it then try again + if(LLFile::isfile(newFullPath)) + { + LLFile::remove(newFullPath); + LL_WARNS("LLLogChat::moveTranscripts") << "File already exists " << fullpath << LL_ENDL; + } + + ms_sleep(100); + } + else + { + listOfFilesMoved.push_back(newFullPath); + + if (retry_count) + { + LL_WARNS("LLLogChat::moveTranscripts") << "Successfully renamed " << fullpath << LL_ENDL; + } + break; + } + } + } + + if(listOfFilesMoved.size() != listOfFilesToMove.size()) + { + movedAllTranscripts = false; + } + + return movedAllTranscripts; +} + //static void LLLogChat::deleteTranscripts() { diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index 5fbb4ade96..b9aede0b29 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -56,6 +56,10 @@ public: typedef boost::signals2::signal<void ()> save_history_signal_t; static boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb); + static bool moveTranscripts(const std::string currentDirectory, + const std::string newDirectory, + std::vector<std::string>& listOfFilesToMove, + std::vector<std::string>& listOfFilesMoved = std::vector<std::string>()); static void deleteTranscripts(); private: diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 3ae9b206a4..234c6d7c0f 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -10028,4 +10028,15 @@ Cannot create large prims that intersect other players. Please re-try when othe yestext="OK"/> </notification> + <notification + icon="alert.tga" + name="PreferenceChatPathChanged" + type="alert"> + Unable to move files. Restored previous path. + <usetemplate + ignoretext="Unable to move files. Restored previous path." + name="okignore" + yestext="OK"/> + </notification> + </notifications> -- cgit v1.2.3 From 7f51bd7897a3ced0edc74a32b9148febd7866721 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Sat, 23 Feb 2013 11:22:09 -0800 Subject: CHUI-568 : Fixed! Implemented Ctrl-H for Nearby Chat, taking into account the existence of other conversations and docked/torn off state --- indra/llui/llfloater.cpp | 6 --- indra/llui/llfloaterreg.cpp | 65 +++++++++++++++++++-------------- indra/newview/llfloaterimcontainer.cpp | 24 ++++++++++++ indra/newview/llfloaterimcontainer.h | 2 + indra/newview/llfloaterimnearbychat.cpp | 20 +++++----- indra/newview/llfloaterimnearbychat.h | 1 - 6 files changed, 72 insertions(+), 46 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index bf424883b3..27dd7f5b32 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -818,12 +818,10 @@ void LLFloater::closeHostedFloater() // When toggling *visibility*, close the host instead of the floater when hosted if (getHost()) { - llinfos << "Merov debug : closeHostedFloater : host " << llendl; getHost()->closeFloater(); } else { - llinfos << "Merov debug : closeHostedFloater : floater " << llendl; closeFloater(); } } @@ -1628,13 +1626,11 @@ void LLFloater::setVisibleAndFrontmost(BOOL take_focus) LLMultiFloater* hostp = getHost(); if (hostp) { - llinfos << "Merov debug : setVisibleAndFrontmost : hostp->setFrontmost " << llendl; hostp->setVisible(TRUE); hostp->setFrontmost(take_focus); } else { - llinfos << "Merov debug : setVisibleAndFrontmost : setFrontmost " << llendl; setVisible(TRUE); setFrontmost(take_focus); } @@ -1645,14 +1641,12 @@ void LLFloater::setFrontmost(BOOL take_focus) LLMultiFloater* hostp = getHost(); if (hostp) { - llinfos << "Merov debug : setFrontmost : hostp->showFloater " << llendl; // this will bring the host floater to the front and select // the appropriate panel hostp->showFloater(this); } else { - llinfos << "Merov debug : setFrontmost : bringToFront " << llendl; // there are more than one floater view // so we need to query our parent directly ((LLFloaterView*)getParent())->bringToFront(this, take_focus); diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index c0be086671..c20d863612 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -265,29 +265,22 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key) if (instance) { instance->closeHostedFloater(); - return true; - } - else - { - return false; } + return (instance != NULL); } //static // returns true if the instance is visible when completed bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key) { - llinfos << "Merov debug : toggleInstance, name = " << name << ", key = " << key.asString() << llendl; LLFloater* instance = findInstance(name, key); if (LLFloater::isShown(instance)) { - llinfos << "Merov debug : call closeHostedFloater " << llendl; instance->closeHostedFloater(); return false; } else { - llinfos << "Merov debug : call show instance " << llendl; return showInstance(name, key, TRUE) ? true : false; } } @@ -476,8 +469,6 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& // * Also, if it is not on top, bring it forward when focus is given. // * Else the target floater is open, close it. // - llinfos << "Merov debug : toggleInstanceOrBringToFront, name = " << sdname.asString() << ", key = " << key.asString() << llendl; - std::string name = sdname.asString(); LLFloater* instance = getInstance(name, key); @@ -489,29 +480,47 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& } // If hosted, we need to take that into account - //LLFloater* host = instance->getHost(); + LLFloater* host = instance->getHost(); - if (instance->isMinimized()) - { - llinfos << "Merov debug : unminimize, make visible and set to front " << llendl; - instance->setMinimized(FALSE); - instance->setVisibleAndFrontmost(); - } - else if (!instance->isShown()) - { - llinfos << "Merov debug : open, make visible and set to front " << llendl; - instance->openFloater(key); - instance->setVisibleAndFrontmost(); - } - else if (!instance->isFrontmost()) + if (host) { - llinfos << "Merov debug : make visible and set to front " << llendl; - instance->setVisibleAndFrontmost(); + if (host->isMinimized() || !host->isShown() || !host->isFrontmost()) + { + host->setMinimized(FALSE); + instance->openFloater(key); + instance->setVisibleAndFrontmost(); + } + else if (!instance->getVisible()) + { + instance->openFloater(key); + instance->setVisibleAndFrontmost(); + instance->setFocus(TRUE); + } + else + { + instance->closeHostedFloater(); + } } else { - llinfos << "Merov debug : closeHostedFloater " << llendl; - instance->closeHostedFloater(); + if (instance->isMinimized()) + { + instance->setMinimized(FALSE); + instance->setVisibleAndFrontmost(); + } + else if (!instance->isShown()) + { + instance->openFloater(key); + instance->setVisibleAndFrontmost(); + } + else if (!instance->isFrontmost()) + { + instance->setVisibleAndFrontmost(); + } + else + { + instance->closeHostedFloater(); + } } } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c8088588da..73fcfa244e 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1337,6 +1337,30 @@ void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) selectConversationPair(session_id, true); } +// Select the conversation *after* (or before if none after) the passed uuid conversation +// Used to change the selection on key hits +void LLFloaterIMContainer::selectNextConversation(const LLUUID& uuid) +{ + LLFolderViewItem* new_selection = NULL; + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); + if (widget) + { + new_selection = mConversationsRoot->getNextFromChild(widget, FALSE); + if (!new_selection) + { + new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE); + } + } + if (new_selection) + { + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem()); + if (vmi) + { + selectConversationPair(vmi->getUUID(), true); + } + } +} + // Synchronous select the conversation item and the conversation floater BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget) { diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 569fa9faab..33d63a391c 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -69,6 +69,7 @@ public: void returnFloaterToHost(); void showConversation(const LLUUID& session_id); void selectConversation(const LLUUID& session_id); + void selectNextConversation(const LLUUID& session_id); BOOL selectConversationPair(const LLUUID& session_id, bool select_widget); void clearAllFlashStates(); @@ -186,6 +187,7 @@ public: static bool isConversationLoggingAllowed(); void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes); boost::signals2::connection mMicroChangedSignal; + S32 getConversationListItemSize() { return mConversationsWidgets.size(); } private: LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 80051eb7f1..a3b81e037a 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -135,24 +135,22 @@ BOOL LLFloaterIMNearbyChat::postBuild() return result; } -// virtual -void LLFloaterIMNearbyChat::closeFloater(bool app_quitting) -{ - llinfos << "Merov debug : LLFloaterIMNearbyChat::closeFloater! " << llendl; - LLFloater::closeFloater(app_quitting); -} - // virtual void LLFloaterIMNearbyChat::closeHostedFloater() { - if (getHost()) + // Should check how many conversations are ongoing. Close all if 1 only (the Nearby Chat), select next one otherwise + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + if (floater_container->getConversationListItemSize() == 1) { - llinfos << "Merov debug : LLFloaterIMNearbyChat::closeHostedFloater : hosted -> do nothing" << llendl; + floater_container->closeFloater(); } else { - llinfos << "Merov debug : LLFloaterIMNearbyChat::closeHostedFloater : close floater " << llendl; - LLFloater::closeFloater(); + if (!getHost()) + { + setVisible(FALSE); + } + floater_container->selectNextConversation(LLUUID()); } } diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index 2d32bb3fc9..2992c12436 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -54,7 +54,6 @@ public: /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setVisible(BOOL visible); - /*virtual*/ void closeFloater(bool app_quitting = false); /*virtual*/ void closeHostedFloater(); void loadHistory(); -- cgit v1.2.3 From c6929e42486dd6aa212dc523be4f3b65f431b016 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 25 Feb 2013 04:20:08 -0800 Subject: CHUI-788 (Saving preferences updates text in all open message panels in conversation floater to show as old messages) Fixed build error for mac/linux --- indra/newview/lllogchat.cpp | 9 +++++++++ indra/newview/lllogchat.h | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index b60e2aa44e..95b0e6b9d6 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -560,6 +560,15 @@ bool LLLogChat::moveTranscripts(const std::string originDirectory, return movedAllTranscripts; } +//static +bool LLLogChat::moveTranscripts(const std::string currentDirectory, + const std::string newDirectory, + std::vector<std::string>& listOfFilesToMove) +{ + std::vector<std::string> listOfFilesMoved; + return moveTranscripts(currentDirectory, newDirectory, listOfFilesToMove, listOfFilesMoved); +} + //static void LLLogChat::deleteTranscripts() { diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index b9aede0b29..244f1c8790 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -59,7 +59,11 @@ public: static bool moveTranscripts(const std::string currentDirectory, const std::string newDirectory, std::vector<std::string>& listOfFilesToMove, - std::vector<std::string>& listOfFilesMoved = std::vector<std::string>()); + std::vector<std::string>& listOfFilesMoved); + static bool moveTranscripts(const std::string currentDirectory, + const std::string newDirectory, + std::vector<std::string>& listOfFilesToMove); + static void deleteTranscripts(); private: -- cgit v1.2.3 From fbf7217b49101faad3a4e910d8c88150c39e73d6 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Mon, 25 Feb 2013 15:00:48 +0200 Subject: CHUI-790 FIXED Just disable "+" if selected participant is your own avatar --- indra/newview/llpanelpeople.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 6667706333..c5283404f1 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -812,19 +812,20 @@ void LLPanelPeople::updateButtons() else { bool is_friend = true; - + bool is_self = false; // Check whether selected avatar is our friend. if (item_selected) { selected_id = selected_uuids.front(); is_friend = LLAvatarTracker::instance().getBuddyInfo(selected_id) != NULL; + is_self = gAgent.getID() == selected_id; } LLPanel* cur_panel = mTabContainer->getCurrentPanel(); if (cur_panel) { if (cur_panel->hasChild("add_friend_btn", TRUE)) - cur_panel->getChildView("add_friend_btn")->setEnabled(item_selected && !is_friend); + cur_panel->getChildView("add_friend_btn")->setEnabled(item_selected && !is_friend && !is_self); if (friends_tab_active) { -- cgit v1.2.3 From c70a951abd0993c85aa96a930a54ff89c93cd03a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 25 Feb 2013 11:41:22 -0800 Subject: CHUI-778: Pushing a quick fix that only pertains to CHUI-778 so we can close out this issue. --- indra/newview/llfloaterpreference.cpp | 32 +++++++++++++++++++++++--------- indra/newview/llfloaterpreference.h | 1 + 2 files changed, 24 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 3d8d0e15ec..688d453789 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -646,9 +646,6 @@ void LLFloaterPreference::cancel() LLFloaterPathfindingConsole* pPathfindingConsole = pathfindingConsoleHandle.get(); pPathfindingConsole->onRegionBoundaryCross(); } - - std::string dir_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); - updateLogLocation(dir_name); } void LLFloaterPreference::onOpen(const LLSD& key) @@ -798,6 +795,14 @@ void LLFloaterPreference::onBtnOK() apply(); closeFloater(false); + //Conversation transcript and log path changed so reload conversations based on new location + if(mPriorInstantMessageLogPath.length()) + { + std::string dir_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); + updateLogLocation(dir_name); + mPriorInstantMessageLogPath.clear(); + } + LLUIColorTable::instance().saveUserSettings(); gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); } @@ -1436,19 +1441,28 @@ void LLFloaterPreference::setAllIgnored() void LLFloaterPreference::onClickLogPath() { - std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); - + std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); + mPriorInstantMessageLogPath.clear(); + LLDirPicker& picker = LLDirPicker::instance(); + //Launches a directory picker and waits for feedback if (!picker.getDir(&proposed_name ) ) { return; //Canceled! } + //Gets the path from the directory picker std::string dir_name = picker.getDirName(); - gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); - - // enable/disable 'Delete transcripts button - updateDeleteTranscriptsButton(); + + //Path changed + if(proposed_name != dir_name) + { + gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); + mPriorInstantMessageLogPath = proposed_name; + + // enable/disable 'Delete transcripts button + updateDeleteTranscriptsButton(); + } } void LLFloaterPreference::updateLogLocation(const std::string& dir_name) diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index dbd87f74a1..31c1e2d9e5 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -187,6 +187,7 @@ private: bool mOriginalIMViaEmail; bool mLanguageChanged; bool mAvatarDataInitialized; + std::string mPriorInstantMessageLogPath; bool mOriginalHideOnlineStatus; std::string mDirectoryVisibility; -- cgit v1.2.3 From 57935506c29e4dfde82626a91a853d87a46aead3 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 25 Feb 2013 13:41:37 -0800 Subject: merge --- indra/newview/llconversationlog.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 4953bcbd02..03d1647c5e 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -380,13 +380,32 @@ void LLConversationLog::cache() bool LLConversationLog::moveLog(const std::string &originDirectory, const std::string &targetDirectory) { + + std::string backupFileName; + UINT backupFileCount = 0; + //Does the file exist in the current path if(LLFile::isfile(originDirectory)) { - //Does same file exist in the destination path, if so try to remove it + + //File already exists so make a backup file if(LLFile::isfile(targetDirectory)) { - LLFile::remove(targetDirectory); + backupFileName = targetDirectory + ".backup"; + + //If needed store backup file as .backup1 etc. + while(LLFile::isfile(backupFileName)) + { + backupFileName = targetDirectory + ".backup"; + + if(backupFileCount) + { + backupFileName += backupFileCount; + } + } + + //Rename the file to its backup name so it is not overwritten + LLFile::rename(targetDirectory, backupFileName); } //Move the file from the current path to destination path -- cgit v1.2.3 From 9ebe7db402af546211b65faf43d1635f3b92937e Mon Sep 17 00:00:00 2001 From: Oz Linden <oz@lindenlab.com> Date: Mon, 25 Feb 2013 17:29:15 -0500 Subject: increment minor version: 3.5.0 --- indra/llcommon/llversionviewer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 6a5ff314e4..1554e9e665 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -28,8 +28,8 @@ #define LL_LLVERSIONVIEWER_H const S32 LL_VERSION_MAJOR = 3; -const S32 LL_VERSION_MINOR = 4; -const S32 LL_VERSION_PATCH = 6; +const S32 LL_VERSION_MINOR = 5; +const S32 LL_VERSION_PATCH = 0; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; -- cgit v1.2.3 From f7100331ebc7913d7117501ccac86f93f4ffb0e3 Mon Sep 17 00:00:00 2001 From: Oz Linden <oz@lindenlab.com> Date: Mon, 25 Feb 2013 17:41:36 -0500 Subject: increment version to 3.5.1 --- indra/llcommon/llversionviewer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 1554e9e665..0b0c74b3d3 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -29,7 +29,7 @@ const S32 LL_VERSION_MAJOR = 3; const S32 LL_VERSION_MINOR = 5; -const S32 LL_VERSION_PATCH = 0; +const S32 LL_VERSION_PATCH = 1; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; -- cgit v1.2.3 From 084ea74d43471eec1ae8781c4946fcf2a3a76a78 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 25 Feb 2013 16:48:09 -0800 Subject: CHUI-778: Now when conversation log and trascript files are moved they will not overwrite prior files with the same name. Instead the prior files will be stored as *.backup. --- indra/newview/llconversationlog.cpp | 21 +++++++++------------ indra/newview/lllogchat.cpp | 24 +++++++++++++++--------- 2 files changed, 24 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 03d1647c5e..4be169e267 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -31,6 +31,8 @@ #include "llnotificationsutil.h" #include "lltrans.h" +#include "boost/lexical_cast.hpp" + const int CONVERSATION_LIFETIME = 30; // lifetime of LLConversation is 30 days by spec struct ConversationParams @@ -382,13 +384,12 @@ bool LLConversationLog::moveLog(const std::string &originDirectory, const std::s { std::string backupFileName; - UINT backupFileCount = 0; + unsigned backupFileCount = 0; - //Does the file exist in the current path - if(LLFile::isfile(originDirectory)) + //Does the file exist in the current path, if it does lets move it + if(LLFile::isfile(originDirectory)) { - - //File already exists so make a backup file + //The target directory contains that file already, so lets store it if(LLFile::isfile(targetDirectory)) { backupFileName = targetDirectory + ".backup"; @@ -396,19 +397,15 @@ bool LLConversationLog::moveLog(const std::string &originDirectory, const std::s //If needed store backup file as .backup1 etc. while(LLFile::isfile(backupFileName)) { - backupFileName = targetDirectory + ".backup"; - - if(backupFileCount) - { - backupFileName += backupFileCount; - } + ++backupFileCount; + backupFileName = targetDirectory + ".backup" + boost::lexical_cast<std::string>(backupFileCount); } //Rename the file to its backup name so it is not overwritten LLFile::rename(targetDirectory, backupFileName); } - //Move the file from the current path to destination path + //Move the file from the current path to target path if(LLFile::rename(originDirectory, targetDirectory) != 0) { return false; diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index d9d28c6d70..6562cfe1bb 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -509,9 +509,12 @@ bool LLLogChat::moveTranscripts(const std::string originDirectory, { std::string newFullPath; bool movedAllTranscripts = true; + std::string backupFileName; + unsigned backupFileCount; BOOST_FOREACH(const std::string& fullpath, listOfFilesToMove) { + backupFileCount = 0; newFullPath = targetDirectory + fullpath.substr(originDirectory.length(), std::string::npos); S32 retry_count = 0; @@ -525,17 +528,20 @@ bool LLLogChat::moveTranscripts(const std::string originDirectory, LL_WARNS("LLLogChat::moveTranscripts") << "Problem renaming " << fullpath << " - errorcode: " << result << " attempt " << retry_count << LL_ENDL; - if(retry_count >= 5) - { - LL_WARNS("LLLogChat::moveTranscripts") << "Failed to rename " << fullpath << LL_ENDL; - return false; - } - - //If the file already exists in the new location, remove it then try again + //The target directory contains that file already, so lets store it if(LLFile::isfile(newFullPath)) { - LLFile::remove(newFullPath); - LL_WARNS("LLLogChat::moveTranscripts") << "File already exists " << fullpath << LL_ENDL; + backupFileName = newFullPath + ".backup"; + + //If needed store backup file as .backup1 etc. + while(LLFile::isfile(backupFileName)) + { + ++backupFileCount; + backupFileName = newFullPath + ".backup" + boost::lexical_cast<std::string>(backupFileCount); + } + + //Rename the file to its backup name so it is not overwritten + LLFile::rename(newFullPath, backupFileName); } ms_sleep(100); -- cgit v1.2.3 From 31e5465158db171a4ac6d3aa48d44e8a62c012f9 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 27 Feb 2013 01:35:27 +0200 Subject: CHUI-788 FIXED Mute icon not shown in participant list in conversation floater --- indra/newview/llconversationmodel.cpp | 29 +++++++++++++++++++++++++---- indra/newview/llconversationmodel.h | 6 +++--- indra/newview/llconversationview.cpp | 13 ------------- indra/newview/llconversationview.h | 1 - indra/newview/lloutputmonitorctrl.cpp | 6 +++--- indra/newview/lloutputmonitorctrl.h | 3 --- 6 files changed, 31 insertions(+), 27 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 0977056b2a..009fce0a92 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -322,7 +322,7 @@ void LLConversationItemSession::setParticipantIsMuted(const LLUUID& participant_ LLConversationItemParticipant* participant = findParticipant(participant_id); if (participant) { - participant->setIsMuted(is_muted); + participant->muteVoice(is_muted); } } @@ -462,7 +462,6 @@ void LLConversationItemSession::onAvatarNameCache(const LLAvatarName& av_name) LLConversationItemParticipant::LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLConversationItem(display_name,uuid,root_view_model), - mIsMuted(false), mIsModerator(false), mDisplayModeratorLabel(false), mDistToAgent(-1.0) @@ -473,7 +472,6 @@ LLConversationItemParticipant::LLConversationItemParticipant(std::string display LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLConversationItem(uuid,root_view_model), - mIsMuted(false), mIsModerator(false), mDisplayModeratorLabel(false), mDistToAgent(-1.0) @@ -549,7 +547,7 @@ LLConversationItemSession* LLConversationItemParticipant::getParentSession() void LLConversationItemParticipant::dumpDebugData() { - llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", display name = " << mDisplayName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; + llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", display name = " << mDisplayName << ", muted = " << isVoiceMuted() << ", moderator = " << mIsModerator << llendl; } void LLConversationItemParticipant::setDisplayModeratorRole(bool displayRole) @@ -561,6 +559,29 @@ void LLConversationItemParticipant::setDisplayModeratorRole(bool displayRole) } } +bool LLConversationItemParticipant::isVoiceMuted() +{ + return LLMuteList::getInstance()->isMuted(mUUID, LLMute::flagVoiceChat); +} + +void LLConversationItemParticipant::muteVoice(bool mute_voice) +{ + std::string name; + gCacheName->getFullName(mUUID, name); + LLMuteList * mute_listp = LLMuteList::getInstance(); + bool voice_already_muted = mute_listp->isMuted(mUUID, name); + + LLMute mute(mUUID, name, LLMute::AGENT); + if (voice_already_muted && !mute_voice) + { + mute_listp->remove(mute); + } + else if (!voice_already_muted && mute_voice) + { + mute_listp->add(mute); + } +} + // // LLConversationSort // diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index c907d1d6d2..8766585049 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -189,9 +189,9 @@ public: virtual const std::string& getDisplayName() const { return mDisplayName; } - bool isMuted() { return mIsMuted; } - bool isModerator() {return mIsModerator; } - void setIsMuted(bool is_muted) { mIsMuted = is_muted; mNeedsRefresh = true; } + bool isVoiceMuted(); + bool isModerator() const { return mIsModerator; } + void muteVoice(bool mute_voice); void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; } void setTimeNow() { mLastActiveTime = LLFrameTimer::getElapsedSeconds(); mNeedsRefresh = true; } void setDistance(F64 dist) { mDistToAgent = dist; mNeedsRefresh = true; } diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 73b2c6f88c..882ef64715 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -527,19 +527,6 @@ S32 LLConversationViewParticipant::arrange(S32* width, S32* height) return arranged; } -void LLConversationViewParticipant::refresh() -{ - // Refresh the participant view from its model data - LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem()); - participant_model->resetRefresh(); - - // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat - mSpeakingIndicator->setIsMuted(participant_model->isMuted()); - - // Do the regular upstream refresh - LLFolderViewItem::refresh(); -} - void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder) { // Add the item to the folder (conversation) diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index f9b45073f4..76d3d079ea 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -130,7 +130,6 @@ public: virtual ~LLConversationViewParticipant( void ); bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } - virtual void refresh(); void addToFolder(LLFolderViewFolder* folder); void addToSession(const LLUUID& session_id); diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index f6e3c0cac0..6c26073d5b 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -284,12 +284,12 @@ void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& s { if (speaker_id == gAgentID) { - setIsMuted(false); + mIsMuted = false; } else { // check only blocking on voice. EXT-3542 - setIsMuted(LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat)); + mIsMuted = LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat); LLMuteList::getInstance()->addObserver(this); } } @@ -298,7 +298,7 @@ void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& s void LLOutputMonitorCtrl::onChange() { // check only blocking on voice. EXT-3542 - setIsMuted(LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat)); + mIsMuted = LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat); } // virtual diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index af2fd45823..a346909027 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -73,9 +73,6 @@ public: void setPower(F32 val); F32 getPower(F32 val) const { return mPower; } - bool getIsMuted() const { return mIsMuted; } - void setIsMuted(bool val) { mIsMuted = val; } - // For the current user, need to know the PTT state to show // correct button image. void setIsAgentControl(bool val) { mIsAgentControl = val; } -- cgit v1.2.3 From 2439956242670cfc52e6d27f0b37bb3b6f0ab6e0 Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Thu, 28 Feb 2013 15:33:33 +0200 Subject: CHUI-789 (Letter m appears in Conversations while exit from outlook view using 'M' keyboard key) --- indra/newview/llfloaterimcontainer.cpp | 6 +++--- indra/newview/llfloaterimcontainer.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c5edd11c12..f9f0173ec7 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -605,7 +605,7 @@ void LLFloaterIMContainer::setVisible(BOOL visible) setSelectedSession(LLUUID(NULL)); } openNearbyChat(); - selectConversationPair(getSelectedSession(), false); + selectConversationPair(getSelectedSession(), false, false); } nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); @@ -1362,7 +1362,7 @@ void LLFloaterIMContainer::selectNextConversation(const LLUUID& uuid) } // Synchronous select the conversation item and the conversation floater -BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget) +BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater/*=true*/) { BOOL handled = TRUE; LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); @@ -1409,7 +1409,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool if (!session_floater->hasFocus()) { BOOL is_minimized = session_floater->isMinimized(); - session_floater->setFocus(TRUE); + session_floater->setFocus(focus_floater); session_floater->setMinimized(is_minimized); } } diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 419239f90b..f1415cd2e6 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -70,7 +70,7 @@ public: void showConversation(const LLUUID& session_id); void selectConversation(const LLUUID& session_id); void selectNextConversation(const LLUUID& session_id); - BOOL selectConversationPair(const LLUUID& session_id, bool select_widget); + BOOL selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater = true); void clearAllFlashStates(); /*virtual*/ void tabClose(); -- cgit v1.2.3 From 9530b9d2b717d338af79108c60c2aa67e33ba6e5 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Fri, 1 Mar 2013 14:24:47 +0200 Subject: CHUI-694 FIXED Handle ALT + Up/Down and ALT + Right/Left to switch conversations in the list. Handle ALT + Enter to expand participant list of selected conversation. --- indra/llui/llfolderviewitem.cpp | 2 +- indra/newview/llfloaterimcontainer.cpp | 88 ++++++++++++++++++++++++++------- indra/newview/llfloaterimcontainer.h | 6 ++- indra/newview/llfloaterimnearbychat.cpp | 17 ++++++- indra/newview/llfloaterimsessiontab.cpp | 21 ++++++++ indra/newview/llfloaterimsessiontab.h | 2 +- indra/newview/llviewerwindow.cpp | 9 +++- 7 files changed, 121 insertions(+), 24 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index f67c134751..fdb4108afb 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -2072,7 +2072,7 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it if (fit != fend) { // try selecting child element of this folder - if ((*fit)->isOpen()) + if ((*fit)->isOpen() && include_children) { result = (*fit)->getPreviousFromChild(NULL); } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index f9f0173ec7..49c30e8768 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1339,25 +1339,14 @@ void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) // Select the conversation *after* (or before if none after) the passed uuid conversation // Used to change the selection on key hits -void LLFloaterIMContainer::selectNextConversation(const LLUUID& uuid) +void LLFloaterIMContainer::selectNextConversationByID(const LLUUID& uuid) { - LLFolderViewItem* new_selection = NULL; - LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); - if (widget) + bool new_selection = false; + selectConversation(uuid); + new_selection = selectNextorPreviousConversation(true); + if (!new_selection) { - new_selection = mConversationsRoot->getNextFromChild(widget, FALSE); - if (!new_selection) - { - new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE); - } - } - if (new_selection) - { - LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem()); - if (vmi) - { - selectConversationPair(vmi->getUUID(), true); - } + selectNextorPreviousConversation(false); } } @@ -1887,6 +1876,71 @@ bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conve return !mConversationsRoot->getVisibleRect().overlaps(widget_rect); } +BOOL LLFloaterIMContainer::handleKeyHere(KEY key, MASK mask ) +{ + if(mask == MASK_ALT) + { + if (KEY_RETURN == key ) + { + expandConversation(); + } + + if ((KEY_DOWN == key ) || (KEY_RIGHT == key)) + { + selectNextorPreviousConversation(true); + } + if ((KEY_UP == key) || (KEY_LEFT == key)) + { + selectNextorPreviousConversation(false); + } + } + return TRUE; +} + +bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next) +{ + if (mConversationsWidgets.size() > 1) + { + LLFolderViewItem* new_selection = NULL; + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,getSelectedSession()); + if (widget) + { + if(select_next) + { + new_selection = mConversationsRoot->getNextFromChild(widget, FALSE); + } + else + { + new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE); + } + if (new_selection) + { + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem()); + if (vmi) + { + selectConversationPair(vmi->getUUID(), true); + LLFloater* floaterp = get_ptr_in_map(mSessions, getSelectedSession()); + if(floaterp && !floaterp->isTornOff()) + { + setFocus(TRUE); + } + return true; + } + } + } + } + return false; +} + +void LLFloaterIMContainer::expandConversation() +{ + LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,getSelectedSession())); + if (widget) + { + widget->setOpen(!widget->isOpen()); + } +} + void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/) { // Always unminimize before trying to close. diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index f1415cd2e6..c84d4978ec 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -69,9 +69,11 @@ public: void returnFloaterToHost(); void showConversation(const LLUUID& session_id); void selectConversation(const LLUUID& session_id); - void selectNextConversation(const LLUUID& session_id); + void selectNextConversationByID(const LLUUID& session_id); BOOL selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater = true); void clearAllFlashStates(); + bool selectNextorPreviousConversation(bool select_next); + void expandConversation(); /*virtual*/ void tabClose(); void showStub(bool visible); @@ -109,7 +111,7 @@ public: void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS); void assignResizeLimits(); - + virtual BOOL handleKeyHere(KEY key, MASK mask ); /*virtual*/ void closeFloater(bool app_quitting = false); private: diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index a3b81e037a..02f54e76db 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -150,7 +150,7 @@ void LLFloaterIMNearbyChat::closeHostedFloater() { setVisible(FALSE); } - floater_container->selectNextConversation(LLUUID()); + floater_container->selectNextConversationByID(LLUUID()); } } @@ -354,6 +354,21 @@ BOOL LLFloaterIMNearbyChat::handleKeyHere( KEY key, MASK mask ) handled = TRUE; } + if((mask == MASK_ALT) && isTornOff()) + { + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + if ((KEY_UP == key) || (KEY_LEFT == key)) + { + floater_container->selectNextorPreviousConversation(false); + handled = TRUE; + } + if ((KEY_DOWN == key ) || (KEY_RIGHT == key)) + { + floater_container->selectNextorPreviousConversation(true); + handled = TRUE; + } + } + return handled; } diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 6dbcdb4474..47744b6ba0 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -918,3 +918,24 @@ LLConversationItem* LLFloaterIMSessionTab::getCurSelectedViewModelItem() return conversationItem; } + +BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask ) +{ + if(mask == MASK_ALT) + { + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + if (KEY_RETURN == key && !isTornOff()) + { + floater_container->expandConversation(); + } + if ((KEY_UP == key) || (KEY_LEFT == key)) + { + floater_container->selectNextorPreviousConversation(false); + } + if ((KEY_DOWN == key ) || (KEY_RIGHT == key)) + { + floater_container->selectNextorPreviousConversation(true); + } + } + return TRUE; +} diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index e90fcbb806..b52bdfd8cd 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -95,8 +95,8 @@ public: void initBtns(); virtual void updateMessages() {} LLConversationItem* getCurSelectedViewModelItem(); - void forceReshape(); + virtual BOOL handleKeyHere( KEY key, MASK mask ); protected: diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index e6e93d81bc..e44a2cc4df 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2515,7 +2515,9 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) { // let Control-Up and Control-Down through for chat line history, if (!(key == KEY_UP && mask == MASK_CONTROL) - && !(key == KEY_DOWN && mask == MASK_CONTROL)) + && !(key == KEY_DOWN && mask == MASK_CONTROL) + && !(key == KEY_UP && mask == MASK_ALT) + && !(key == KEY_DOWN && mask == MASK_ALT)) { switch(key) { @@ -2607,7 +2609,10 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask) if ((uni_char == 13 && mask != MASK_CONTROL) || (uni_char == 3 && mask == MASK_NONE)) { - return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN)); + if (mask != MASK_ALT) + { + return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN)); + } } // let menus handle navigation (jump) keys -- cgit v1.2.3 From ae8f8c6999c4ccc396c4f329842e61592a59586e Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Fri, 1 Mar 2013 14:36:39 +0200 Subject: CHUI-794 FIXED Disable context menu options if you select yourself with other participants --- indra/newview/llfloaterimcontainer.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 49c30e8768..d6571845cc 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1213,6 +1213,15 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v return false; } + // If the user agent is selected with others, everything is disabled + for (uuid_vec_t::const_iterator id = uuids.begin(); id != uuids.end(); ++id) + { + if (gAgent.getID() == *id) + { + return false; + } + } + // Handle all other options if (("can_invite" == item) || ("can_chat_history" == item) || ("can_share" == item) || ("can_pay" == item)) { -- cgit v1.2.3 From 7b8822a24ae0a26228b975ebff3f22a0365ffd9e Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Thu, 28 Feb 2013 19:59:26 +0200 Subject: CHUI-795 FIXED 'Chat history' is enabled but not functional in context menu for friend in Conversation pane while all logs cleared. --- indra/newview/llfloaterimcontainer.cpp | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index d6571845cc..46ec1d510d 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1096,12 +1096,9 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command, } else if("chat_history" == command) { - const LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(conversationItem->getUUID()); - - if (NULL != session) + if (selectedIDS.size() > 0) { - const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID; - LLFloaterReg::showInstance("preview_conversation", session_id, true); + LLAvatarActions::viewChatHistory(selectedIDS.front()); } } else @@ -1165,15 +1162,9 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) } //Enable Chat history item for ad-hoc and group conversations - if ("can_chat_history" == item) + if ("can_chat_history" == item && uuids.size() > 0) { - if(getCurSelectedViewModelItem()) - { - if (getCurSelectedViewModelItem()->getType() != LLConversationItem::CONV_PARTICIPANT) - { - return isConversationLoggingAllowed(); - } - } + return LLLogChat::isTranscriptExist(uuids.front()); } // If nothing is selected(and selected item is not group chat), everything needs to be disabled -- cgit v1.2.3 From e42e6bc68ae0b0f7a0bd2ca6f500ba783cc201a3 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 1 Mar 2013 17:02:51 -0800 Subject: CHUI-807 : Fixed (attempt) : Defensive coding to prevent potential crash --- indra/llui/lltabcontainer.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 91527c68f2..0c43a571b8 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1483,6 +1483,8 @@ BOOL LLTabContainer::setTab(S32 which) for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { LLTabTuple* tuple = *iter; + if (!tuple) + continue; BOOL is_selected = ( tuple == selected_tuple ); tuple->mButton->setUseEllipses(mUseTabEllipses); tuple->mButton->setHAlign(mFontHalign); -- cgit v1.2.3 From 23ca3a1f2ce113cde94bdfea5fd794ecf808535e Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Mon, 4 Mar 2013 17:11:14 +0200 Subject: CHUI-806 (IM floater is not become as a top while geting message with enabled 'Open conversation window' option) --- indra/newview/llimview.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d69bd89f13..8f3f5145a9 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -273,7 +273,7 @@ void on_new_message(const LLSD& msg) } } - else if("openconversations" == action && !session_floater_is_open) + else if("openconversations" == action) { //User is not focused on conversation containing the message if(session_floater_not_focused) @@ -291,7 +291,8 @@ void on_new_message(const LLSD& msg) //useMostItrusiveIMNotification will be called to notify user a message exists if(session_id.notNull() && participant_id.notNull() - && gAgent.isDoNotDisturb()) + && gAgent.isDoNotDisturb() + && !session_floater_is_open) { LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); } -- cgit v1.2.3 From 19033255ee2952bd5ee1ebf6114b518548106f34 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 4 Mar 2013 19:10:40 +0200 Subject: CHUI-821 FIXED Conversation size regression when logging out with conversation list minimized to icons : save current conv. panel's width --- indra/newview/llfloaterimcontainer.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 46ec1d510d..8d630b9d50 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -764,6 +764,14 @@ void LLFloaterIMContainer::assignResizeLimits() S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0; S32 new_min_width = conv_pane_current_width + msg_pane_min_width + summary_width_of_visible_borders; + if (is_conv_pane_expanded) + { + // Save the conversations pane width. + gSavedPerAccountSettings.setS32( + "ConversationsListPaneWidth", + mConversationsPane->getRect().getWidth()); + } + setResizeLimits(new_min_width, getMinHeight()); } @@ -1947,10 +1955,10 @@ void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/) // Most of the time the user will never see this state. setMinimized(FALSE); - S32 conv_pane_width = mConversationsPane->getRect().getWidth(); - - // Save the conversations pane width before collapsing it. - gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", conv_pane_width); + // Save the conversations pane width. + gSavedPerAccountSettings.setS32( + "ConversationsListPaneWidth", + mConversationsPane->getRect().getWidth()); LLFloater::closeFloater(app_quitting); } -- cgit v1.2.3 From ce7db31b7f113967d1fb8033bb41261700fca109 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Mon, 4 Mar 2013 18:46:37 +0200 Subject: CHUI-822 FIXED Resizing conversation floater with conversation list minimized to icons sets to fixed width that cannot be reduced : set resize limits to conv.panel's minDim() when conv. panel is collapsed --- indra/newview/llfloaterimcontainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 8d630b9d50..413707baae 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -759,7 +759,7 @@ void LLFloaterIMContainer::assignResizeLimits() S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3); S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH; S32 conv_pane_current_width = is_msg_pane_expanded - ? mConversationsPane->getRect().getWidth() + ? (is_conv_pane_expanded? mConversationsPane->getRect().getWidth() : mConversationsPane->getMinDim()) : (is_conv_pane_expanded? mConversationsPane->getExpandedMinDim() : mConversationsPane->getMinDim()); S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0; S32 new_min_width = conv_pane_current_width + msg_pane_min_width + summary_width_of_visible_borders; -- cgit v1.2.3 From a26c1672235578f3a4e21be370b11522207e2c57 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Mon, 4 Mar 2013 20:05:35 +0200 Subject: CHUI-757 FIXED CHUI viewer shows Autopilot cancelled notification toast when interrupting click to walk: - The AutopilotCanceled notification was disabled for this viewer; --- indra/newview/skins/default/xui/en/notifications.xml | 8 -------- 1 file changed, 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 3ae9b206a4..9c81c877b5 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -9706,14 +9706,6 @@ There is no suitable surface to sit on, try another spot. No room to sit here, try another spot. </notification> - <notification - icon="alertmodal.tga" - name="AutopilotCanceled" - type="notify"> - <tag>fail</tag> -Autopilot canceled - </notification> - <notification icon="alertmodal.tga" name="ClaimObjectFailedNoPermission" -- cgit v1.2.3 From 9f965be297422ddab79ff9be47fb6d5c64a5096f Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 4 Mar 2013 10:11:51 -0800 Subject: CHUI-778: Now when changing paths for chat logs and transcripts any empty conversations will be reloaded with data from the new location. Use case for this is if the users nearby chat is empty and they switch to a location that has a nearby chat file, then the nearby chat file be loaded. --- indra/newview/llfloaterimnearbychat.h | 1 + indra/newview/llfloaterimsession.h | 1 + indra/newview/llfloaterimsessiontab.cpp | 21 +++++++++++++++++++++ indra/newview/llfloaterimsessiontab.h | 1 + indra/newview/llfloaterpreference.cpp | 7 ++++++- indra/newview/lllogchat.cpp | 32 ++++++++++++++++---------------- 6 files changed, 46 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index 2992c12436..4ad37eb0c7 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -69,6 +69,7 @@ public: LLChatEntry* getChatBox() { return mInputEditor; } std::string getCurrentChat(); + S32 getMessageArchiveLength() {return mMessageArchive.size();} virtual BOOL handleKeyHere( KEY key, MASK mask ); diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index 381b3cf721..cb330bca0f 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -133,6 +133,7 @@ public: static floater_showed_signal_t sIMFloaterShowedSignal; bool needsTitleOverwrite() { return mSessionNameUpdatedForTyping && mOtherTyping; } + S32 getLastChatMessageIndex() {return mLastMessageIndex;} private: /*virtual*/ void refresh(); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 6dbcdb4474..f773ed4e23 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -725,6 +725,27 @@ void LLFloaterIMSessionTab::processChatHistoryStyleUpdate(bool clean_messages/* } } +// static +void LLFloaterIMSessionTab::reloadEmptyFloaters() +{ + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); + iter != inst_list.end(); ++iter) + { + LLFloaterIMSession* floater = dynamic_cast<LLFloaterIMSession*>(*iter); + if (floater && floater->getLastChatMessageIndex() == -1) + { + floater->reloadMessages(true); + } + } + + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); + if (nearby_chat && nearby_chat->getMessageArchiveLength() == 0) + { + nearby_chat->reloadMessages(true); + } +} + void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive) { LLButton* voiceButton = getChild<LLButton>("voice_call_btn"); diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index e90fcbb806..b245049137 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -54,6 +54,7 @@ public: // reload all message with new settings of visual modes static void processChatHistoryStyleUpdate(bool clean_messages = false); + static void reloadEmptyFloaters(); /** * Returns true if chat is displayed in multi tabbed floater diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 988190f96a..3f8c23ba83 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -798,8 +798,13 @@ void LLFloaterPreference::onBtnOK() //Conversation transcript and log path changed so reload conversations based on new location if(mPriorInstantMessageLogPath.length()) { + if(moveTranscriptsAndLog()) + { + //When floaters are empty but have a chat history files, reload chat history into them + LLFloaterIMSessionTab::reloadEmptyFloaters(); + } //Couldn't move files so restore the old path and show a notification - if(!moveTranscriptsAndLog()) + else { gSavedPerAccountSettings.setString("InstantMessageLogPath", mPriorInstantMessageLogPath); LLNotificationsUtil::add("PreferenceChatPathChanged"); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 6562cfe1bb..448100c5d6 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -517,6 +517,22 @@ bool LLLogChat::moveTranscripts(const std::string originDirectory, backupFileCount = 0; newFullPath = targetDirectory + fullpath.substr(originDirectory.length(), std::string::npos); + //The target directory contains that file already, so lets store it + if(LLFile::isfile(newFullPath)) + { + backupFileName = newFullPath + ".backup"; + + //If needed store backup file as .backup1 etc. + while(LLFile::isfile(backupFileName)) + { + ++backupFileCount; + backupFileName = newFullPath + ".backup" + boost::lexical_cast<std::string>(backupFileCount); + } + + //Rename the file to its backup name so it is not overwritten + LLFile::rename(newFullPath, backupFileName); + } + S32 retry_count = 0; while (retry_count < 5) { @@ -528,22 +544,6 @@ bool LLLogChat::moveTranscripts(const std::string originDirectory, LL_WARNS("LLLogChat::moveTranscripts") << "Problem renaming " << fullpath << " - errorcode: " << result << " attempt " << retry_count << LL_ENDL; - //The target directory contains that file already, so lets store it - if(LLFile::isfile(newFullPath)) - { - backupFileName = newFullPath + ".backup"; - - //If needed store backup file as .backup1 etc. - while(LLFile::isfile(backupFileName)) - { - ++backupFileCount; - backupFileName = newFullPath + ".backup" + boost::lexical_cast<std::string>(backupFileCount); - } - - //Rename the file to its backup name so it is not overwritten - LLFile::rename(newFullPath, backupFileName); - } - ms_sleep(100); } else -- cgit v1.2.3 From f352c81f11f26dfe9fe2cf494407045bab41dabf Mon Sep 17 00:00:00 2001 From: "Graham Madarasz (Graham)" <graham@lindenlab.com> Date: Mon, 4 Mar 2013 14:18:49 -0800 Subject: For MAINT-2423 fix regression from CHUI merge. Code review: DaveP --- indra/newview/lldrawable.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 59c2f15dd9..ba1759f642 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -643,18 +643,9 @@ BOOL LLDrawable::updateMove() return FALSE; } - BOOL done; + makeActive(); - if (isState(MOVE_UNDAMPED)) - { - done = updateMoveUndamped(); - } - else - { - makeActive(); - done = updateMoveDamped(); - } - return done; + return isState(MOVE_UNDAMPED) ? updateMoveUndamped() : updateMoveDamped(); } BOOL LLDrawable::updateMoveUndamped() -- cgit v1.2.3 From a5861a4a49b06fe8e61c5d120df637062e10799d Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Tue, 5 Mar 2013 00:41:22 +0000 Subject: CHUI-772 FIX User sees no notification of conversation activity not visible in long scrolling conversation list Added call to setSelectedSession() from LLConversationViewParticipant::handleMouseDown() --- indra/newview/llconversationview.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 882ef64715..74b348cd81 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -567,6 +567,7 @@ BOOL LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask ) LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); + im_container->setSelectedSession(session_id); im_container->flashConversationItemWidget(session_id,false); im_container->selectFloater(session_floater); im_container->collapseMessagesPane(false); -- cgit v1.2.3 From 49319a90ef1fcca590e077805d5aaa65322a1a6d Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 4 Mar 2013 19:35:31 -0800 Subject: CHUI-778: Now when delete transcripts is pressed the backup files will be deleted as well. Also if clear logs is pressed then backup logs will be cleared. --- indra/newview/llconversationlog.cpp | 33 +++++++++++++++++++++++++++++++++ indra/newview/llconversationlog.h | 2 ++ indra/newview/lllogchat.cpp | 2 +- 3 files changed, 36 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 4be169e267..dd20ca15ae 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -28,9 +28,11 @@ #include "llagent.h" #include "llavatarnamecache.h" #include "llconversationlog.h" +#include "lldiriterator.h" #include "llnotificationsutil.h" #include "lltrans.h" +#include <boost/foreach.hpp> #include "boost/lexical_cast.hpp" const int CONVERSATION_LIFETIME = 30; // lifetime of LLConversation is 30 days by spec @@ -380,6 +382,36 @@ void LLConversationLog::cache() } } +void LLConversationLog::getListOfBackupLogs(std::vector<std::string>& list_of_backup_logs) +{ + // get Users log directory + std::string dirname = gDirUtilp->getPerAccountChatLogsDir(); + + // add final OS dependent delimiter + dirname += gDirUtilp->getDirDelimiter(); + + // create search pattern + std::string pattern = "conversation.log.backup*"; + + LLDirIterator iter(dirname, pattern); + std::string filename; + while (iter.next(filename)) + { + list_of_backup_logs.push_back(gDirUtilp->add(dirname, filename)); + } +} + +void LLConversationLog::deleteBackupLogs() +{ + std::vector<std::string> backup_logs; + getListOfBackupLogs(backup_logs); + + BOOST_FOREACH(const std::string& fullpath, backup_logs) + { + LLFile::remove(fullpath); + } +} + bool LLConversationLog::moveLog(const std::string &originDirectory, const std::string &targetDirectory) { @@ -575,5 +607,6 @@ void LLConversationLog::onClearLogResponse(const LLSD& notification, const LLSD& mConversations.clear(); notifyObservers(); cache(); + deleteBackupLogs(); } } diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 58e698de25..265b1f0ef0 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -138,6 +138,8 @@ public: */ void cache(); bool moveLog(const std::string &originDirectory, const std::string &targetDirectory); + void getListOfBackupLogs(std::vector<std::string>& list_of_backup_logs); + void deleteBackupLogs(); void onClearLog(); void onClearLogResponse(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 448100c5d6..7f4b925b53 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -453,7 +453,7 @@ void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_trans dirname += gDirUtilp->getDirDelimiter(); // create search pattern - std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION; + std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION + "*"; LLDirIterator iter(dirname, pattern); std::string filename; -- cgit v1.2.3 From 67741ae9786a88bb00f3419ad6a8ac8533481acb Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Tue, 5 Mar 2013 15:28:41 +0200 Subject: CHUI-815 FIXED Handle SHIFT+ENTER to whisper in Nearby chat --- indra/newview/llfloaterimnearbychat.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 02f54e76db..dfaf4bbdd6 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -353,6 +353,13 @@ BOOL LLFloaterIMNearbyChat::handleKeyHere( KEY key, MASK mask ) sendChat(CHAT_TYPE_SHOUT); handled = TRUE; } + else if (KEY_RETURN == key && mask == MASK_SHIFT) + { + // whisper + sendChat(CHAT_TYPE_WHISPER); + handled = TRUE; + } + if((mask == MASK_ALT) && isTornOff()) { -- cgit v1.2.3 From 477920b13834c977659d11d91d8f2d52e05f54b8 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Tue, 5 Mar 2013 15:40:31 +0200 Subject: CHUI-809 FIXED "Start IM" menu item is added --- indra/llui/lltextbase.cpp | 1 + indra/llui/llurlaction.cpp | 14 ++++++++++++++ indra/llui/llurlaction.h | 1 + indra/newview/skins/default/xui/en/menu_url_agent.xml | 7 +++++++ 4 files changed, 23 insertions(+) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 7cee9f5b46..4bb819a7f6 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1911,6 +1911,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url)); registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url)); registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url)); + registrar.add("Url.SendIM", boost::bind(&LLUrlAction::sendIM, url)); registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url)); registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url)); registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url)); diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp index fd9b3d9a6d..fd872eca4b 100644 --- a/indra/llui/llurlaction.cpp +++ b/indra/llui/llurlaction.cpp @@ -157,3 +157,17 @@ void LLUrlAction::showProfile(std::string url) } } } + +void LLUrlAction::sendIM(std::string url) +{ + LLURI uri(url); + LLSD path_array = uri.pathArray(); + if (path_array.size() == 4) + { + std::string id_str = path_array.get(2).asString(); + if (LLUUID::validate(id_str)) + { + executeSLURL("secondlife:///app/agent/" + id_str + "/im"); + } + } +} diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h index c34960b826..f5f2ceba72 100644 --- a/indra/llui/llurlaction.h +++ b/indra/llui/llurlaction.h @@ -76,6 +76,7 @@ public: /// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile static void showProfile(std::string url); + static void sendIM(std::string url); /// specify the callbacks to enable this class's functionality typedef boost::function<void (const std::string&)> url_callback_t; diff --git a/indra/newview/skins/default/xui/en/menu_url_agent.xml b/indra/newview/skins/default/xui/en/menu_url_agent.xml index 73f0fa7979..88ae441bd3 100644 --- a/indra/newview/skins/default/xui/en/menu_url_agent.xml +++ b/indra/newview/skins/default/xui/en/menu_url_agent.xml @@ -2,6 +2,13 @@ <context_menu layout="topleft" name="Url Popup"> + <menu_item_call + label="Send IM" + layout="topleft" + name="show_agent"> + <menu_item_call.on_click + function="Url.SendIM" /> + </menu_item_call> <menu_item_call label="Show Resident Profile" layout="topleft" -- cgit v1.2.3 From 84662ce63bea0d5ff8ff8bed0b12e4162a8514a5 Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Tue, 5 Mar 2013 18:54:43 +0200 Subject: CHUI-764 (Group Profile is not opened after selecting 'Show group information' in context menu of 'About Land' dialog) --- indra/newview/skins/default/xui/en/menu_url_group.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/menu_url_group.xml b/indra/newview/skins/default/xui/en/menu_url_group.xml index c5eaf94d22..2cb125ce09 100644 --- a/indra/newview/skins/default/xui/en/menu_url_group.xml +++ b/indra/newview/skins/default/xui/en/menu_url_group.xml @@ -7,7 +7,7 @@ layout="topleft" name="show_group"> <menu_item_call.on_click - function="Url.Execute" /> + function="Url.ShowProfile" /> </menu_item_call> <menu_item_separator layout="topleft" /> -- cgit v1.2.3 From 95cea4aa71b84fb203167084c51892f09520fd48 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 5 Mar 2013 13:20:24 -0800 Subject: CHUI-778: Adjusted deletion of transcripts/logs to be more clean code-wise. --- indra/newview/lllogchat.cpp | 22 ++++++++++++++++++---- indra/newview/lllogchat.h | 2 ++ 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 7f4b925b53..2d7454b636 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -444,7 +444,7 @@ std::string LLLogChat::oldLogFileName(std::string filename) } // static -void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_transcriptions) +void LLLogChat::findTranscriptFiles(std::string pattern, std::vector<std::string>& list_of_transcriptions) { // get Users log directory std::string dirname = gDirUtilp->getPerAccountChatLogsDir(); @@ -452,9 +452,6 @@ void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_trans // add final OS dependent delimiter dirname += gDirUtilp->getDirDelimiter(); - // create search pattern - std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION + "*"; - LLDirIterator iter(dirname, pattern); std::string filename; while (iter.next(filename)) @@ -490,6 +487,22 @@ void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_trans } } +// static +void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_transcriptions) +{ + // create search pattern + std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION; + findTranscriptFiles(pattern, list_of_transcriptions); +} + +// static +void LLLogChat::getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions) +{ + // create search pattern + std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION + ".backup*"; + findTranscriptFiles(pattern, list_of_transcriptions); +} + //static boost::signals2::connection LLLogChat::setSaveHistorySignal(const save_history_signal_t::slot_type& cb) { @@ -581,6 +594,7 @@ void LLLogChat::deleteTranscripts() { std::vector<std::string> list_of_transcriptions; getListOfTranscriptFiles(list_of_transcriptions); + getListOfTranscriptBackupFiles(list_of_transcriptions); BOOST_FOREACH(const std::string& fullpath, list_of_transcriptions) { diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index 784786a565..e819f00dd9 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -49,7 +49,9 @@ public: const std::string& from, const LLUUID& from_id, const std::string& line); + static void findTranscriptFiles(std::string pattern, std::vector<std::string>& list_of_transcriptions); static void getListOfTranscriptFiles(std::vector<std::string>& list); + static void getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions); static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD()); -- cgit v1.2.3 From f135503a9ed99f5e9b009a6608a9c4bc21c5e8cf Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 5 Mar 2013 13:41:30 -0800 Subject: CHUI-829 (Allow Conversations floater to display a different chat than the torn off and selected window): Now when selecting a torn off conversation this will not select the conversation line item. --- indra/newview/llfloaterimcontainer.cpp | 4 ++++ indra/newview/llfloaterimsessiontab.cpp | 7 ------- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 46ec1d510d..429ea09f56 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1392,6 +1392,10 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool // Switch to the conversation floater that is being selected selectFloater(session_floater); } + else + { + showStub(true); + } } // Set the focus on the selected floater diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index d3fcfbbc56..de1b398131 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -324,13 +324,6 @@ void LLFloaterIMSessionTab::onFocusReceived() } LLTransientDockableFloater::onFocusReceived(); - - LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container"); - if (container) - { - container->selectConversationPair(mSessionID, true); - container->showStub(! getHost()); - } } void LLFloaterIMSessionTab::onFocusLost() -- cgit v1.2.3 From 2ea750ebcad8335aeb0ec77a483831b62d05f643 Mon Sep 17 00:00:00 2001 From: "Graham Madarasz (Graham)" <graham@lindenlab.com> Date: Tue, 5 Mar 2013 13:47:02 -0800 Subject: For MAINT-2247 MAINT-1742 MAINT-2275 contrib from STORM-1934. --- indra/newview/lldrawable.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra') diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index ba1759f642..4b0d3b361d 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -577,6 +577,12 @@ F32 LLDrawable::updateXform(BOOL undamped) mVObjp->dirtySpatialGroup(); } } + else if (!isRoot() && + ((dist_vec_squared(old_pos, target_pos) > 0.f) + || (1.f - dot(old_rot, target_rot)) > 0.f)) + { //fix for BUG-840, MAINT-2275, MAINT-1742, MAINT-2247 + gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); + } else if (!getVOVolume() && !isAvatar()) { movePartition(); -- cgit v1.2.3 From 4a50271c19f584916c84abc117636f45fc050e61 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 6 Mar 2013 19:00:28 +0200 Subject: CHUI-821 Clean up code --- indra/newview/llfloaterimcontainer.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 413707baae..29ff037d59 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -758,11 +758,16 @@ void LLFloaterIMContainer::assignResizeLimits() // between the panels are merged into one S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3); S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH; - S32 conv_pane_current_width = is_msg_pane_expanded + S32 conv_pane_target_width = is_conv_pane_expanded? + (is_msg_pane_expanded? + mConversationsPane->getRect().getWidth() + : mConversationsPane->getExpandedMinDim()) + : mConversationsPane->getMinDim(); + S32 conv_pane_target_width = is_msg_pane_expanded ? (is_conv_pane_expanded? mConversationsPane->getRect().getWidth() : mConversationsPane->getMinDim()) : (is_conv_pane_expanded? mConversationsPane->getExpandedMinDim() : mConversationsPane->getMinDim()); S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0; - S32 new_min_width = conv_pane_current_width + msg_pane_min_width + summary_width_of_visible_borders; + S32 new_min_width = conv_pane_target_width + msg_pane_min_width + summary_width_of_visible_borders; if (is_conv_pane_expanded) { -- cgit v1.2.3 From 82c92ce5a97d6a83505c775348aef692e18e42ed Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 6 Mar 2013 19:02:19 +0200 Subject: CHUI-821 Clean up code --- indra/newview/llfloaterimcontainer.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 29ff037d59..a0c386717b 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -763,9 +763,6 @@ void LLFloaterIMContainer::assignResizeLimits() mConversationsPane->getRect().getWidth() : mConversationsPane->getExpandedMinDim()) : mConversationsPane->getMinDim(); - S32 conv_pane_target_width = is_msg_pane_expanded - ? (is_conv_pane_expanded? mConversationsPane->getRect().getWidth() : mConversationsPane->getMinDim()) - : (is_conv_pane_expanded? mConversationsPane->getExpandedMinDim() : mConversationsPane->getMinDim()); S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0; S32 new_min_width = conv_pane_target_width + msg_pane_min_width + summary_width_of_visible_borders; -- cgit v1.2.3 From d73ca40667527a1fdaf29ac3629ec7ce8a7e0f40 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Wed, 6 Mar 2013 17:43:10 -0800 Subject: CHUI-834 (Conversation selection in conversation list does not update when redocking torn off conversations): Now when click to dock a torn off floater, the correct conversation line item will be selected. --- indra/newview/llfloaterimsessiontab.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index de1b398131..164625fc95 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -798,6 +798,12 @@ void LLFloaterIMSessionTab::onTearOffClicked() { forceReshape(); } + //Upon re-docking the torn off floater, select the corresponding conversation line item + else + { + LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container"); + container->selectConversation(mSessionID); + } refreshConversation(); updateGearBtn(); } -- cgit v1.2.3 From 4458986cf22a749d3387085a70ea07930519b8ab Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 6 Mar 2013 18:44:02 -0800 Subject: CHUI-705 : Fixed! Force hide context menu when deleting line editor widget --- indra/llui/lllineeditor.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra') diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 2e64be89fa..6976b06a92 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -202,6 +202,14 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) LLLineEditor::~LLLineEditor() { mCommitOnFocusLost = FALSE; + + // Make sure no context menu linger around once the widget is deleted + LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get()); + if (menu) + { + menu->hide(); + } + setContextMenu(NULL); // calls onCommit() while LLLineEditor still valid gFocusMgr.releaseFocusIfNeeded( this ); -- cgit v1.2.3 From 8e924c850569b8aa2d2765c6514d742f51f3392b Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Thu, 7 Mar 2013 13:49:29 +0200 Subject: CHUI-823 ([CHUIBUG]Triple-clicking on the scroll back button in the CHUI causes all the conversation to be selected) --- indra/llui/lltextbase.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 7cee9f5b46..89d9f47dc2 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1086,7 +1086,14 @@ BOOL LLTextBase::handleRightMouseUp(S32 x, S32 y, MASK mask) BOOL LLTextBase::handleDoubleClick(S32 x, S32 y, MASK mask) { - mTripleClickTimer.setTimerExpirySec(TRIPLE_CLICK_INTERVAL); + //Don't start triple click timer if user have clicked on scrollbar + mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect(); + if (x >= mVisibleTextRect.mLeft && x <= mVisibleTextRect.mRight + && y >= mVisibleTextRect.mBottom && y <= mVisibleTextRect.mTop) + { + mTripleClickTimer.setTimerExpirySec(TRIPLE_CLICK_INTERVAL); + } + LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); if (cur_segment && cur_segment->handleDoubleClick(x, y, mask)) { -- cgit v1.2.3 From 014376b49a1e6bf41fa8b0f1b36c0c02fca3096e Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 7 Mar 2013 16:26:37 -0800 Subject: CHUI-832 (Different conversation than is selected shown in message panel after tearing off conversation): Now when a conversation is torn off an adjacent conversation is selected (but not focused). --- indra/newview/llfloaterimcontainer.cpp | 21 ++++++++++++++------- indra/newview/llfloaterimcontainer.h | 3 ++- indra/newview/llfloaterimsessiontab.cpp | 4 +++- 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 5a37b5b57b..d67f2be658 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1912,7 +1912,19 @@ BOOL LLFloaterIMContainer::handleKeyHere(KEY key, MASK mask ) return TRUE; } -bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next) +bool LLFloaterIMContainer::selectAdjacentConversation(bool focus_selected) +{ + bool selectedAdjacentConversation = selectNextorPreviousConversation(true, focus_selected); + + if(!selectedAdjacentConversation) + { + selectedAdjacentConversation = selectNextorPreviousConversation(false, focus_selected); + } + + return selectedAdjacentConversation; +} + +bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next, bool focus_selected) { if (mConversationsWidgets.size() > 1) { @@ -1933,12 +1945,7 @@ bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next) LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem()); if (vmi) { - selectConversationPair(vmi->getUUID(), true); - LLFloater* floaterp = get_ptr_in_map(mSessions, getSelectedSession()); - if(floaterp && !floaterp->isTornOff()) - { - setFocus(TRUE); - } + selectConversationPair(vmi->getUUID(), true, focus_selected); return true; } } diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index c84d4978ec..1e760a8710 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -72,7 +72,8 @@ public: void selectNextConversationByID(const LLUUID& session_id); BOOL selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater = true); void clearAllFlashStates(); - bool selectNextorPreviousConversation(bool select_next); + bool selectAdjacentConversation(bool focus_selected); + bool selectNextorPreviousConversation(bool select_next, bool focus_selected = true); void expandConversation(); /*virtual*/ void tabClose(); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 164625fc95..faeb860712 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -794,14 +794,16 @@ void LLFloaterIMSessionTab::onTearOffClicked() mSaveRect = isTornOff(); initRectControl(); LLFloater::onClickTearOff(this); + LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container"); + if (isTornOff()) { + container->selectAdjacentConversation(false); forceReshape(); } //Upon re-docking the torn off floater, select the corresponding conversation line item else { - LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container"); container->selectConversation(mSessionID); } refreshConversation(); -- cgit v1.2.3 From 228d868cf6b3436f9cace3db5bd304e7ea639609 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Fri, 8 Mar 2013 02:02:45 +0000 Subject: CHUI-772 FIX User sees no notification of conversation activity not visible in long scrolling conversation list Added call to mConversationsRoot->arrange() in LLFloaterIMContainer::isScrolledOutOfSight() --- indra/newview/llconversationview.cpp | 15 +++++++++------ indra/newview/llfloaterimcontainer.cpp | 3 +++ 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 74b348cd81..837389aed5 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -104,6 +104,15 @@ LLConversationViewSession::~LLConversationViewSession() void LLConversationViewSession::setFlashState(bool flash_state) { + if (flash_state && !mFlashStateOn) + { + // flash chat toolbar button if scrolled out of sight (because flashing will not be visible) + if (mContainer->isScrolledOutOfSight(this)) + { + gToolBarView->flashCommand(LLCommandId("chat"), true); + } + } + mFlashStateOn = flash_state; mFlashStarted = false; mFlashTimer->stopFlashing(); @@ -115,12 +124,6 @@ void LLConversationViewSession::startFlashing() { mFlashStarted = true; mFlashTimer->startFlashing(); - - // flash chat toolbar button if scrolled out of sight (because flashing will not be visible) - if (mContainer->isScrolledOutOfSight(this)) - { - gToolBarView->flashCommand(LLCommandId("chat"), true); - } } } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 74490b695c..e2b9723537 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1881,6 +1881,9 @@ bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conve { llassert(conversation_item_widget != NULL); + // make sure the widget is actually in the right spot first + mConversationsRoot->arrange(NULL, NULL); + // check whether the widget is in the visible portion of the scroll container LLRect widget_rect; conversation_item_widget->localRectToOtherView(conversation_item_widget->getLocalRect(), &widget_rect, mConversationsRoot); -- cgit v1.2.3 From 24e650b4039d3b3515109fa9e271abfa2a2ebd6a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 8 Mar 2013 18:34:40 -0800 Subject: CHUI-835 (ctrl-h does not select nearby chat conversation in list): Modified setVisibleAndFrontMost() to now take a arguement for the key that was pressed (if one was pressed). This allows the floater to select the converation line item when becoming visible/frontmost. --- indra/llui/llfloater.cpp | 2 +- indra/llui/llfloater.h | 2 +- indra/llui/llfloaterreg.cpp | 10 +++++----- indra/newview/llfloaterimnearbychat.cpp | 11 +++++++++++ indra/newview/llfloaterimnearbychat.h | 1 + 5 files changed, 19 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 27dd7f5b32..09e27a264a 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1621,7 +1621,7 @@ void LLFloater::bringToFront( S32 x, S32 y ) // virtual -void LLFloater::setVisibleAndFrontmost(BOOL take_focus) +void LLFloater::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key) { LLMultiFloater* hostp = getHost(); if (hostp) diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index cb5bf28db3..4dba1e645f 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -305,7 +305,7 @@ public: /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); // do not override void setFrontmost(BOOL take_focus = TRUE); - virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE); + virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD()); // Defaults to false. virtual BOOL canSaveAs() const { return FALSE; } diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index c20d863612..1cdddf0d5b 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -488,12 +488,12 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& { host->setMinimized(FALSE); instance->openFloater(key); - instance->setVisibleAndFrontmost(); + instance->setVisibleAndFrontmost(true, key); } else if (!instance->getVisible()) { instance->openFloater(key); - instance->setVisibleAndFrontmost(); + instance->setVisibleAndFrontmost(true, key); instance->setFocus(TRUE); } else @@ -506,16 +506,16 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& if (instance->isMinimized()) { instance->setMinimized(FALSE); - instance->setVisibleAndFrontmost(); + instance->setVisibleAndFrontmost(true, key); } else if (!instance->isShown()) { instance->openFloater(key); - instance->setVisibleAndFrontmost(); + instance->setVisibleAndFrontmost(true, key); } else if (!instance->isFrontmost()) { - instance->setVisibleAndFrontmost(); + instance->setVisibleAndFrontmost(true, key); } else { diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index dfaf4bbdd6..cfee5001a6 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -257,6 +257,17 @@ void LLFloaterIMNearbyChat::setVisible(BOOL visible) } } + +void LLFloaterIMNearbyChat::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key) +{ + LLFloaterIMSessionTab::setVisibleAndFrontmost(take_focus, key); + + if(!isTornOff() && matchesKey(key)) + { + LLFloaterIMContainer::getInstance()->selectConversationPair(mSessionID, true, false); + } +} + // virtual void LLFloaterIMNearbyChat::onTearOffClicked() { diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index 4ad37eb0c7..05b48cccb0 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -54,6 +54,7 @@ public: /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD()); /*virtual*/ void closeHostedFloater(); void loadHistory(); -- cgit v1.2.3 From 7f5dee6161c6eed96275722cbb52a3fb1fcb3eb7 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 7 Mar 2013 17:31:44 +0200 Subject: CHUI-738 FIXED Your own nametag disappears - mysteriously: reset display time when nametag is changes --- indra/newview/llvoavatar.cpp | 81 ++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 40 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 157be08f45..c74d9f1292 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2994,43 +2994,43 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) return; } - BOOL new_name = FALSE; - if (visible_chat != mVisibleChat) + BOOL new_name = FALSE; + if (visible_chat != mVisibleChat) + { + mVisibleChat = visible_chat; + new_name = TRUE; + } + + if (sRenderGroupTitles != mRenderGroupTitles) + { + mRenderGroupTitles = sRenderGroupTitles; + new_name = TRUE; + } + + // First Calculate Alpha + // If alpha > 0, create mNameText if necessary, otherwise delete it + F32 alpha = 0.f; + if (mAppAngle > 5.f) + { + const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; + if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) { - mVisibleChat = visible_chat; - new_name = TRUE; + alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; } - - if (sRenderGroupTitles != mRenderGroupTitles) + else { - mRenderGroupTitles = sRenderGroupTitles; - new_name = TRUE; + // ...not fading, full alpha + alpha = 1.f; } - - // First Calculate Alpha - // If alpha > 0, create mNameText if necessary, otherwise delete it - F32 alpha = 0.f; - if (mAppAngle > 5.f) - { - const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; - if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) - { - alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; - } - else - { - // ...not fading, full alpha - alpha = 1.f; - } - } - else if (mAppAngle > 2.f) - { - // far away is faded out also - alpha = (mAppAngle-2.f)/3.f; - } + } + else if (mAppAngle > 2.f) + { + // far away is faded out also + alpha = (mAppAngle-2.f)/3.f; + } if (alpha <= 0.f) - { + { if (mNameText) { mNameText->markDead(); @@ -3040,19 +3040,19 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) return; } - if (!mNameText) - { + if (!mNameText) + { mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject( LLHUDObject::LL_HUD_NAME_TAG) ); //mNameText->setMass(10.f); - mNameText->setSourceObject(this); + mNameText->setSourceObject(this); mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); - mNameText->setVisibleOffScreen(TRUE); - mNameText->setMaxLines(11); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - sNumVisibleChatBubbles++; - new_name = TRUE; - } + mNameText->setVisibleOffScreen(TRUE); + mNameText->setMaxLines(11); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + sNumVisibleChatBubbles++; + new_name = TRUE; + } idleUpdateNameTagPosition(root_pos_last); idleUpdateNameTagText(new_name); @@ -3303,6 +3303,7 @@ void LLVOAvatar::clearNameTag() mNameText->setLabel(""); mNameText->setString( "" ); } + mTimeVisible.reset(); } //static -- cgit v1.2.3 From f51a39574722ffaea5912a084b02f8f22972e81c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 7 Mar 2013 15:59:51 +0200 Subject: CHUI-821 ADD FIX Conversation size regression when logging out with conversation list minimized to icons: deleted redundant savings of the convers. panel width; added a manually reshape of the conv. panel after change it's collapse state; function with uninformative name "updateState" was renamed to "reshapeFloaterAndSetResizeLimits" --- indra/newview/llfloaterimcontainer.cpp | 49 ++++++++++++++++------------------ indra/newview/llfloaterimcontainer.h | 4 +-- 2 files changed, 25 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index cdffdcf806..7437dd8cda 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -226,10 +226,11 @@ BOOL LLFloaterIMContainer::postBuild() childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this)); collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); - collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); + collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed"), false); LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false)); mMicroChangedSignal = LLVoiceClient::getInstance()->MicroChangedCallback(boost::bind(&LLFloaterIMContainer::updateSpeakBtnState, this)); - if (! mMessagesPane->isCollapsed()) + + if (! mMessagesPane->isCollapsed() && ! mConversationsPane->isCollapsed()) { S32 conversations_panel_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"); LLRect conversations_panel_rect = mConversationsPane->getRect(); @@ -668,7 +669,7 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse) // Make sure layout is updated before resizing conversation pane. mConversationsStack->updateLayout(); - updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); + reshapeFloaterAndSetResizeLimits(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); if (!collapse) { @@ -677,7 +678,7 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse) } } -void LLFloaterIMContainer::collapseConversationsPane(bool collapse) +void LLFloaterIMContainer::collapseConversationsPane(bool collapse, bool save_is_allowed /*=true*/) { if (mConversationsPane->isCollapsed() == collapse) { @@ -691,7 +692,7 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) // Save current width of Conversation panel before collapsing/expanding right pane. S32 conv_pane_width = mConversationsPane->getRect().getWidth(); - if (collapse) + if (collapse && save_is_allowed) { // Save the conversations pane width before collapsing it. gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", conv_pane_width); @@ -701,10 +702,18 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) } mConversationsStack->collapsePanel(mConversationsPane, collapse); + if (!collapse) + { + // Make sure layout is updated before resizing conversation pane. + mConversationsStack->updateLayout(); + // Restore conversation's pane previous width. + mConversationsPane->setTargetDim(gSavedPerAccountSettings.getS32("ConversationsListPaneWidth")); + } - S32 delta_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - mConversationsPane->getMinDim(); + S32 delta_width = + gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - mConversationsPane->getMinDim(); - updateState(collapse, delta_width); + reshapeFloaterAndSetResizeLimits(collapse, delta_width); for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); widget_it != mConversationsWidgets.end(); ++widget_it) @@ -724,21 +733,20 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) } } -void LLFloaterIMContainer::updateState(bool collapse, S32 delta_width) +void LLFloaterIMContainer::reshapeFloaterAndSetResizeLimits(bool collapse, S32 delta_width) { LLRect floater_rect = getRect(); floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); // Set by_user = true so that reshaped rect is saved in user_settings. setShape(floater_rect, true); - updateResizeLimits(); - bool is_left_pane_expanded = !mConversationsPane->isCollapsed(); - bool is_right_pane_expanded = !mMessagesPane->isCollapsed(); + bool at_least_one_panel_is_expanded = + ! (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed()); - setCanResize(is_left_pane_expanded || is_right_pane_expanded); - setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); + setCanResize(at_least_one_panel_is_expanded); + setCanMinimize(at_least_one_panel_is_expanded); assignResizeLimits(); @@ -767,15 +775,9 @@ void LLFloaterIMContainer::assignResizeLimits() S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0; S32 new_min_width = conv_pane_target_width + msg_pane_min_width + summary_width_of_visible_borders; - if (is_conv_pane_expanded) - { - // Save the conversations pane width. - gSavedPerAccountSettings.setS32( - "ConversationsListPaneWidth", - mConversationsPane->getRect().getWidth()); - } - setResizeLimits(new_min_width, getMinHeight()); + + mConversationsStack->updateLayout(); } void LLFloaterIMContainer::onAddButtonClicked() @@ -1972,11 +1974,6 @@ void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/) // Most of the time the user will never see this state. setMinimized(FALSE); - // Save the conversations pane width. - gSavedPerAccountSettings.setS32( - "ConversationsListPaneWidth", - mConversationsPane->getRect().getWidth()); - LLFloater::closeFloater(app_quitting); } diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 1e760a8710..5139651d8d 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -129,9 +129,9 @@ private: void processParticipantsStyleUpdate(); void onSpeakButtonClicked(); - void collapseConversationsPane(bool collapse); + void collapseConversationsPane(bool collapse, bool save_is_allowed=true); - void updateState(bool collapse, S32 delta_width); + void reshapeFloaterAndSetResizeLimits(bool collapse, S32 delta_width); void onAddButtonClicked(); void onAvatarPicked(const uuid_vec_t& ids); -- cgit v1.2.3 From 11199f2bef65f67f3ddd798944cb4ad62affa8ed Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Thu, 7 Mar 2013 17:04:06 +0200 Subject: CHUI-824 FIXED Open Message panel when session is activated. --- indra/newview/llfloaterimcontainer.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a0c386717b..74490b695c 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -114,6 +114,7 @@ void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::str void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { selectConversationPair(session_id, true); + collapseMessagesPane(false); } void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) -- cgit v1.2.3 From d29bec7f4d390b932705ac9342f01f0b2412dd97 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 8 Mar 2013 19:04:01 -0800 Subject: CHUI-793 : WIP : Limit the number of participants we load on groups when we load from the local group data --- indra/newview/llspeakers.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 05df7261e1..301b489c34 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -409,12 +409,10 @@ void LLSpeakerMgr::update(BOOL resort_ok) // update status of all current speakers BOOL voice_channel_active = (!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive()); - for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end();) + for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); speaker_it++) { LLUUID speaker_id = speaker_it->first; LLSpeaker* speakerp = speaker_it->second; - - speaker_map_t::iterator cur_speaker_it = speaker_it++; if (voice_channel_active && LLVoiceClient::getInstance()->getVoiceEnabled(speaker_id)) { @@ -551,18 +549,25 @@ void LLSpeakerMgr::updateSpeakerList() { // Add group members when we get the complete list (note: can take a while before we get that list) LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin(); + S32 updated = 0; while (member_it != gdatap->mMembers.end()) { LLGroupMemberData* member = member_it->second; - // Add only the members who are online - if (member->getOnlineStatus() == "Online") + LLUUID id = member_it->first; + // Add only members who are online and not already in the list + if ((member->getOnlineStatus() == "Online") && (mSpeakers.find(id) == mSpeakers.end())) { - LLPointer<LLSpeaker> speakerp = setSpeaker(member_it->first, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + LLPointer<LLSpeaker> speakerp = setSpeaker(id, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); speakerp->mIsModerator = ((member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR); + updated++; } ++member_it; + // Limit the number of "manually updated" participants to a reasonable number to avoid severe fps drop + // *TODO : solve the perf issue of having several hundreds of widgets in the conversation list + if (updated >= 100) + break; } - mSpeakerListUpdated = true; + mSpeakerListUpdated = true; } } else if (mSpeakers.size() == 0) -- cgit v1.2.3 From 40f61ae60091909bae8229b7d0496154a87fefbf Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Mon, 11 Mar 2013 12:32:34 +0200 Subject: CHUI-840 (Right clicking on unselected group conversation can have unpredictable results for menu options) --- indra/newview/llconversationview.cpp | 36 +++++++++++++++++++++++++++--------- indra/newview/llconversationview.h | 2 ++ 2 files changed, 29 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 74b348cd81..85c9a11b43 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -254,20 +254,38 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) //This node (conversation) was selected and a child (participant) was not if(result && getRoot()) { - if(getRoot()->getCurSelectedItem() == this) - { - LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem()); - LLUUID session_id = item? item->getUUID() : LLUUID(); + selectConversationItem(); + } - LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); - im_container->flashConversationItemWidget(session_id,false); - im_container->selectConversationPair(session_id, false); - im_container->collapseMessagesPane(false); - } + return result; +} + +BOOL LLConversationViewSession::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + BOOL result = LLFolderViewFolder::handleRightMouseDown(x, y, mask); + + if(result) + { + selectConversationItem(); } + return result; } +void LLConversationViewSession::selectConversationItem() +{ + if(getRoot()->getCurSelectedItem() == this) + { + LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem()); + LLUUID session_id = item? item->getUUID() : LLUUID(); + + LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + im_container->flashConversationItemWidget(session_id,false); + im_container->selectConversationPair(session_id, false); + im_container->collapseMessagesPane(false); + } +} + // virtual S32 LLConversationViewSession::arrange(S32* width, S32* height) { diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 76d3d079ea..3eb2e63792 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -68,6 +68,7 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void draw(); /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); /*virtual*/ S32 arrange(S32* width, S32* height); @@ -90,6 +91,7 @@ private: void onCurrentVoiceSessionChanged(const LLUUID& session_id); void startFlashing(); + void selectConversationItem(); LLPanel* mItemPanel; LLPanel* mCallIconLayoutPanel; -- cgit v1.2.3 From d2a689be4aee7487a18183d6208c52dc15c39051 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Mon, 11 Mar 2013 15:30:49 +0200 Subject: CHUI-815 FIXED Display whispered text in italics and shouted text as bold --- indra/newview/llchathistory.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index c4f63d9256..0152571e20 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -820,6 +820,15 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL body_message_params.font.style = "ITALIC"; } + if(chat.mChatType == CHAT_TYPE_WHISPER) + { + body_message_params.font.style = "ITALIC"; + } + else if(chat.mChatType == CHAT_TYPE_SHOUT) + { + body_message_params.font.style = "BOLD"; + } + bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY; // We graying out chat history by graying out messages that contains full date in a time string if (message_from_log) -- cgit v1.2.3 From 9fb00841669ed75479b57cccaa124747d09bbf97 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Mon, 11 Mar 2013 14:52:15 +0200 Subject: CHUI-836 FIXED [CHUIBUG]Opening chat history from the conversation log sometimes crashes the viewer --- indra/newview/llconversationloglist.cpp | 69 ++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 96b225b841..b202cfc9d3 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -198,6 +198,8 @@ void LLConversationLogList::refresh() void LLConversationLogList::rebuildList() { + const LLConversation * selected_conversationp = getSelectedConversation(); + clear(); bool have_filter = !mNameFilter.empty(); @@ -214,7 +216,12 @@ void LLConversationLogList::rebuildList() addNewItem(&*iter); } - + + // try to restore selection of item + if (NULL != selected_conversationp) + { + selectItemByUUID(selected_conversationp->getSessionID()); + } bool logging_enabled = log_instance.getIsLoggingEnabled(); bool log_empty = log_instance.isLogEmpty(); @@ -238,8 +245,16 @@ void LLConversationLogList::rebuildList() void LLConversationLogList::onCustomAction(const LLSD& userdata) { + const LLConversation * selected_conversationp = getSelectedConversation(); + + if (NULL == selected_conversationp) + { + return; + } + const std::string command_name = userdata.asString(); - const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); + const LLUUID& selected_conversation_participant_id = selected_conversationp->getParticipantID(); + const LLUUID& selected_conversation_session_id = selected_conversationp->getSessionID(); LLIMModel::LLIMSession::SType stype = getSelectedSessionType(); if ("im" == command_name) @@ -247,11 +262,11 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata) switch (stype) { case LLIMModel::LLIMSession::P2P_SESSION: - LLAvatarActions::startIM(selected_id); + LLAvatarActions::startIM(selected_conversation_participant_id); break; case LLIMModel::LLIMSession::GROUP_SESSION: - LLGroupActions::startIM(getSelectedConversation()->getSessionID()); + LLGroupActions::startIM(selected_conversation_session_id); break; default: @@ -263,11 +278,11 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata) switch (stype) { case LLIMModel::LLIMSession::P2P_SESSION: - LLAvatarActions::startCall(selected_id); + LLAvatarActions::startCall(selected_conversation_participant_id); break; case LLIMModel::LLIMSession::GROUP_SESSION: - LLGroupActions::startCall(getSelectedConversation()->getSessionID()); + LLGroupActions::startCall(selected_conversation_session_id); break; default: @@ -279,11 +294,11 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata) switch (stype) { case LLIMModel::LLIMSession::P2P_SESSION: - LLAvatarActions::showProfile(selected_id); + LLAvatarActions::showProfile(selected_conversation_participant_id); break; case LLIMModel::LLIMSession::GROUP_SESSION: - LLGroupActions::show(getSelectedConversation()->getSessionID()); + LLGroupActions::show(selected_conversation_session_id); break; default: @@ -292,52 +307,53 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata) } else if ("chat_history" == command_name) { - const LLUUID& session_id = getSelectedConversation()->getSessionID(); - LLFloaterReg::showInstance("preview_conversation", session_id, true); + LLFloaterReg::showInstance("preview_conversation", selected_conversation_session_id, true); } else if ("offer_teleport" == command_name) { - LLAvatarActions::offerTeleport(selected_id); + LLAvatarActions::offerTeleport(selected_conversation_participant_id); } else if("add_friend" == command_name) { - if (!LLAvatarActions::isFriend(selected_id)) + if (!LLAvatarActions::isFriend(selected_conversation_participant_id)) { - LLAvatarActions::requestFriendshipDialog(selected_id); + LLAvatarActions::requestFriendshipDialog(selected_conversation_participant_id); } } else if("remove_friend" == command_name) { - if (LLAvatarActions::isFriend(selected_id)) + if (LLAvatarActions::isFriend(selected_conversation_participant_id)) { - LLAvatarActions::removeFriendDialog(selected_id); + LLAvatarActions::removeFriendDialog(selected_conversation_participant_id); } } else if ("invite_to_group" == command_name) { - LLAvatarActions::inviteToGroup(selected_id); + LLAvatarActions::inviteToGroup(selected_conversation_participant_id); } else if ("show_on_map" == command_name) { - LLAvatarActions::showOnMap(selected_id); + LLAvatarActions::showOnMap(selected_conversation_participant_id); } else if ("share" == command_name) { - LLAvatarActions::share(selected_id); + LLAvatarActions::share(selected_conversation_participant_id); } else if ("pay" == command_name) { - LLAvatarActions::pay(selected_id); + LLAvatarActions::pay(selected_conversation_participant_id); } else if ("block" == command_name) { - LLAvatarActions::toggleBlock(selected_id); + LLAvatarActions::toggleBlock(selected_conversation_participant_id); } } bool LLConversationLogList::isActionEnabled(const LLSD& userdata) { - if (numSelected() != 1) + const LLConversation * selected_conversationp = getSelectedConversation(); + + if (NULL == selected_conversationp || numSelected() > 1) { return false; } @@ -345,7 +361,7 @@ bool LLConversationLogList::isActionEnabled(const LLSD& userdata) const std::string command_name = userdata.asString(); LLIMModel::LLIMSession::SType stype = getSelectedSessionType(); - const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); + const LLUUID& selected_id = selected_conversationp->getParticipantID(); bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == stype; bool is_group = LLIMModel::LLIMSession::GROUP_SESSION == stype; @@ -384,9 +400,16 @@ bool LLConversationLogList::isActionEnabled(const LLSD& userdata) bool LLConversationLogList::isActionChecked(const LLSD& userdata) { + const LLConversation * selected_conversationp = getSelectedConversation(); + + if (NULL == selected_conversationp) + { + return false; + } + const std::string command_name = userdata.asString(); - const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); + const LLUUID& selected_id = selected_conversationp->getParticipantID(); bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == getSelectedSessionType(); if ("is_blocked" == command_name) -- cgit v1.2.3 From 6b067125a0d338c3acc6fd1c786620e474a80aa8 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 11 Mar 2013 14:49:24 -0700 Subject: CHUI-778: Adjusted text in prompts for deleting chat log and chat transcripts (per UX). --- indra/newview/llfloaterpreference.cpp | 5 ++++- indra/newview/skins/default/xui/en/notifications.xml | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 3f8c23ba83..b308a820b2 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1667,7 +1667,10 @@ void LLFloaterPreference::onClickActionChange() void LLFloaterPreference::onDeleteTranscripts() { - LLNotificationsUtil::add("PreferenceChatDeleteTranscripts", LLSD(), LLSD(), boost::bind(&LLFloaterPreference::onDeleteTranscriptsResponse, this, _1, _2)); + LLSD args; + args["FOLDER"] = gDirUtilp->getUserName(); + + LLNotificationsUtil::add("PreferenceChatDeleteTranscripts", args, LLSD(), boost::bind(&LLFloaterPreference::onDeleteTranscriptsResponse, this, _1, _2)); } void LLFloaterPreference::onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response) diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 88c02fc84e..c681e39002 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -9998,7 +9998,7 @@ Cannot create large prims that intersect other players. Please re-try when othe icon="alertmodal.tga" name="PreferenceChatClearLog" type="alertmodal"> - This will delete the log of previous conversations. Proceed? + This will delete the logs of previous conversations, and any backups of that file. <tag>confirm</tag> <usetemplate ignoretext="Confirm before I delete the log of previous conversations." @@ -10011,7 +10011,7 @@ Cannot create large prims that intersect other players. Please re-try when othe icon="alertmodal.tga" name="PreferenceChatDeleteTranscripts" type="alertmodal"> - This will delete transcripts for all previous conversations. The list of conversations will not be affected. If you run scripts on your chat transcript files, you may want to proceed with caution. Proceed? + This will delete the transcripts for all previous conversations. The list of past conversations will not be affected. All files with the suffixes .txt and txt.backup in the folder [FOLDER] will be deleted. <tag>confirm</tag> <usetemplate ignoretext="Confirm before I delete transcripts." -- cgit v1.2.3 From e5aa9088f01f8689e19be82e3caa56fffbab85c1 Mon Sep 17 00:00:00 2001 From: merov_linden <none@none> Date: Mon, 11 Mar 2013 14:59:53 -0700 Subject: CHUI-810 : Merged Marine Kelley's patch on selected text and use of return key in chat --- indra/llui/llchatentry.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'indra') diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index 8e9c6555c3..9e48dcde7e 100644 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -169,6 +169,15 @@ BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask) { BOOL handled = FALSE; + // In the case of a chat entry, pressing RETURN when something is selected + // should NOT erase the selection (unlike a notecard, for example) + if (key == KEY_RETURN) + { + endOfDoc(); + startSelection(); + endSelection(); + } + LLTextEditor::handleSpecialKey(key, mask); switch(key) -- cgit v1.2.3 From e7a4cce3566988d5b58dc070196a32844d705318 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Tue, 12 Mar 2013 00:41:35 +0200 Subject: CHUI-846 FIXED [crashhunters] crash in LLFontGL::maxDrawableChars --- indra/llrender/llfontgl.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra') diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 647512eb2e..8772779645 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -599,6 +599,11 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch if(!fgi) { fgi = mFontFreetype->getGlyphInfo(wch); + + if (NULL == fgi) + { + return 0; + } } // account for glyphs that run beyond the starting point for the next glyphs -- cgit v1.2.3 From ac63601a2aeb05f67d6be87d7ad40495bbc3080b Mon Sep 17 00:00:00 2001 From: merov <none@none> Date: Mon, 11 Mar 2013 21:32:40 -0700 Subject: CHUI-793 : Fixed! Introduced ChatLoadGroupTimeout and ChatLoadGroupMaxMembers to mitigate slow group loading. --- indra/newview/app_settings/settings.xml | 22 ++++++++++++++++++++++ indra/newview/llspeakers.cpp | 11 ++++++++--- indra/newview/llspeakers.h | 1 + 3 files changed, 31 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 79376f7467..e216c7865d 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1584,6 +1584,28 @@ <key>Value</key> <integer>0</integer> </map> + <key>ChatLoadGroupMaxMembers</key> + <map> + <key>Comment</key> + <string>Max number of active members we'll show up for an unresponsive group</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <real>100</real> + </map> + <key>ChatLoadGroupTimeout</key> + <map> + <key>Comment</key> + <string>Time we give the server to send group participants before we hit the server for group info (seconds)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>10.0</real> + </map> <key>ChatOnlineNotification</key> <map> <key>Comment</key> diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 301b489c34..8783d99b11 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -38,6 +38,8 @@ #include "llvoavatar.h" #include "llworld.h" +extern LLControlGroup gSavedSettings; + const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f); const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f); @@ -311,6 +313,7 @@ LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) : mModerateModeHandledFirstTime(false), mSpeakerListUpdated(false) { + mGetListTime.reset(); static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0); mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay); @@ -537,18 +540,20 @@ void LLSpeakerMgr::updateSpeakerList() LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); if (session->isGroupSessionType() && (mSpeakers.size() <= 1)) { + const F32 load_group_timeout = gSavedSettings.getF32("ChatLoadGroupTimeout"); // For groups, we need to hit the group manager. // Note: The session uuid and the group uuid are actually one and the same. If that was to change, this will fail. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id); - if (!gdatap) + if (!gdatap && (mGetListTime.getElapsedTimeF32() >= load_group_timeout)) { // Request the data the first time around LLGroupMgr::getInstance()->sendCapGroupMembersRequest(session_id); } - else if (gdatap->isMemberDataComplete() && !gdatap->mMembers.empty()) + else if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty()) { // Add group members when we get the complete list (note: can take a while before we get that list) LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin(); + const S32 load_group_max_members = gSavedSettings.getS32("ChatLoadGroupMaxMembers"); S32 updated = 0; while (member_it != gdatap->mMembers.end()) { @@ -564,7 +569,7 @@ void LLSpeakerMgr::updateSpeakerList() ++member_it; // Limit the number of "manually updated" participants to a reasonable number to avoid severe fps drop // *TODO : solve the perf issue of having several hundreds of widgets in the conversation list - if (updated >= 100) + if (updated >= load_group_max_members) break; } mSpeakerListUpdated = true; diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 5f5095097e..e953dd0e1a 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -264,6 +264,7 @@ protected: typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t; speaker_map_t mSpeakers; bool mSpeakerListUpdated; + LLTimer mGetListTime; speaker_list_t mSpeakersSorted; LLFrameTimer mSpeechTimer; -- cgit v1.2.3 From d81226f1707a93b6be52264fc00cae9c60057cc5 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Tue, 12 Mar 2013 15:38:10 +0200 Subject: CHUI-809 FIXED Changes in menu items to make them consistent. Do not start IM if selected person is self. --- indra/llui/lltextbase.cpp | 1 + indra/llui/llurlaction.cpp | 31 +++++++++++++++++----- indra/llui/llurlaction.h | 2 ++ indra/newview/llavataractions.cpp | 2 +- indra/newview/llchathistory.cpp | 13 ++++++++- .../skins/default/xui/en/menu_object_icon.xml | 18 +++++++++++++ .../skins/default/xui/en/menu_url_agent.xml | 17 ++++++++---- .../skins/default/xui/en/menu_url_objectim.xml | 2 +- 8 files changed, 71 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index a1b6d61cda..0f6947ca19 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1919,6 +1919,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url)); registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url)); registrar.add("Url.SendIM", boost::bind(&LLUrlAction::sendIM, url)); + registrar.add("Url.AddFriend", boost::bind(&LLUrlAction::addFriend, url)); registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url)); registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url)); registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url)); diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp index fd872eca4b..f51aeaec13 100644 --- a/indra/llui/llurlaction.cpp +++ b/indra/llui/llurlaction.cpp @@ -24,7 +24,6 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - #include "linden_common.h" #include "llurlaction.h" @@ -32,6 +31,7 @@ #include "llwindow.h" #include "llurlregistry.h" + // global state for the callback functions LLUrlAction::url_callback_t LLUrlAction::sOpenURLCallback; LLUrlAction::url_callback_t LLUrlAction::sOpenURLInternalCallback; @@ -158,16 +158,33 @@ void LLUrlAction::showProfile(std::string url) } } -void LLUrlAction::sendIM(std::string url) +std::string LLUrlAction::getUserID(std::string url) { LLURI uri(url); LLSD path_array = uri.pathArray(); + std::string id_str; if (path_array.size() == 4) { - std::string id_str = path_array.get(2).asString(); - if (LLUUID::validate(id_str)) - { - executeSLURL("secondlife:///app/agent/" + id_str + "/im"); - } + id_str = path_array.get(2).asString(); } + return id_str; } + +void LLUrlAction::sendIM(std::string url) +{ + std::string id_str = getUserID(url); + if (LLUUID::validate(id_str)) + { + executeSLURL("secondlife:///app/agent/" + id_str + "/im"); + } +} + +void LLUrlAction::addFriend(std::string url) +{ + std::string id_str = getUserID(url); + if (LLUUID::validate(id_str)) + { + executeSLURL("secondlife:///app/agent/" + id_str + "/requestfriend"); + } +} + diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h index f5f2ceba72..e31cd71a20 100644 --- a/indra/llui/llurlaction.h +++ b/indra/llui/llurlaction.h @@ -76,7 +76,9 @@ public: /// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile static void showProfile(std::string url); + static std::string getUserID(std::string url); static void sendIM(std::string url); + static void addFriend(std::string url); /// specify the callbacks to enable this class's functionality typedef boost::function<void (const std::string&)> url_callback_t; diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index ce063a9887..b513a52ff7 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -193,7 +193,7 @@ static void on_avatar_name_cache_start_im(const LLUUID& agent_id, // static void LLAvatarActions::startIM(const LLUUID& id) { - if (id.isNull()) + if (id.isNull() || gAgent.getID() == id) return; LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_cache_start_im, _1, _2)); diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 0152571e20..53926c1fef 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -58,7 +58,7 @@ #include "llworld.h" #include "lluiconstants.h" #include "llstring.h" - +#include "llurlaction.h" #include "llviewercontrol.h" static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history"); @@ -156,6 +156,17 @@ public: LLFloaterSidePanelContainer::showPanel("people", "panel_people", LLSD().with("people_panel_tab_name", "blocked_panel").with("blocked_to_select", getAvatarId())); } + else if (level == "map") + { + std::string url = "secondlife://" + mObjectData["slurl"].asString(); + LLUrlAction::showLocationOnMap(url); + } + else if (level == "teleport") + { + std::string url = "secondlife://" + mObjectData["slurl"].asString(); + LLUrlAction::teleportToLocation(url); + } + } void onAvatarIconContextMenuItemClicked(const LLSD& userdata) diff --git a/indra/newview/skins/default/xui/en/menu_object_icon.xml b/indra/newview/skins/default/xui/en/menu_object_icon.xml index 0c8a2af002..2d4f1792c2 100644 --- a/indra/newview/skins/default/xui/en/menu_object_icon.xml +++ b/indra/newview/skins/default/xui/en/menu_object_icon.xml @@ -24,4 +24,22 @@ function="ObjectIcon.Action" parameter="block" /> </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call + label="Show on Map" + layout="topleft" + name="show_on_map"> + <menu_item_call.on_click + function="ObjectIcon.Action" + parameter="map" /> + </menu_item_call> + <menu_item_call + label="Teleport to Object Location" + layout="topleft" + name="teleport_to_object"> + <menu_item_call.on_click + function="ObjectIcon.Action" + parameter="teleport" /> + </menu_item_call> </menu> diff --git a/indra/newview/skins/default/xui/en/menu_url_agent.xml b/indra/newview/skins/default/xui/en/menu_url_agent.xml index 88ae441bd3..7cd56f257a 100644 --- a/indra/newview/skins/default/xui/en/menu_url_agent.xml +++ b/indra/newview/skins/default/xui/en/menu_url_agent.xml @@ -1,20 +1,27 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <context_menu layout="topleft" - name="Url Popup"> + name="Url Popup"> <menu_item_call - label="Send IM" + label="View Profile" layout="topleft" name="show_agent"> + <menu_item_call.on_click + function="Url.ShowProfile" /> + </menu_item_call> + <menu_item_call + label="Send IM..." + layout="topleft" + name="send_im"> <menu_item_call.on_click function="Url.SendIM" /> </menu_item_call> <menu_item_call - label="Show Resident Profile" + label="Add Friend..." layout="topleft" - name="show_agent"> + name="add_friend"> <menu_item_call.on_click - function="Url.ShowProfile" /> + function="Url.AddFriend" /> </menu_item_call> <menu_item_separator layout="topleft" /> diff --git a/indra/newview/skins/default/xui/en/menu_url_objectim.xml b/indra/newview/skins/default/xui/en/menu_url_objectim.xml index 35c2269b0d..87ab58e622 100644 --- a/indra/newview/skins/default/xui/en/menu_url_objectim.xml +++ b/indra/newview/skins/default/xui/en/menu_url_objectim.xml @@ -3,7 +3,7 @@ layout="topleft" name="Url Popup"> <menu_item_call - label="Show Object Information" + label="Object Profile..." layout="topleft" name="show_object"> <menu_item_call.on_click -- cgit v1.2.3 From cb6574c905806feac3846733ca0ead77e431beb1 Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Tue, 12 Mar 2013 19:38:01 -0700 Subject: CHUI-845 : Avoid some xml param parsing error that seems to be linked with crashers --- indra/llui/lltextbase.cpp | 1 - indra/llui/lltexteditor.cpp | 1 - indra/newview/llfloaterimsessiontab.cpp | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index a1b6d61cda..af29f3b56f 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -2337,7 +2337,6 @@ const LLWString& LLTextBase::getWText() const S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line) const { // Figure out which line we're nearest to. - LLRect visible_region = getVisibleDocumentRect(); LLRect doc_rect = mDocumentView->getRect(); S32 doc_y = local_y - doc_rect.mBottom; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 2f120479d9..d5e08fa29b 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2515,7 +2515,6 @@ void LLTextEditor::updateSegments() mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this); clearSegments(); - segment_set_t::iterator insert_it = mSegments.begin(); for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it) { insertSegment(*list_it); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index faeb860712..85b25afe43 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -253,6 +253,7 @@ BOOL LLFloaterIMSessionTab::postBuild() p.root = NULL; p.use_ellipses = true; p.options_menu = "menu_conversation.xml"; + p.name = "root"; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); // Attach that root to the scroller -- cgit v1.2.3 From aa8809ff3b2f29ad2140328be955e338725d613b Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 12 Mar 2013 17:20:15 +0200 Subject: CHUI-831 Minimized conversation floater is not opened with Open Conversation Window preference if conversation receiving message is selected : force unminimized of the session's floater --- indra/newview/llimview.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 8f3f5145a9..37f5888e8c 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -285,6 +285,11 @@ void on_new_message(const LLSD& msg) { //Surface conversations floater LLFloaterReg::showInstance("im_container"); + + if (session_floater && session_floater->isMinimized()) + { + LLFloater::onClickMinimize(session_floater); + } } //If in DND mode, allow notification to be stored so upon DND exit -- cgit v1.2.3 From 212e21f3526d7d979a0950cc3c8c7ddaceef6cdc Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Tue, 12 Mar 2013 15:43:07 +0200 Subject: CHUI-847 Fixed [CHUIBUG]Collapse Participant List, operates on all torn off chats: make flag mIsPartListExpanded for saving of the participant list panel expand/collapse state --- indra/newview/llfloaterimsessiontab.cpp | 15 +++++++++++---- indra/newview/llfloaterimsessiontab.h | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 85b25afe43..5fc7f46ca3 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -61,6 +61,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) , mRefreshTimer(new LLTimer()) , mIsHostAttached(false) , mHasVisibleBeenInitialized(false) + , mIsParticipantListExpanded(true) { setAutoFocus(FALSE); mSession = LLIMModel::getInstance()->findIMSession(mSessionID); @@ -180,6 +181,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id) // LLFloater::mLastHostHandle = floater_container (a "future" host) conversp->setHost(floater_container); conversp->setHost(NULL); + conversp->forceReshape(); } // Added floaters share some state (like sort order) with their host @@ -269,6 +271,12 @@ BOOL LLFloaterIMSessionTab::postBuild() mRefreshTimer->setTimerExpirySec(0); mRefreshTimer->start(); initBtns(); + + if (mIsParticipantListExpanded != gSavedSettings.getBOOL("IMShowControlPanel")) + { + LLFloaterIMSessionTab::onSlide(this); + } + return result; } @@ -638,7 +646,7 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() // Participant list should be visible only in torn off floaters. bool is_participant_list_visible = !is_not_torn_off - && gSavedSettings.getBOOL("IMShowControlPanel") + && mIsParticipantListExpanded && !mIsP2PChat; mParticipantListPanel->setVisible(is_participant_list_visible); @@ -769,9 +777,8 @@ void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self) // Expand/collapse the IM control panel self->mParticipantListPanel->setVisible(expand); - - gSavedSettings.setBOOL("IMShowControlPanel", expand); - + gSavedSettings.setBOOL("IMShowControlPanel", expand); + self->mIsParticipantListExpanded = expand; self->mExpandCollapseBtn->setImageOverlay(self->getString(expand ? "collapse_icon" : "expand_icon")); } } diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index d55b021df7..e8ae557412 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -138,6 +138,7 @@ protected: bool mIsNearbyChat; bool mIsP2PChat; + bool mIsParticipantListExpanded; LLIMModel::LLIMSession* mSession; -- cgit v1.2.3 From 3468d2d93b7ea3ec4a86445a6187aa6738d8fc16 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 13 Mar 2013 16:08:23 +0200 Subject: CHUI-816 [CHUIBUG]CHUI does not remember undocked state and position of Nearby Chat : canceled the erroneous torn-off/docked state saving when nearby chat is closes --- indra/newview/llfloaterimnearbychat.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index cfee5001a6..eb1a1f54ed 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -274,7 +274,7 @@ void LLFloaterIMNearbyChat::onTearOffClicked() LLFloaterIMSessionTab::onTearOffClicked(); // see CHUI-170: Save torn-off state of the nearby chat between sessions - BOOL in_the_multifloater = !isTornOff(); + BOOL in_the_multifloater = (BOOL)getHost(); gSavedSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater); } @@ -297,8 +297,10 @@ void LLFloaterIMNearbyChat::onClose(bool app_quitting) void LLFloaterIMNearbyChat::onClickCloseBtn() { if (!isTornOff()) + { return; - onTearOffClicked(); + } + LLFloaterIMSessionTab::onTearOffClicked(); LLFloaterIMContainer *im_box = LLFloaterIMContainer::findInstance(); if (im_box) -- cgit v1.2.3 From 7e26f6a59e043fd22296452755d532e2a37b0399 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 13 Mar 2013 19:34:41 +0200 Subject: build fix --- indra/newview/llfloaterimsessiontab.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 5fc7f46ca3..9fd22b1537 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -272,7 +272,7 @@ BOOL LLFloaterIMSessionTab::postBuild() mRefreshTimer->start(); initBtns(); - if (mIsParticipantListExpanded != gSavedSettings.getBOOL("IMShowControlPanel")) + if (mIsParticipantListExpanded != (bool)gSavedSettings.getBOOL("IMShowControlPanel")) { LLFloaterIMSessionTab::onSlide(this); } -- cgit v1.2.3 From 5cddf709acb93a17059e5539258fc30b534a8e99 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Thu, 14 Mar 2013 22:34:15 +0100 Subject: CHUI-700 FIX [CHUIBUG]"Zoom in" feature for avatars has disappeared Disabled "Zoom In" menu item in the case where gObjectList.findObject() returns nothing --- indra/newview/llfloaterimcontainer.cpp | 7 ++++++- indra/newview/llpanelpeoplemenus.cpp | 10 ++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 53daaabe3d..e91717312e 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -53,6 +53,7 @@ #include "llcallbacklist.h" #include "llworld.h" #include "llsdserialize.h" +#include "llviewerobjectlist.h" // // LLFloaterIMContainer @@ -1231,7 +1232,7 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v } // Handle all other options - if (("can_invite" == item) || ("can_chat_history" == item) || ("can_share" == item) || ("can_pay" == item) || ("can_zoom_in" == item)) + if (("can_invite" == item) || ("can_chat_history" == item) || ("can_share" == item) || ("can_pay" == item)) { // Those menu items are enable only if a single avatar is selected return is_single_select; @@ -1261,6 +1262,10 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v { return LLAvatarActions::canCall(); } + else if ("can_zoom_in" == item) + { + return is_single_select && gObjectList.findObject(single_id); + } else if ("can_show_on_map" == item) { return (is_single_select ? (LLAvatarTracker::instance().isBuddyOnline(single_id) && is_agent_mappable(single_id)) || gAgent.isGodlike() : false); diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index aa14b74869..49f7361c4a 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -40,6 +40,7 @@ #include "lllogchat.h" #include "llviewermenu.h" // for gMenuHolder #include "llconversationmodel.h" +#include "llviewerobjectlist.h" namespace LLPanelPeopleMenus { @@ -212,6 +213,12 @@ bool PeopleContextMenu::enableContextMenuItem(const LLSD& userdata) { return LLAvatarActions::canCall(); } + else if (item == std::string("can_zoom_in")) + { + const LLUUID& id = mUUIDs.front(); + + return gObjectList.findObject(id); + } else if (item == std::string("can_show_on_map")) { const LLUUID& id = mUUIDs.front(); @@ -228,8 +235,7 @@ bool PeopleContextMenu::enableContextMenuItem(const LLSD& userdata) return LLLogChat::isTranscriptExist(mUUIDs.front()); } else if (item == std::string("can_im") || item == std::string("can_invite") || - item == std::string("can_share") || item == std::string("can_pay") || - item == std::string("can_zoom_in")) + item == std::string("can_share") || item == std::string("can_pay")) { return true; } -- cgit v1.2.3 From f0b1d1c7ea6e31e89165ff805bf2314767a7e23d Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 14 Mar 2013 16:55:11 -0700 Subject: CHUI-853 (Crashing on ejecting member in group): Upon receiving the rejection response message, the incorrect session id was being used to display the message. session_id was being used instead of new_session_id. --- indra/newview/llimview.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cd47a0c171..1d62a32fc2 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2638,7 +2638,7 @@ void LLIMMgr::addMessage( if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly")) { // Evaluate if we need to skip this message when that setting is true (default is false) - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(new_session_id); skip_message = (LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); // Skip non friends... skip_message &= !session->isGroupSessionType(); // Do not skip group chats... skip_message &= !(other_participant_id == gAgentID); // You are your best friend... Don't skip yourself @@ -2654,7 +2654,7 @@ void LLIMMgr::addMessage( { LLFloaterReg::showInstance("im_container"); LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")-> - flashConversationItemWidget(session_id, true); + flashConversationItemWidget(new_session_id, true); } } -- cgit v1.2.3 From ee4fbb8e37ca20ebfbf85845dbb67941b7abfd29 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Fri, 15 Mar 2013 12:33:46 +0200 Subject: CHUI-830 FIXED Button for collapsing torn-off floater(to a single input line) is added. Show toasts for new messages for that conversation, regardless of other prefs. --- indra/newview/app_settings/settings.xml | 11 ++ indra/newview/llfloaterimnearbychat.cpp | 1 + indra/newview/llfloaterimnearbychathandler.cpp | 10 +- indra/newview/llfloaterimsession.cpp | 2 +- indra/newview/llfloaterimsessiontab.cpp | 82 +++++++++++++- indra/newview/llfloaterimsessiontab.h | 15 +++ indra/newview/llimview.cpp | 7 +- indra/newview/skins/default/textures/textures.xml | 2 + .../skins/default/xui/en/floater_im_session.xml | 123 ++++++++++++++++++--- 9 files changed, 227 insertions(+), 26 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e216c7865d..ca6b9843fd 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4281,6 +4281,17 @@ <string>Boolean</string> <key>Value</key> <integer>1</integer> + </map> + <key>IMShowContentPanel</key> + <map> + <key>Comment</key> + <string>Show Toolbar and Body Panels</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> </map> <key>IgnoreAllNotifications</key> <map> diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index eb1a1f54ed..148f6a0609 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -290,6 +290,7 @@ void LLFloaterIMNearbyChat::onOpen(const LLSD& key) void LLFloaterIMNearbyChat::onClose(bool app_quitting) { // Override LLFloaterIMSessionTab::onClose() so that Nearby Chat is not removed from the conversation floater + LLFloaterIMSessionTab::restoreFloater(); onClickCloseBtn(); } diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 8870d54cd2..7afcf288ce 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -559,12 +559,14 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); - if( nearby_chat->hasFocus() + if(( nearby_chat->hasFocus() || im_box->hasFocus() || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT && gSavedSettings.getBOOL("UseChatBubbles") ) || mChannel.isDead() - || !mChannel.get()->getShowToasts() ) // to prevent toasts in Do Not Disturb mode + || !mChannel.get()->getShowToasts() ) + && nearby_chat->isMessagePaneExpanded()) + // to prevent toasts in Do Not Disturb mode return;//no need in toast if chat is visible or if bubble chat is enabled // arrange a channel on a screen @@ -606,7 +608,7 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, //Don't show nearby toast, if conversation is visible but not focused LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(LLUUID()); - if (session_floater + if (session_floater && session_floater->isMessagePaneExpanded() && session_floater->isInVisibleChain() && !session_floater->isMinimized() && !(session_floater->getHost() && session_floater->getHost()->isMinimized())) { @@ -614,7 +616,7 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, } //Will show toast when chat preference is set - if(gSavedSettings.getString("NotificationNearbyChatOptions") == "toast") + if((gSavedSettings.getString("NotificationNearbyChatOptions") == "toast") || !session_floater->isMessagePaneExpanded()) { // Add a nearby chat toast. LLUUID id; diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 50b2ed8c51..733678364e 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -618,7 +618,7 @@ void LLFloaterIMSession::onClose(bool app_quitting) // Last change: // EXT-3516 X Button should end IM session, _ button should hide gIMMgr->leaveSession(mSessionID); - + LLFloaterIMSessionTab::restoreFloater(); // Clean up the conversation *after* the session has been ended LLFloaterIMSessionTab::onClose(app_quitting); } diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 9fd22b1537..c744350dc6 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -194,19 +194,28 @@ BOOL LLFloaterIMSessionTab::postBuild() { BOOL result; + mBodyStack = getChild<LLLayoutStack>("main_stack"); + + mCloseBtn = getChild<LLButton>("close_btn"); mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onSlide, this)); + mExpandCollapseLineBtn = getChild<LLButton>("minz_btn"); + mExpandCollapseLineBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onCollapseToLine, this)); + mTearOffBtn = getChild<LLButton>("tear_off_btn"); mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this)); mGearBtn = getChild<LLButton>("gear_btn"); mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); - + mToolbarPanel = getChild<LLLayoutPanel>("toolbar_panel"); + mContentPanel = getChild<LLLayoutPanel>("body_panel"); + mInputButtonPanel = getChild<LLLayoutPanel>("input_button_layout_panel"); + mInputButtonPanel->setVisible(false); // Add a scroller for the folder (participant) view LLRect scroller_view_rect = mParticipantListPanel->getRect(); scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); @@ -264,6 +273,8 @@ BOOL LLFloaterIMSessionTab::postBuild() mConversationsRoot->setFollowsAll(); mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); + setMessagePaneExpanded(true); + buildConversationViewParticipant(); refreshConversation(); @@ -651,6 +662,7 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() mParticipantListPanel->setVisible(is_participant_list_visible); + // Display collapse image (<<) if the floater is hosted // or if it is torn off but has an open control panel. bool is_expanded = is_not_torn_off || is_participant_list_visible; @@ -674,6 +686,7 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() mTearOffBtn->setImageOverlay(getString(is_not_torn_off? "tear_off_icon" : "return_icon")); mTearOffBtn->setToolTip(getString(is_not_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window")); + mCloseBtn->setVisible(is_not_torn_off && !mIsNearbyChat); enableDisableCallBtn(); @@ -784,6 +797,65 @@ void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self) } } +void LLFloaterIMSessionTab::onCollapseToLine(LLFloaterIMSessionTab* self) +{ + LLFloaterIMContainer* host_floater = dynamic_cast<LLFloaterIMContainer*>(self->getHost()); + if (!host_floater) + { + if(self->mParticipantListPanel->getVisible()) + { + onSlide(self); + } + + bool expand = self->isMessagePaneExpanded(); + self->mExpandCollapseLineBtn->setImageOverlay(self->getString(expand ? "collapseline_icon" : "expandline_icon")); + self->mContentPanel->setVisible(!expand); + self->mToolbarPanel->setVisible(!expand); + self->reshapeFloater(expand); + self->setMessagePaneExpanded(!expand); + + } +} + +void LLFloaterIMSessionTab::reshapeFloater(bool collapse) +{ + LLRect floater_rect = getRect(); + + if(collapse) + { + mFloaterHeight = floater_rect.getHeight(); + S32 height = mContentPanel->getRect().getHeight() + mToolbarPanel->getRect().getHeight(); + floater_rect.mTop -= height; + enableResizeCtrls(true, true, false); + } + else + { + floater_rect.mTop = floater_rect.mBottom + mFloaterHeight; + enableResizeCtrls(true, true, true); + + } + + setShape(floater_rect, true); + mBodyStack->updateLayout(); + +} + +void LLFloaterIMSessionTab::restoreFloater() +{ + if(!isMessagePaneExpanded()) + { + mContentPanel->setVisible(true); + mToolbarPanel->setVisible(true); + LLRect floater_rect = getRect(); + floater_rect.mTop = floater_rect.mBottom + mFloaterHeight; + setShape(floater_rect, true); + mBodyStack->updateLayout(); + mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon")); + setMessagePaneExpanded(true); + enableResizeCtrls(true, true, true); + } +} + /*virtual*/ void LLFloaterIMSessionTab::onOpen(const LLSD& key) { @@ -793,12 +865,15 @@ void LLFloaterIMSessionTab::onOpen(const LLSD& key) // Show the messages pane when opening a floater hosted in the Conversations host_floater->collapseMessagesPane(false); } + + mInputButtonPanel->setVisible(isTornOff()); } void LLFloaterIMSessionTab::onTearOffClicked() { - setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); + restoreFloater(); + setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); mSaveRect = isTornOff(); initRectControl(); LLFloater::onClickTearOff(this); @@ -813,7 +888,10 @@ void LLFloaterIMSessionTab::onTearOffClicked() else { container->selectConversation(mSessionID); + } + mInputButtonPanel->setVisible(isTornOff()); + refreshConversation(); updateGearBtn(); } diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index e8ae557412..e41f639037 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -98,6 +98,8 @@ public: LLConversationItem* getCurSelectedViewModelItem(); void forceReshape(); virtual BOOL handleKeyHere( KEY key, MASK mask ); + bool isMessagePaneExpanded(){return mMessagePaneExpanded;} + void setMessagePaneExpanded(bool expanded){mMessagePaneExpanded = expanded;} protected: @@ -111,6 +113,9 @@ protected: bool onIMShowModesMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemEnable(const LLSD& userdata); static void onSlide(LLFloaterIMSessionTab *self); + static void onCollapseToLine(LLFloaterIMSessionTab *self); + void reshapeFloater(bool collapse); + void restoreFloater(); // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); @@ -138,15 +143,22 @@ protected: bool mIsNearbyChat; bool mIsP2PChat; + + bool mMessagePaneExpanded; bool mIsParticipantListExpanded; + LLIMModel::LLIMSession* mSession; // Participants list: model and view LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item); LLUUID mSessionID; + LLLayoutStack* mBodyStack; LLLayoutPanel* mParticipantListPanel; // add the widgets to that see mConversationsListPanel + LLLayoutPanel* mContentPanel; + LLLayoutPanel* mToolbarPanel; + LLLayoutPanel* mInputButtonPanel; LLParticipantList* getParticipantList(); conversations_widgets_map mConversationsWidgets; LLConversationViewModel mConversationViewModel; @@ -158,11 +170,14 @@ protected: LLChatEntry* mInputEditor; int mInputEditorTopPad; // padding between input field and chat history + LLButton* mExpandCollapseLineBtn; LLButton* mExpandCollapseBtn; LLButton* mTearOffBtn; LLButton* mCloseBtn; LLButton* mGearBtn; + S32 mFloaterHeight; + private: // Handling selection and contextual menu diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 1d62a32fc2..d04e76c0b3 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -226,17 +226,18 @@ void on_new_message(const LLSD& msg) && !session_floater->isMinimized() && !(session_floater->getHost() && session_floater->getHost()->isMinimized()); - if ("toast" == action && !session_floater_is_open) + bool conversation_floater_collapsed = !session_floater->isMessagePaneExpanded(); + if (("toast" == action && !session_floater_is_open) || conversation_floater_collapsed) { //User is not focused on conversation containing the message - if(session_floater_not_focused) + if(session_floater_not_focused || conversation_floater_collapsed) { if(!LLMuteList::getInstance()->isMuted(participant_id)) { im_box->flashConversationItemWidget(session_id, true); } //The conversation floater isn't focused/open - if(conversation_floater_not_focused) + if(conversation_floater_not_focused || conversation_floater_collapsed) { if(!LLMuteList::getInstance()->isMuted(participant_id) && !gAgent.isDoNotDisturb()) diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index a07d7e4855..93c9cb02cb 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -171,6 +171,8 @@ with the same filename but different name <texture name="Conv_toolbar_call_log" file_name="icons/Conv_toolbar_call_log.png" preload="false" /> <texture name="Conv_toolbar_close" file_name="icons/Conv_toolbar_close.png" preload="false" /> <texture name="Conv_toolbar_collapse" file_name="icons/Conv_toolbar_collapse.png" preload="false" /> + <texture name="Conv_collapse_to_one_line" file_name="icons/collapse_to_one_line.png" preload="false" /> + <texture name="Conv_expand_one_line" file_name="icons/expand_one_liner.png" preload="false" /> <texture name="Conv_toolbar_expand" file_name="icons/Conv_toolbar_expand.png" preload="false" /> <texture name="Conv_toolbar_hang_up" file_name="icons/Conv_toolbar_hang_up.png" preload="false" /> <texture name="Conv_toolbar_open_call" file_name="icons/Conv_toolbar_open_call.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 8f0574177f..1a9199f9e7 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -19,6 +19,12 @@ positioning="relative"> <floater.string name="call_btn_start">Conv_toolbar_open_call</floater.string> <floater.string name="call_btn_stop">Conv_toolbar_hang_up</floater.string> + <floater.string + name="collapseline_icon" + value="Conv_collapse_to_one_line"/> + <floater.string + name="expandline_icon" + value="Conv_expand_one_line"/> <floater.string name="collapse_icon" value="Conv_toolbar_collapse"/> @@ -65,14 +71,28 @@ top="0" left="0" height="355" - width="394"> - <panel + width="394"> + <layout_stack + animate="true" + default_tab_group="2" + follows="all" + height="355" + width="394" + layout="topleft" + orientation="vertical" + name="main_stack" + tab_group="1" + top="0" + left="0"> + + <layout_panel follows="left|top|right" layout="topleft" name="toolbar_panel" top="0" left="0" height="35" + min_height="35" width="394"> <menu_button menu_filename="menu_im_session_showmodes.xml" @@ -180,12 +200,19 @@ left_pad="5" name="tear_off_btn" width="31" /> - </panel> + </layout_panel> + <layout_panel + name="body_panel" + follows="all" + width="394" + height="235" + user_resize="false" + auto_resize="true"> <layout_stack animate="true" default_tab_group="2" follows="all" - height="310" + height="275" width="394" layout="topleft" orientation="horizontal" @@ -198,7 +225,7 @@ follows="all" min_width="115" width="150" - height="310" + height="275" user_resize="true" auto_resize="true"> </layout_panel> @@ -208,7 +235,7 @@ tab_group="2" follows="all" top="0" - height="310" + height="275" width="244" layout="topleft" user_resize="true" @@ -221,13 +248,13 @@ follows="all" layout="topleft" visible="true" - height="275" + height="240" width="244"> <layout_stack animate="true" default_tab_group="2" follows="all" - height="275" + height="240" width="244" layout="topleft" visible="true" @@ -258,7 +285,7 @@ width="230" /> </layout_panel> <layout_panel - height="248" + height="233" width="210" layout="topleft" follows="all" @@ -273,7 +300,7 @@ font="SansSerifSmall" follows="all" visible="true" - height="240" + height="225" name="chat_history" parse_highlights="true" parse_urls="true" @@ -283,26 +310,90 @@ </layout_panel> </layout_stack> </panel> - <chat_editor + </layout_panel> + </layout_stack> + </layout_panel> + <layout_panel + height="35" + layout="topleft" + follows="left|right|bottom" + left_delta="0" + right="0" + top_delta="0" bottom="0" + visible="true" + user_resize="false" + auto_resize="false" + name="chat_layout_panel"> + <layout_stack + animate="true" + default_tab_group="2" + follows="all" + height="35" + right="0" + layout="topleft" + orientation="horizontal" + name="input_panels" + top_pad="0" + left="0"> + <layout_panel + height="35" + layout="topleft" + follows="left|right|bottom" + left_delta="0" + top_delta="0" + bottom="0" + visible="true" + user_resize="false" + auto_resize="true" + name="input_editor_layout_panel"> + <chat_editor + top="6" expand_lines_count="5" follows="left|right|bottom" - font="SansSerifSmall" + font="SansSerifSmall" visible="true" height="20" is_expandable="true" label="To" text_tentative_color="TextFgTentativeColor" - layout="bottomleft" + layout="topleft" name="chat_editor" max_length="1023" spellcheck="true" tab_group="3" - width="220" - left="10" + width="160" + left="5" + right="-5" wrap="true"> </chat_editor> - </layout_panel> + </layout_panel> + <layout_panel + height="35" + layout="topleft" + follows="left|right|bottom" + left_delta="0" + top_delta="0" + bottom="0" + width="35" + visible="true" + user_resize="false" + auto_resize="false" + name="input_button_layout_panel"> + <button + follows="left|right|bottom" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_expand_one_line" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + name="minz_btn" + tool_tip="Shows/hides message panel" + width="28"/> + </layout_panel> + </layout_stack> + </layout_panel> </layout_stack> </view> </floater> -- cgit v1.2.3 From a5a9bd791c910314888b8dad84cd711993c60a40 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 15 Mar 2013 16:04:09 +0200 Subject: CHUI-816 [CHUIBUG]CHUI does not remember undocked state and position of Nearby Chat --- indra/newview/app_settings/settings.xml | 11 ----------- indra/newview/app_settings/settings_per_account.xml | 11 +++++++++++ indra/newview/llfloaterimnearbychat.cpp | 4 ++-- indra/newview/llfloaterimsessiontab.cpp | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ca6b9843fd..4c305e1d60 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1716,17 +1716,6 @@ <key>Value</key> <integer>131073</integer> </map> - <key>NearbyChatIsNotTornOff</key> - <map> - <key>Comment</key> - <string>saving torn-off state of the nearby chat between sessions</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>CloseChatOnReturn</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 363713f2f4..47137c8de9 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -281,6 +281,17 @@ <key>Value</key> <integer>2</integer> </map> + <key>NearbyChatIsNotTornOff</key> + <map> + <key>Comment</key> + <string>saving torn-off state of the nearby chat between sessions</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>ShowFavoritesOnLogin</key> <map> <key>Comment</key> diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 148f6a0609..a593fd4732 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -275,7 +275,7 @@ void LLFloaterIMNearbyChat::onTearOffClicked() // see CHUI-170: Save torn-off state of the nearby chat between sessions BOOL in_the_multifloater = (BOOL)getHost(); - gSavedSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater); + gSavedPerAccountSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater); } @@ -337,7 +337,7 @@ bool LLFloaterIMNearbyChat::isChatVisible() const if (im_box != NULL) { isVisible = - isChatMultiTab() && gSavedSettings.getBOOL("NearbyChatIsNotTornOff")? + isChatMultiTab() && gSavedPerAccountSettings.getBOOL("NearbyChatIsNotTornOff")? im_box->getVisible() && !im_box->isMinimized() : getVisible() && !isMinimized(); } diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index c744350dc6..cfd239c22f 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -170,7 +170,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id) conversp->setHostAttached(true); if (!conversp->isNearbyChat() - || gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) + || gSavedPerAccountSettings.getBOOL("NearbyChatIsNotTornOff")) { floater_container->addFloater(conversp, false, LLTabContainer::RIGHT_OF_CURRENT); } @@ -242,7 +242,7 @@ BOOL LLFloaterIMSessionTab::postBuild() setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); mSaveRect = isNearbyChat() - && !gSavedSettings.getBOOL("NearbyChatIsNotTornOff"); + && !gSavedPerAccountSettings.getBOOL("NearbyChatIsNotTornOff"); initRectControl(); if (isChatMultiTab()) -- cgit v1.2.3 From bd8b0de8970387d2660af10220bbe53901c4aaed Mon Sep 17 00:00:00 2001 From: alexanderpproductengine <alexanderpproductengine@lindenlab.com> Date: Wed, 13 Mar 2013 22:18:41 +0200 Subject: CHUI-831 ADD FIX Minimized conversation floater is not opened with Open Conversation Window preference if conversation receiving message is selected --- indra/newview/llimview.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d04e76c0b3..a266f06a20 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -199,13 +199,13 @@ void on_new_message(const LLSD& msg) // execution of the action LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); - - if (im_box->isFrontmost() && im_box->getSelectedSession() == session_id) + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); + + if (im_box->isFrontmost() && im_box->getSelectedSession() == session_id + && !(session_floater->getHost() ? im_box->isMinimized() : session_floater->isMinimized())) { return; } - - LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); //session floater not focused (visible or not) bool session_floater_not_focused = session_floater && !session_floater->hasFocus(); -- cgit v1.2.3 From d37b3ca62ea5d1f2d3cd57909d77c42227024c0f Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Wed, 13 Mar 2013 13:40:26 -0700 Subject: CHUI-839 : Fixed! Make the LLLineEditor in chat preferences read-only but selectable --- indra/newview/llfloaterpreference.cpp | 3 ++- indra/newview/skins/default/xui/en/panel_preferences_chat.xml | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index b308a820b2..a28af2101b 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -443,6 +443,8 @@ BOOL LLFloaterPreference::postBuild() std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""); setCacheLocation(cache_location); + getChild<LLUICtrl>("log_path_string")->setEnabled(FALSE); // make it read-only but selectable + getChild<LLComboBox>("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this)); getChild<LLComboBox>("FriendIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"FriendIMOptions")); @@ -1572,7 +1574,6 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im getChildView("send_im_to_email")->setEnabled(TRUE); getChild<LLUICtrl>("send_im_to_email")->setValue(im_via_email); getChildView("favorites_on_login_check")->setEnabled(TRUE); - getChildView("log_path_string")->setEnabled(FALSE);// LineEditor becomes readonly in this case. getChildView("log_path_button")->setEnabled(TRUE); getChildView("chat_font_size")->setEnabled(TRUE); } diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 9db3816c92..bd096ebb88 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -429,7 +429,6 @@ </text> <line_editor - enabled="false" control_name="InstantMessageLogPath" border_style="line" border_thickness="1" -- cgit v1.2.3 From 8904f32ba48b49ec216a3ca3b1508d5f3f633e78 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 13 Mar 2013 23:01:10 +0200 Subject: CHUI-796 FIXED User doesn't get all messages in 'do not disturb' mode --- indra/newview/llviewermessage.cpp | 113 ++++++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 42 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 2340436a01..a13c793899 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2382,7 +2382,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LLPostponedNotification::add<LLPostponedIMSystemTipNotification>(params, from_id, false); break; - case IM_NOTHING_SPECIAL: + case IM_NOTHING_SPECIAL: // p2p IM // Don't show dialog, just do IM if (!gAgent.isGodlike() && gAgent.getRegion()->isPrelude() @@ -2783,47 +2783,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } break; - case IM_SESSION_SEND: - { - if (is_do_not_disturb) - { - return; - } - - // Only show messages if we have a session open (which - // should happen after you get an "invitation" - if ( !gIMMgr->hasSession(session_id) ) - { - return; - } - - // standard message, not from system - std::string saved; - if(offline == IM_OFFLINE) - { - saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str()); - } - buffer = saved + message; - BOOL is_this_agent = FALSE; - if(from_id == gAgentID) - { - is_this_agent = TRUE; - } - gIMMgr->addMessage( - session_id, - from_id, - name, - buffer, - IM_OFFLINE == offline, - ll_safe_string((char*)binary_bucket), - IM_SESSION_INVITE, - parent_estate_id, - region_id, - position, - true); - } - break; - case IM_FROM_TASK: { if (is_do_not_disturb && !is_owned_by_me) @@ -2922,6 +2881,76 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LLPostponedNotification::add<LLPostponedServerObjectNotification>(params, from_id, from_group); } break; + + case IM_SESSION_SEND: // ad-hoc or group IMs + + // Only show messages if we have a session open (which + // should happen after you get an "invitation" + if ( !gIMMgr->hasSession(session_id) ) + { + return; + } + + else if (offline == IM_ONLINE && is_do_not_disturb) + { + + // return a standard "do not disturb" message, but only do it to online IM + // (i.e. not other auto responses and not store-and-forward IM) + if (!gIMMgr->hasSession(session_id)) + { + // if there is not a panel for this conversation (i.e. it is a new IM conversation + // initiated by the other party) then... + send_do_not_disturb_message(msg, from_id, session_id); + } + + // now store incoming IM in chat history + + buffer = message; + + LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; + + // add to IM panel, but do not bother the user + gIMMgr->addMessage( + session_id, + from_id, + name, + buffer, + IM_OFFLINE == offline, + ll_safe_string((char*)binary_bucket), + IM_SESSION_INVITE, + parent_estate_id, + region_id, + position, + true); + } + else + { + // standard message, not from system + std::string saved; + if(offline == IM_OFFLINE) + { + saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str()); + } + + buffer = saved + message; + + LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; + + gIMMgr->addMessage( + session_id, + from_id, + name, + buffer, + IM_OFFLINE == offline, + ll_safe_string((char*)binary_bucket), + IM_SESSION_INVITE, + parent_estate_id, + region_id, + position, + true); + } + break; + case IM_FROM_TASK_AS_ALERT: if (is_do_not_disturb && !is_owned_by_me) { -- cgit v1.2.3 From 8b388922434e431c49b9e7f2c9d1e8d90d15ed21 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Thu, 14 Mar 2013 01:28:40 +0100 Subject: CHUI-700 FIX [CHUIBUG]"Zoom in" feature for avatars has disappeared Added "Zoom In" context menu item to Nearby Chat list in People floater and Conversation floater --- indra/newview/llconversationloglist.cpp | 2 +- indra/newview/llconversationmodel.cpp | 2 + indra/newview/llfloaterimcontainer.cpp | 6 +- indra/newview/llpanelpeople.cpp | 13 ++- indra/newview/llpanelpeoplemenus.cpp | 114 ++++++++++++++++++--- indra/newview/llpanelpeoplemenus.h | 20 +++- .../skins/default/xui/en/menu_conversation.xml | 9 +- .../skins/default/xui/en/menu_im_conversation.xml | 7 ++ .../skins/default/xui/en/menu_people_nearby.xml | 40 +++++--- .../xui/en/menu_people_nearby_multiselect.xml | 14 +-- 10 files changed, 178 insertions(+), 49 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index b202cfc9d3..5ab108b39f 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -390,7 +390,7 @@ bool LLConversationLogList::isActionEnabled(const LLSD& userdata) { return is_p2p && LLAvatarActions::canOfferTeleport(selected_id); } - else if ("can_show_on_map") + else if ("can_show_on_map" == command_name) { return is_p2p && ((LLAvatarTracker::instance().isBuddyOnline(selected_id) && is_agent_mappable(selected_id)) || gAgent.isGodlike()); } diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 009fce0a92..c74ce24872 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -139,6 +139,8 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32 items.push_back(std::string("remove_friend")); items.push_back(std::string("invite_to_group")); items.push_back(std::string("separator_invite_to_group")); + if (static_cast<LLConversationItem*>(mParent)->getType() == CONV_SESSION_NEARBY) + items.push_back(std::string("zoom_in")); items.push_back(std::string("map")); items.push_back(std::string("share")); items.push_back(std::string("pay")); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 7437dd8cda..53daaabe3d 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1036,6 +1036,10 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec { LLAvatarActions::inviteToGroup(userID); } + else if ("zoom_in" == command) + { + handle_zoom_to_object(userID); + } else if ("map" == command) { LLAvatarActions::showOnMap(userID); @@ -1227,7 +1231,7 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v } // Handle all other options - if (("can_invite" == item) || ("can_chat_history" == item) || ("can_share" == item) || ("can_pay" == item)) + if (("can_invite" == item) || ("can_chat_history" == item) || ("can_share" == item) || ("can_pay" == item) || ("can_zoom_in" == item)) { // Those menu items are enable only if a single avatar is selected return is_single_select; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index c5283404f1..4138558bad 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -611,10 +611,10 @@ BOOL LLPanelPeople::postBuild() mGroupList->setNoItemsMsg(getString("no_groups_msg")); mGroupList->setNoFilteredItemsMsg(getString("no_filtered_groups_msg")); - mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); - mRecentList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); - mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); - mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); + mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyPeopleContextMenu); + mRecentList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu); + mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu); + mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu); setSortOrder(mRecentList, (ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"), false); setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false); @@ -1143,7 +1143,10 @@ void LLPanelPeople::onGearButtonClicked(LLUICtrl* btn) uuid_vec_t selected_uuids; getCurrentItemIDs(selected_uuids); // Spawn at bottom left corner of the button. - LLPanelPeopleMenus::gNearbyMenu.show(btn, selected_uuids, 0, 0); + if (getActiveTabName() == NEARBY_TAB_NAME) + LLPanelPeopleMenus::gNearbyPeopleContextMenu.show(btn, selected_uuids, 0, 0); + else + LLPanelPeopleMenus::gPeopleContextMenu.show(btn, selected_uuids, 0, 0); } void LLPanelPeople::onImButtonClicked() diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index 47d6b49a50..aa14b74869 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -39,15 +39,17 @@ #include "llcallingcard.h" // for LLAvatarTracker #include "lllogchat.h" #include "llviewermenu.h" // for gMenuHolder +#include "llconversationmodel.h" namespace LLPanelPeopleMenus { -NearbyMenu gNearbyMenu; +PeopleContextMenu gPeopleContextMenu; +NearbyPeopleContextMenu gNearbyPeopleContextMenu; -//== NearbyMenu =============================================================== +//== PeopleContextMenu =============================================================== -LLContextMenu* NearbyMenu::createMenu() +LLContextMenu* PeopleContextMenu::createMenu() { // set up the callbacks for all of the avatar menu items LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -64,7 +66,8 @@ LLContextMenu* NearbyMenu::createMenu() registrar.add("Avatar.RemoveFriend", boost::bind(&LLAvatarActions::removeFriendDialog, id)); registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, id)); registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, id)); - registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this)); + registrar.add("Avatar.OfferTeleport", boost::bind(&PeopleContextMenu::offerTeleport, this)); + registrar.add("Avatar.ZoomIn", boost::bind(&handle_zoom_to_object, id)); registrar.add("Avatar.ShowOnMap", boost::bind(&LLAvatarActions::showOnMap, id)); registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, id)); registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, id)); @@ -72,33 +75,72 @@ LLContextMenu* NearbyMenu::createMenu() registrar.add("Avatar.InviteToGroup", boost::bind(&LLAvatarActions::inviteToGroup, id)); registrar.add("Avatar.Calllog", boost::bind(&LLAvatarActions::viewChatHistory, id)); - enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2)); - enable_registrar.add("Avatar.CheckItem", boost::bind(&NearbyMenu::checkContextMenuItem, this, _2)); + enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2)); + enable_registrar.add("Avatar.CheckItem", boost::bind(&PeopleContextMenu::checkContextMenuItem, this, _2)); // create the context menu from the XUI menu = createFromFile("menu_people_nearby.xml"); + buildContextMenu(*menu, 0x0); } else { // Set up for multi-selected People // registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs)); // *TODO: unimplemented - registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startConference, mUUIDs, LLUUID::null)); - registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs, LLUUID::null)); - registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this)); - registrar.add("Avatar.RemoveFriend",boost::bind(&LLAvatarActions::removeFriendsDialog, mUUIDs)); + registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startConference, mUUIDs, LLUUID::null)); + registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs, LLUUID::null)); + registrar.add("Avatar.OfferTeleport", boost::bind(&PeopleContextMenu::offerTeleport, this)); + registrar.add("Avatar.RemoveFriend", boost::bind(&LLAvatarActions::removeFriendsDialog, mUUIDs)); // registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::startIM, mUUIDs)); // *TODO: unimplemented - // registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs)); // *TODO: unimplemented - enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2)); + // registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs)); // *TODO: unimplemented + + enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2)); // create the context menu from the XUI menu = createFromFile("menu_people_nearby_multiselect.xml"); + buildContextMenu(*menu, ITEM_IN_MULTI_SELECTION); } return menu; } -bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) +void PeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags) +{ + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + if (flags & ITEM_IN_MULTI_SELECTION) + { + items.push_back(std::string("add_friends")); + items.push_back(std::string("remove_friends")); + items.push_back(std::string("im")); + items.push_back(std::string("call")); + items.push_back(std::string("share")); + items.push_back(std::string("pay")); + items.push_back(std::string("offer_teleport")); + } + else + { + items.push_back(std::string("view_profile")); + items.push_back(std::string("im")); + items.push_back(std::string("offer_teleport")); + items.push_back(std::string("voice_call")); + items.push_back(std::string("chat_history")); + items.push_back(std::string("separator_chat_history")); + items.push_back(std::string("add_friend")); + items.push_back(std::string("remove_friend")); + items.push_back(std::string("invite_to_group")); + items.push_back(std::string("separator_invite_to_group")); + items.push_back(std::string("map")); + items.push_back(std::string("share")); + items.push_back(std::string("pay")); + items.push_back(std::string("block_unblock")); + } + + hide_context_entries(menu, items, disabled_items); +} + +bool PeopleContextMenu::enableContextMenuItem(const LLSD& userdata) { if(gAgent.getID() == mUUIDs.front()) { @@ -186,14 +228,15 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) return LLLogChat::isTranscriptExist(mUUIDs.front()); } else if (item == std::string("can_im") || item == std::string("can_invite") || - item == std::string("can_share") || item == std::string("can_pay")) + item == std::string("can_share") || item == std::string("can_pay") || + item == std::string("can_zoom_in")) { return true; } return false; } -bool NearbyMenu::checkContextMenuItem(const LLSD& userdata) +bool PeopleContextMenu::checkContextMenuItem(const LLSD& userdata) { std::string item = userdata.asString(); const LLUUID& id = mUUIDs.front(); @@ -206,11 +249,50 @@ bool NearbyMenu::checkContextMenuItem(const LLSD& userdata) return false; } -void NearbyMenu::offerTeleport() +void PeopleContextMenu::offerTeleport() { // boost::bind cannot recognize overloaded method LLAvatarActions::offerTeleport(), // so we have to use a wrapper. LLAvatarActions::offerTeleport(mUUIDs); } +//== NearbyPeopleContextMenu =============================================================== + +void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags) +{ + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + if (flags & ITEM_IN_MULTI_SELECTION) + { + items.push_back(std::string("add_friends")); + items.push_back(std::string("remove_friends")); + items.push_back(std::string("im")); + items.push_back(std::string("call")); + items.push_back(std::string("share")); + items.push_back(std::string("pay")); + items.push_back(std::string("offer_teleport")); + } + else + { + items.push_back(std::string("view_profile")); + items.push_back(std::string("im")); + items.push_back(std::string("offer_teleport")); + items.push_back(std::string("voice_call")); + items.push_back(std::string("chat_history")); + items.push_back(std::string("separator_chat_history")); + items.push_back(std::string("add_friend")); + items.push_back(std::string("remove_friend")); + items.push_back(std::string("invite_to_group")); + items.push_back(std::string("separator_invite_to_group")); + items.push_back(std::string("zoom_in")); + items.push_back(std::string("map")); + items.push_back(std::string("share")); + items.push_back(std::string("pay")); + items.push_back(std::string("block_unblock")); + } + + hide_context_entries(menu, items, disabled_items); +} + } // namespace LLPanelPeopleMenus diff --git a/indra/newview/llpanelpeoplemenus.h b/indra/newview/llpanelpeoplemenus.h index d51eaec716..0a1dcef303 100644 --- a/indra/newview/llpanelpeoplemenus.h +++ b/indra/newview/llpanelpeoplemenus.h @@ -33,19 +33,33 @@ namespace LLPanelPeopleMenus { /** - * Menu used in the nearby people list. + * Menu used in the people lists. */ -class NearbyMenu : public LLListContextMenu +class PeopleContextMenu : public LLListContextMenu { public: /*virtual*/ LLContextMenu* createMenu(); + +protected: + virtual void buildContextMenu(class LLMenuGL& menu, U32 flags); + private: bool enableContextMenuItem(const LLSD& userdata); bool checkContextMenuItem(const LLSD& userdata); void offerTeleport(); }; -extern NearbyMenu gNearbyMenu; +/** + * Menu used in the nearby people list. + */ +class NearbyPeopleContextMenu : public PeopleContextMenu +{ +protected: + /*virtual*/ void buildContextMenu(class LLMenuGL& menu, U32 flags); +}; + +extern PeopleContextMenu gPeopleContextMenu; +extern NearbyPeopleContextMenu gNearbyPeopleContextMenu; } // namespace LLPanelPeopleMenus diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index fd5c86b3ca..5a13ef0a59 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -89,7 +89,14 @@ <on_click function="Avatar.DoToSelected" parameter="invite_to_group" /> <on_enable function="Avatar.EnableItem" parameter="can_invite" /> </menu_item_call> - <menu_item_separator layout="topleft" name="separator_invite_to_group"/> + <menu_item_separator layout="topleft" name="separator_invite_to_group"/> + <menu_item_call + label="Zoom In" + layout="topleft" + name="zoom_in"> + <on_click function="Avatar.DoToSelected" parameter="zoom_in" /> + <on_enable function="Avatar.EnableItem" parameter="can_zoom_in" /> + </menu_item_call> <menu_item_call label="Map" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_im_conversation.xml b/indra/newview/skins/default/xui/en/menu_im_conversation.xml index 8882d0a7d8..43287c6ec3 100644 --- a/indra/newview/skins/default/xui/en/menu_im_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_im_conversation.xml @@ -49,6 +49,13 @@ </menu_item_call> <menu_item_separator layout="topleft"/> + <menu_item_call + label="Zoom In" + layout="topleft" + name="zoom_in"> + <on_click function="Avatar.DoToSelected" parameter="zoom_in" /> + <on_enable function="Avatar.EnableItem" parameter="can_zoom_in" /> + </menu_item_call> <menu_item_call label="Map" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index 60a6c98514..3abb5f7bc8 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -1,18 +1,18 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <context_menu layout="topleft" - name="Avatar Context Menu"> + name="Nearby People Context Menu"> <menu_item_call label="View Profile" layout="topleft" - name="View Profile"> + name="view_profile"> <menu_item_call.on_click function="Avatar.Profile" /> </menu_item_call> <menu_item_call label="IM" layout="topleft" - name="IM"> + name="im"> <menu_item_call.on_click function="Avatar.IM" /> <menu_item_call.on_enable @@ -21,7 +21,7 @@ </menu_item_call> <menu_item_call label="Offer Teleport" - name="teleport"> + name="offer_teleport"> <menu_item_call.on_click function="Avatar.OfferTeleport"/> <menu_item_call.on_enable @@ -31,7 +31,7 @@ <menu_item_call label="Voice call" layout="topleft" - name="Call"> + name="voice_call"> <menu_item_call.on_click function="Avatar.Call" /> <menu_item_call.on_enable @@ -42,18 +42,18 @@ <menu_item_call label="View chat history..." layout="topleft" - name="Chat history"> + name="chat_history"> <menu_item_call.on_click function="Avatar.Calllog" /> <menu_item_call.on_enable function="Avatar.EnableItem" parameter="can_callog"/> </menu_item_call> - <menu_item_separator /> + <menu_item_separator name="separator_chat_history"/> <menu_item_call label="Add Friend" layout="topleft" - name="Add Friend"> + name="add_friend"> <menu_item_call.on_click function="Avatar.AddFriend" /> <menu_item_call.on_visible @@ -63,7 +63,7 @@ <menu_item_call label="Remove Friend" layout="topleft" - name="Remove Friend"> + name="remove_friend"> <menu_item_call.on_click function="Avatar.RemoveFriend" /> <menu_item_call.on_enable @@ -73,18 +73,28 @@ <menu_item_call label="Invite to group..." layout="topleft" - name="Invite"> + name="invite_to_group"> <menu_item_call.on_click function="Avatar.InviteToGroup" /> <menu_item_call.on_enable function="Avatar.EnableItem" parameter="can_invite"/> </menu_item_call> - <menu_item_separator /> + <menu_item_separator name="separator_invite_to_group"/> + <menu_item_call + label="Zoom In" + layout="topleft" + name="zoom_in"> + <menu_item_call.on_click + function="Avatar.ZoomIn" /> + <menu_item_call.on_enable + function="Avatar.EnableItem" + parameter="can_zoom_in"/> + </menu_item_call> <menu_item_call label="Map" layout="topleft" - name="Map"> + name="map"> <menu_item_call.on_click function="Avatar.ShowOnMap" /> <menu_item_call.on_enable @@ -94,7 +104,7 @@ <menu_item_call label="Share" layout="topleft" - name="Share"> + name="share"> <menu_item_call.on_click function="Avatar.Share" /> <menu_item_call.on_enable @@ -104,7 +114,7 @@ <menu_item_call label="Pay" layout="topleft" - name="Pay"> + name="pay"> <menu_item_call.on_click function="Avatar.Pay" /> <menu_item_call.on_enable @@ -114,7 +124,7 @@ <menu_item_check label="Block/Unblock" layout="topleft" - name="Block/Unblock"> + name="block_unblock"> <menu_item_check.on_click function="Avatar.BlockUnblock" /> <menu_item_check.on_check diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml index 5d58a9d289..5f973088fd 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml @@ -6,7 +6,7 @@ enabled="false" label="Add Friends" layout="topleft" - name="Add Friends"> + name="add_friends"> <on_click function="Avatar.AddFriends" /> <on_enable @@ -16,7 +16,7 @@ <menu_item_call label="Remove Friends" layout="topleft" - name="Remove Friend"> + name="remove_friends"> <menu_item_call.on_click function="Avatar.RemoveFriend" /> <menu_item_call.on_enable @@ -26,7 +26,7 @@ <menu_item_call label="IM" layout="topleft" - name="IM"> + name="im"> <on_click function="Avatar.IM" /> </menu_item_call> @@ -34,7 +34,7 @@ enabled="false" label="Call" layout="topleft" - name="Call"> + name="call"> <on_click function="Avatar.Call" /> <on_enable @@ -45,7 +45,7 @@ enabled="false" label="Share" layout="topleft" - name="Share"> + name="share"> <on_click function="Avatar.Share" /> </menu_item_call> @@ -53,13 +53,13 @@ enabled="false" label="Pay" layout="topleft" - name="Pay"> + name="pay"> <on_click function="Avatar.Pay" /> </menu_item_call> <menu_item_call label="Offer Teleport" - name="teleport"> + name="offer_teleport"> <menu_item_call.on_click function="Avatar.OfferTeleport"/> <menu_item_call.on_enable -- cgit v1.2.3 From 3ee18d8b29caa612ee7656aa1ac69e3c1edce4cc Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Thu, 14 Mar 2013 11:28:56 +0200 Subject: CHUI-844 (Collapsed conversation panel auto expands when a new IM conversation starts) CHUI-713 ("Conversations" floater size doesn't persist between sessions) --- indra/newview/llfloaterimcontainer.cpp | 12 +----------- indra/newview/llfloaterimcontainer.h | 1 - indra/newview/llimview.cpp | 1 + 3 files changed, 2 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 7437dd8cda..5f1b3dcfb1 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -62,8 +62,7 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param mExpandCollapseBtn(NULL), mConversationsRoot(NULL), mConversationsEventStream("ConversationsEvents"), - mInitialized(false), - mIsFirstLaunch(false) + mInitialized(false) { mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2)); mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction, this, _2)); @@ -245,7 +244,6 @@ BOOL LLFloaterIMContainer::postBuild() mGeneralTitle = getTitle(); mInitialized = true; - mIsFirstLaunch = true; // Add callbacks: // We'll take care of view updates on idle @@ -280,12 +278,6 @@ void LLFloaterIMContainer::addFloater(LLFloater* floaterp, LLUUID session_id = floaterp->getKey(); - // Make sure the message panel is open when adding a floater or it stays mysteriously hidden - if (!mIsFirstLaunch) - { - collapseMessagesPane(false); - } - // Add the floater LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); @@ -646,8 +638,6 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse) return; } - mIsFirstLaunch = false; - // Save current width of panels before collapsing/expanding right pane. S32 conv_pane_width = mConversationsPane->getRect().getWidth(); S32 msg_pane_width = mMessagesPane->getRect().getWidth(); diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 5139651d8d..2cbc1e99f9 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -174,7 +174,6 @@ private: LLLayoutStack* mConversationsStack; bool mInitialized; - bool mIsFirstLaunch; LLUUID mSelectedSession; std::string mGeneralTitle; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 8f3f5145a9..699e36db4f 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -285,6 +285,7 @@ void on_new_message(const LLSD& msg) { //Surface conversations floater LLFloaterReg::showInstance("im_container"); + im_box->collapseMessagesPane(false); } //If in DND mode, allow notification to be stored so upon DND exit -- cgit v1.2.3 From 780fe4e37fe5df4120ef4de09e6fc69f6184e4d3 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Fri, 15 Mar 2013 17:39:09 +0200 Subject: CHUI-831 ADD FIX Minimized conversation floater is not opened with Open Conversation Window preference if conversation receiving message is selected --- indra/newview/llimview.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index a266f06a20..aadc61c4f5 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -287,9 +287,22 @@ void on_new_message(const LLSD& msg) //Surface conversations floater LLFloaterReg::showInstance("im_container"); im_box->collapseMessagesPane(false); - if (session_floater && session_floater->isMinimized()) + if (session_floater) { - LLFloater::onClickMinimize(session_floater); + if (session_floater->getHost()) + { + if (NULL != im_box && im_box->isMinimized()) + { + LLFloater::onClickMinimize(im_box); + } + } + else + { + if (session_floater->isMinimized()) + { + LLFloater::onClickMinimize(session_floater); + } + } } } -- cgit v1.2.3 From 242c39f24bc38ee306f1a9b4a173fd095fdab49d Mon Sep 17 00:00:00 2001 From: Merov Linden <merov@lindenlab.com> Date: Fri, 15 Mar 2013 17:54:16 -0700 Subject: CHUI-807 : More defensive code. Don't assume anything while iterating through panels. --- indra/llui/lltabcontainer.cpp | 27 ++++++++++++++++----------- indra/newview/llimview.cpp | 5 ++--- 2 files changed, 18 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 0c43a571b8..6f895ed939 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1483,16 +1483,22 @@ BOOL LLTabContainer::setTab(S32 which) for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { LLTabTuple* tuple = *iter; - if (!tuple) - continue; BOOL is_selected = ( tuple == selected_tuple ); - tuple->mButton->setUseEllipses(mUseTabEllipses); - tuple->mButton->setHAlign(mFontHalign); - tuple->mTabPanel->setVisible( is_selected ); -// tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here. - tuple->mButton->setToggleState( is_selected ); - // RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs - tuple->mButton->setTabStop( is_selected ); + + // Although the selected tab must be complete, we may have hollow LLTabTuple tucked in the list + if (tuple->mButton) + { + tuple->mButton->setUseEllipses(mUseTabEllipses); + tuple->mButton->setHAlign(mFontHalign); + tuple->mButton->setToggleState( is_selected ); + // RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs + tuple->mButton->setTabStop( is_selected ); + } + if (tuple->mTabPanel) + { + tuple->mTabPanel->setVisible( is_selected ); + //tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here. + } if (is_selected) { @@ -1563,8 +1569,7 @@ BOOL LLTabContainer::selectTabByName(const std::string& name) LLPanel* panel = getPanelByName(name); if (!panel) { - llwarns << "LLTabContainer::selectTabByName(" - << name << ") failed" << llendl; + llwarns << "LLTabContainer::selectTabByName(" << name << ") failed" << llendl; return FALSE; } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cd47a0c171..fbb3bd4a8e 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -641,8 +641,7 @@ void LLIMModel::LLIMSession::loadHistory() LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const { - return get_if_there(mId2SessionMap, session_id, - (LLIMModel::LLIMSession*) NULL); + return get_if_there(mId2SessionMap, session_id, (LLIMModel::LLIMSession*) NULL); } //*TODO consider switching to using std::set instead of std::list for holding LLUUIDs across the whole code @@ -2809,7 +2808,7 @@ LLUUID LLIMMgr::addSession( } } - bool new_session = !LLIMModel::getInstance()->findIMSession(session_id); + bool new_session = (LLIMModel::getInstance()->findIMSession(session_id) == NULL); //works only for outgoing ad-hoc sessions if (new_session && IM_SESSION_CONFERENCE_START == dialog && ids.size()) -- cgit v1.2.3 From 0a0ba068bf5bc6d829440a12946174c6ed961843 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Fri, 15 Mar 2013 18:16:44 -0700 Subject: CHUI-852 ([crashhunters] crash in LLNotificationsUI::LLScreenChannel::addToast): Crash is due to a gesture not loading while the user is shutting down the app. A notification saying that the gesture couldn't load is trying to display while the app is shutting down, which causes a crash. --- indra/newview/lldelayedgestureerror.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldelayedgestureerror.cpp b/indra/newview/lldelayedgestureerror.cpp index 80e7c9f1b2..ef1b644ad4 100644 --- a/indra/newview/lldelayedgestureerror.cpp +++ b/indra/newview/lldelayedgestureerror.cpp @@ -113,9 +113,11 @@ bool LLDelayedGestureError::doDialog(const LLErrorEntry &ent, bool uuid_ok) } } - - LLNotificationsUtil::add(ent.mNotifyName, args); - + if(!LLApp::isQuitting()) + { + LLNotificationsUtil::add(ent.mNotifyName, args); + } + return true; } -- cgit v1.2.3 From c294c7c4740e41c43b2b04f136cc909e37b28f7d Mon Sep 17 00:00:00 2001 From: merov <none@none> Date: Sat, 16 Mar 2013 16:09:50 -0700 Subject: CHUI-863 : Clean up dead code that's creating failures on gcc-4.6 builds on Linux --- indra/llrender/llgl.cpp | 9 +-------- indra/llui/lltextbase.cpp | 1 - indra/newview/llchiclet.cpp | 3 +++ indra/newview/llviewerdisplay.cpp | 1 - indra/newview/llviewerwindow.cpp | 2 -- indra/newview/llworldmapview.cpp | 3 --- 6 files changed, 4 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 9e4857b6bc..c8cf3713ab 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -597,11 +597,6 @@ bool LLGLManager::initGL() if (mGLVendor.substr(0,4) == "ATI ") { mGLVendorShort = "ATI"; - BOOL mobile = FALSE; - if (mGLRenderer.find("MOBILITY") != std::string::npos) - { - mobile = TRUE; - } mIsATI = TRUE; #if LL_WINDOWS && !LL_MESA_HEADLESS @@ -1489,9 +1484,7 @@ void assert_glerror() void clear_glerror() { - // Create or update texture to be used with this data - GLenum error; - error = glGetError(); + glGetError(); } /////////////////////////////////////////////////////////////// diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index c4ec1edc73..ebc9ee244e 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -359,7 +359,6 @@ void LLTextBase::drawSelectionBackground() S32 selection_left = llmin( mSelectionStart, mSelectionEnd ); S32 selection_right = llmax( mSelectionStart, mSelectionEnd ); - LLRect selection_rect = mVisibleTextRect; // Skip through the lines we aren't drawing. LLRect content_display_rect = getVisibleDocumentRect(); diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 3dbb43c657..b221daf936 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -427,6 +427,8 @@ LLChicletPanel::~LLChicletPanel() void LLChicletPanel::onMessageCountChanged(const LLSD& data) { + // *TODO : we either suppress this method or return a value. Right now, it servers no purpose. + /* LLUUID session_id = data["session_id"].asUUID(); S32 unread = data["participant_unread"].asInteger(); @@ -435,6 +437,7 @@ void LLChicletPanel::onMessageCountChanged(const LLSD& data) { unread = 0; } + */ } void LLChicletPanel::objectChicletCallback(const LLSD& data) diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index ffeea2f4df..40577118ba 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1038,7 +1038,6 @@ void render_hud_attachments() if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices()) { LLCamera hud_cam = *LLViewerCamera::getInstance(); - LLVector3 origin = hud_cam.getOrigin(); hud_cam.setOrigin(-1.f,0,0); hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1)); LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index e44a2cc4df..4afd90b44c 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2827,7 +2827,6 @@ void LLViewerWindow::updateUI() BOOL handled = FALSE; - BOOL handled_by_top_ctrl = FALSE; LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); LLView* captor_view = dynamic_cast<LLView*>(mouse_captor); @@ -3012,7 +3011,6 @@ void LLViewerWindow::updateUI() S32 local_x, local_y; top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask); - handled_by_top_ctrl = TRUE; } if ( !handled ) diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index ccc513b80d..11b2770ec0 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -965,8 +965,6 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4& S32 text_x = x; S32 text_y = (S32)(y - sTrackCircleImage->getHeight()/2 - font->getLineHeight()); - BOOL is_in_window = true; - if( x < 0 || y < 0 || x >= getRect().getWidth() @@ -979,7 +977,6 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4& text_x = sTrackingArrowX; text_y = sTrackingArrowY; } - is_in_window = false; } else if (LLTracker::getTrackingStatus() == LLTracker::TRACKING_LOCATION && LLTracker::getTrackedLocationType() != LLTracker::LOCATION_NOTHING) -- cgit v1.2.3 From bc8ac5854f8b1eb9995139bb43cdf3b944030076 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Mon, 18 Mar 2013 14:37:21 +0200 Subject: CHUI-620 FIXED Clear the highlight when auto-selecting new conversation or when text is entered into the message panel. --- indra/newview/llfloaterimcontainer.cpp | 2 +- indra/newview/llfloaterimnearbychat.cpp | 6 ++++++ indra/newview/llfloaterimsession.cpp | 5 +++++ 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 1954f098b6..2fd8901d9e 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1418,7 +1418,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool session_floater->setMinimized(is_minimized); } } - + flashConversationItemWidget(session_id,false); return handled; } diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index a593fd4732..7c552f98e0 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -420,6 +420,12 @@ BOOL LLFloaterIMNearbyChat::matchChatTypeTrigger(const std::string& in_str, std: void LLFloaterIMNearbyChat::onChatBoxKeystroke() { + LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); + if (im_box) + { + im_box->flashConversationItemWidget(mSessionID,false); + } + LLFirstUse::otherAvatarChatFirst(false); LLWString raw_text = mInputEditor->getWText(); diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 733678364e..73adfd0eda 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -892,6 +892,11 @@ void LLFloaterIMSession::onInputEditorFocusLost(LLFocusableElement* caller, void void LLFloaterIMSession::onInputEditorKeystroke(LLTextEditor* caller, void* userdata) { LLFloaterIMSession* self = (LLFloaterIMSession*)userdata; + LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); + if (im_box) + { + im_box->flashConversationItemWidget(self->mSessionID,false); + } std::string text = self->mInputEditor->getText(); // Deleting all text counts as stopping typing. -- cgit v1.2.3 From 8e1c21bf702c357528101c2073c2717a9b26880b Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Mon, 18 Mar 2013 14:51:38 +0200 Subject: CHUI-830 Icons uploaded --- .../skins/default/textures/icons/collapse_to_one_line.png | Bin 0 -> 538 bytes .../skins/default/textures/icons/expand_one_liner.png | Bin 0 -> 545 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 indra/newview/skins/default/textures/icons/collapse_to_one_line.png create mode 100644 indra/newview/skins/default/textures/icons/expand_one_liner.png (limited to 'indra') diff --git a/indra/newview/skins/default/textures/icons/collapse_to_one_line.png b/indra/newview/skins/default/textures/icons/collapse_to_one_line.png new file mode 100644 index 0000000000..d57144a645 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/collapse_to_one_line.png differ diff --git a/indra/newview/skins/default/textures/icons/expand_one_liner.png b/indra/newview/skins/default/textures/icons/expand_one_liner.png new file mode 100644 index 0000000000..58b7d90131 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/expand_one_liner.png differ -- cgit v1.2.3 From a079acf1aa3b7cfe8ee35bb7afdbae83df0df5ca Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Mon, 18 Mar 2013 16:02:09 +0200 Subject: CHUI-861 FIXED "Animate" param is set false. --- indra/newview/skins/default/xui/en/floater_im_session.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 1a9199f9e7..6862788c65 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -73,7 +73,7 @@ height="355" width="394"> <layout_stack - animate="true" + animate="false" default_tab_group="2" follows="all" height="355" -- cgit v1.2.3 From 22203b43db851a611adbaa2413bc92a14dd7f951 Mon Sep 17 00:00:00 2001 From: Cho <cho@lindenlab.com> Date: Mon, 18 Mar 2013 20:06:25 +0100 Subject: CHUI-826 FIX [CHUIBUG]User nametags (nametag floaters) intermittently disappear in CHUI builds. Added check in LLVOAvatar::idleUpdateNameTagText() to account for case where mNameString is literally "" (two quotes) --- indra/newview/llvoavatar.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index c74d9f1292..d295fc60cd 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3097,6 +3097,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) // Rebuild name tag if state change detected if (mNameString.empty() + || (mNameString.size() == 2 && mNameString[0] == 10 && mNameString[1] == 10) // *TODO : find out why mNameString is sometimes "" || new_name || (!title && !mTitle.empty()) || (title && mTitle != title->getString()) -- cgit v1.2.3 From 73f68342f657984d6ab3447f3f9dbc44f35b1982 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Mon, 18 Mar 2013 15:56:50 -0700 Subject: CHUI-864 ([crashhunters] crash in LLConversationLog): Found a probable cause. It is likely that the user was missing the user settings variable called 'KeepConversationLogTranscripts.' If this variable doesn't exist or is deleted then the CHUI viewer would try to extract data from this non-existent variable. Resolution, now perform a check to make sure the 'KeepConversationLogTranscripts' settings variable exists before extracting data. --- indra/newview/llconversationlog.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index dd20ca15ae..7883e4cb89 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -194,14 +194,17 @@ LLConversationLog::LLConversationLog() : mAvatarNameCacheConnection(), mLoggingEnabled(false) { - LLControlVariable * keep_log_ctrlp = gSavedPerAccountSettings.getControl("KeepConversationLogTranscripts").get(); - S32 log_mode = keep_log_ctrlp->getValue(); - keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); - if (log_mode > 0) + if(gSavedPerAccountSettings.controlExists("KeepConversationLogTranscripts")) { - loadFromFile(getFileName()); + LLControlVariable * keep_log_ctrlp = gSavedPerAccountSettings.getControl("KeepConversationLogTranscripts").get(); + S32 log_mode = keep_log_ctrlp->getValue(); + keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); + if (log_mode > 0) + { + loadFromFile(getFileName()); - enableLogging(log_mode); + enableLogging(log_mode); + } } } -- cgit v1.2.3 From 0c5ff7eb4870ac2ec933bd624e6969dbea862dbb Mon Sep 17 00:00:00 2001 From: mberezhnoy <mberezhnoy@productengine.com> Date: Tue, 19 Mar 2013 10:57:38 +0200 Subject: CHUI-812 ([CHUIBUG]Resizing "Nearby chat" window creates confusing layout) --- indra/newview/skins/default/xui/en/floater_im_session.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 6862788c65..c42e58a9f4 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -227,7 +227,7 @@ width="150" height="275" user_resize="true" - auto_resize="true"> + auto_resize="false"> </layout_panel> <layout_panel default_tab_group="3" -- cgit v1.2.3 From c4f283334c9ee6abff7253d8024f3b1870b342f3 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 19 Mar 2013 11:34:13 -0700 Subject: CHUI 796 (User doesn't get all messages in 'do not disturb' mode): Now IM DND notifications will be stored as p2p, ad-hoc or group. When loading these notifications upon app start ad-hoc/group notifications will launch the conversation log and play a sound. --- .../newview/lldonotdisturbnotificationstorage.cpp | 25 ++++++++++++++++++++-- indra/newview/llimview.cpp | 2 ++ 2 files changed, 25 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 22f35752bd..be20adeb8a 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -33,6 +33,7 @@ #include "lldir.h" #include "llerror.h" #include "llfloaterreg.h" +#include "llimview.h" #include "llnotifications.h" #include "llnotificationhandler.h" #include "llnotificationstorage.h" @@ -145,6 +146,8 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() LLNotifications& instance = LLNotifications::instance(); bool imToastExists = false; + bool group_ad_hoc_toast_exists = false; + S32 toastSessionType; bool offerExists = false; for (LLSD::array_const_iterator notification_it = data.beginArray(); @@ -158,7 +161,20 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() if(notificationName == toastName) { - imToastExists = true; + toastSessionType = notification_params["payload"]["SESSION_TYPE"]; + if(toastSessionType == LLIMModel::LLIMSession::P2P_SESSION) + { + imToastExists = true; + } + //Don't add group/ad-hoc messages to the notification system because + //this means the group/ad-hoc session has to be re-created + else if(toastSessionType == LLIMModel::LLIMSession::GROUP_SESSION + || toastSessionType == LLIMModel::LLIMSession::ADHOC_SESSION) + { + //Just allows opening the conversation log for group/ad-hoc messages upon startup + group_ad_hoc_toast_exists = true; + continue; + } } else if(notificationName == offerName) { @@ -197,7 +213,12 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() LLFloaterReg::showInstance("im_container"); } - if(imToastExists || offerExists) + if(group_ad_hoc_toast_exists) + { + LLFloaterReg::showInstance("conversation"); + } + + if(imToastExists || group_ad_hoc_toast_exists || offerExists) { make_ui_sound_deferred("UISndNewIncomingIMSession"); } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 10e214bc90..8c862548bb 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -154,6 +154,7 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id, args["FROM"] = av_name.getCompleteName(); args["FROM_ID"] = msg["from_id"]; args["SESSION_ID"] = msg["session_id"]; + args["SESSION_TYPE"] = msg["session_type"]; LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); } @@ -1008,6 +1009,7 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co arg["from"] = from; arg["from_id"] = from_id; arg["time"] = LLLogChat::timestamp(false); + arg["session_type"] = session->mSessionType; mNewMsgSignal(arg); return true; -- cgit v1.2.3 From 2a8baeed3a2dc67abff131249aa23538e76fb05d Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Tue, 19 Mar 2013 16:46:04 -0700 Subject: CHUI-843 ([CHUIBUG]Suggested alteration to toolbar_panel in floater_im_container in CHUI): Adjusted button layout in conversation floater. --- indra/newview/skins/default/xui/en/floater_im_container.xml | 10 +++++----- indra/newview/skins/default/xui/en/floater_im_session.xml | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 12c1676127..65f623a47e 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -61,7 +61,7 @@ image_unselected="Toolbar_Middle_Off" menu_filename="menu_participant_view.xml" layout="topleft" - left="10" + left="5" name="sort_btn" tool_tip="View/sort options" top="5" @@ -75,7 +75,7 @@ image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" - left_pad="4" + left_pad="2" name="add_btn" tool_tip="Start a new conversation" width="31"/> @@ -88,7 +88,7 @@ image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" - left_pad="4" + left_pad="2" name="speak_btn" tool_tip="Speak with people using your microphone" width="31"/> @@ -114,7 +114,7 @@ </layout_panel> </layout_stack> <panel - bottom="-5" + bottom="-1" follows="all" layout="topleft" name="conversations_list_panel" @@ -129,7 +129,7 @@ name="messages_layout_panel" expanded_min_dim="222"> <panel_container - bottom="-5" + bottom="-1" follows="all" layout="topleft" left="0" diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 6862788c65..56a1b35caf 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -118,7 +118,7 @@ image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" - left_pad="4" + left_pad="2" name="gear_btn" visible="false" tool_tip="Actions on selected person" @@ -133,7 +133,7 @@ image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" - left_pad="4" + left_pad="2" name="add_btn" tool_tip="Add someone to this conversation" width="31"/> @@ -146,7 +146,7 @@ image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" - left_pad="4" + left_pad="2" name="voice_call_btn" tool_tip="Open voice connection" width="31"/> @@ -171,7 +171,7 @@ image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" - left="283" + left="292" name="close_btn" tool_tip="End this conversation" width="31" /> @@ -184,7 +184,7 @@ image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" - left_pad="5" + left_pad="2" name="expand_collapse_btn" tool_tip="Collapse/Expand this pane" width="31" /> @@ -197,7 +197,7 @@ image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" - left_pad="5" + left_pad="2" name="tear_off_btn" width="31" /> </layout_panel> -- cgit v1.2.3 From 5187f5b41f8b748dd7f092d97e69f24a4c43f4ee Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Wed, 20 Mar 2013 15:08:02 +0200 Subject: CHUI-869 FIXED Clicking on toast will restore Message pane. --- indra/newview/llfloaterimnearbychat.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 7c552f98e0..3af3c65045 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -348,6 +348,11 @@ bool LLFloaterIMNearbyChat::isChatVisible() const void LLFloaterIMNearbyChat::showHistory() { openFloater(); + if(!isMessagePaneExpanded()) + { + restoreFloater(); + setFocus(true); + } setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); } -- cgit v1.2.3 From 78e0dc5aa3650c74aade364b7be4669d58fe8316 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Wed, 20 Mar 2013 15:30:27 +0200 Subject: CHUI-860 FIXED Don't call onSlide() to change Participant list's state --- indra/newview/llfloaterimsessiontab.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index cfd239c22f..4ae00fcd5f 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -802,18 +802,12 @@ void LLFloaterIMSessionTab::onCollapseToLine(LLFloaterIMSessionTab* self) LLFloaterIMContainer* host_floater = dynamic_cast<LLFloaterIMContainer*>(self->getHost()); if (!host_floater) { - if(self->mParticipantListPanel->getVisible()) - { - onSlide(self); - } - bool expand = self->isMessagePaneExpanded(); self->mExpandCollapseLineBtn->setImageOverlay(self->getString(expand ? "collapseline_icon" : "expandline_icon")); self->mContentPanel->setVisible(!expand); self->mToolbarPanel->setVisible(!expand); self->reshapeFloater(expand); self->setMessagePaneExpanded(!expand); - } } -- cgit v1.2.3 From cee1a311ad218c6d5ed8ae9924624d959b6be6a0 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Wed, 20 Mar 2013 15:41:57 +0200 Subject: CHUI-870 FIXED Expand Message panel after clicking toast. --- indra/newview/llfloaterimcontainer.cpp | 3 +++ indra/newview/llfloaterimsessiontab.cpp | 4 ++++ indra/newview/llfloaterimsessiontab.h | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 2fd8901d9e..5e0cd8ef78 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1329,6 +1329,9 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id) { setVisibleAndFrontmost(false); selectConversationPair(session_id, true); + + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); + session_floater->restoreFloater(); } void LLFloaterIMContainer::clearAllFlashStates() diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 4ae00fcd5f..5df1a382cd 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -838,6 +838,10 @@ void LLFloaterIMSessionTab::restoreFloater() { if(!isMessagePaneExpanded()) { + if(isMinimized()) + { + setMinimized(false); + } mContentPanel->setVisible(true); mToolbarPanel->setVisible(true); LLRect floater_rect = getRect(); diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index e41f639037..f22e2b5744 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -100,6 +100,7 @@ public: virtual BOOL handleKeyHere( KEY key, MASK mask ); bool isMessagePaneExpanded(){return mMessagePaneExpanded;} void setMessagePaneExpanded(bool expanded){mMessagePaneExpanded = expanded;} + void restoreFloater(); protected: @@ -115,7 +116,6 @@ protected: static void onSlide(LLFloaterIMSessionTab *self); static void onCollapseToLine(LLFloaterIMSessionTab *self); void reshapeFloater(bool collapse); - void restoreFloater(); // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); -- cgit v1.2.3 From a48cd164a20734722e25592f5cf22c8344dd4860 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Wed, 20 Mar 2013 21:51:36 +0200 Subject: CHUI-857 Nearby chat opens as torn off on first login: changed initial setting for nearby chat docked state --- indra/newview/app_settings/settings_per_account.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 47137c8de9..ada374f892 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -290,7 +290,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>ShowFavoritesOnLogin</key> <map> -- cgit v1.2.3 From 4a2fb4c64f2079089b78202e53bbe1dbe8ac09c7 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Wed, 20 Mar 2013 22:27:16 +0200 Subject: CHUI-873 FIXED [CHUIBUG]Torn off nearby chat with message panel hidden has huge bottom padding when opening in mouselook mode --- indra/newview/llfloaterimnearbychat.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 3af3c65045..b287950c21 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -739,7 +739,14 @@ void LLFloaterIMNearbyChat::startChat(const char* line) LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); if (nearby_chat) { - nearby_chat->show(); + if(!nearby_chat->isTornOff()) + { + nearby_chat->show(); + } + if(nearby_chat->isMinimized()) + { + nearby_chat->setMinimized(false); + } nearby_chat->setVisible(TRUE); nearby_chat->setFocus(TRUE); nearby_chat->mInputEditor->setFocus(TRUE); -- cgit v1.2.3 From 1df1ce7a31df77743675899d4a15458ac84a281a Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 21 Mar 2013 15:57:44 +0200 Subject: CHUI-858 FIXED Text can be clipped by text input bar in message panel --- indra/newview/skins/default/xui/en/floater_im_session.xml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index e081ea8e74..1ad54bdb6b 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -266,6 +266,7 @@ left="0"> <layout_panel auto_resize="false" + user_resize="false" height="26" layout="topleft" left_delta="0" @@ -285,7 +286,6 @@ width="230" /> </layout_panel> <layout_panel - height="233" width="210" layout="topleft" follows="all" @@ -293,19 +293,21 @@ top_delta="0" bottom="0" visible="true" - user_resize="true" + user_resize="false" auto_resize="true" name="chat_holder"> <chat_history font="SansSerifSmall" follows="all" visible="true" - height="225" name="chat_history" parse_highlights="true" parse_urls="true" + layout="topleft" right="-5" - left="5"> + left="5" + top="0" + bottom="1"> </chat_history> </layout_panel> </layout_stack> @@ -348,7 +350,6 @@ auto_resize="true" name="input_editor_layout_panel"> <chat_editor - top="6" expand_lines_count="5" follows="left|right|bottom" font="SansSerifSmall" @@ -363,6 +364,7 @@ spellcheck="true" tab_group="3" width="160" + top="6" left="5" right="-5" wrap="true"> -- cgit v1.2.3 From 9887daa3e3224b00ffc46ce69604b3227b14637c Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine <mnikolenko@productengine.com> Date: Thu, 21 Mar 2013 18:04:10 +0200 Subject: CHUI-880 FIXED Show Button panel if floater is torned off. Don't show Conversation floater in Mouselook, if Nearby chat is torned off. --- indra/newview/llfloaterimsessiontab.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 5df1a382cd..7b50ce5ae2 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -30,6 +30,7 @@ #include "llfloaterimsessiontab.h" #include "llagent.h" +#include "llagentcamera.h" #include "llavataractions.h" #include "llchatentry.h" #include "llchathistory.h" @@ -125,8 +126,12 @@ void LLFloaterIMSessionTab::setVisible(BOOL visible) if(visible && !mHasVisibleBeenInitialized) { mHasVisibleBeenInitialized = true; - LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->setVisible(true); + if(!gAgentCamera.cameraMouselook()) + { + LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->setVisible(true); + } LLFloaterIMSessionTab::addToHost(mSessionID); + mInputButtonPanel->setVisible(isTornOff()); } LLTransientDockableFloater::setVisible(visible); -- cgit v1.2.3 From 4d9e3e159e63a0317a069c9d74c6904d5b222537 Mon Sep 17 00:00:00 2001 From: maksymsproductengine <maksymsproductengine@lindenlab.com> Date: Thu, 21 Mar 2013 18:29:18 +0200 Subject: CHUI-855 FIXED Text entry bar auto expand does not resize --- indra/newview/llfloaterimsessiontab.cpp | 20 ++++++++++---------- indra/newview/llfloaterimsessiontab.h | 5 +++-- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 7b50ce5ae2..0dd61568f9 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -58,11 +58,12 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) , mSpeakingIndicator(NULL) , mChatHistory(NULL) , mInputEditor(NULL) - , mInputEditorTopPad(0) + , mInputEditorPad(0) , mRefreshTimer(new LLTimer()) , mIsHostAttached(false) , mHasVisibleBeenInitialized(false) , mIsParticipantListExpanded(true) + , mChatLayoutPanel(NULL) { setAutoFocus(FALSE); mSession = LLIMModel::getInstance()->findIMSession(mSessionID); @@ -237,12 +238,15 @@ BOOL LLFloaterIMSessionTab::postBuild() mChatHistory = getChild<LLChatHistory>("chat_history"); mInputEditor = getChild<LLChatEntry>("chat_editor"); - mInputEditor->setTextExpandedCallback(boost::bind(&LLFloaterIMSessionTab::reshapeChatHistory, this)); + + mChatLayoutPanel = getChild<LLLayoutPanel>("chat_layout_panel"); + + mInputEditor->setTextExpandedCallback(boost::bind(&LLFloaterIMSessionTab::reshapeChatLayoutPanel, this)); mInputEditor->setCommitOnFocusLost( FALSE ); mInputEditor->setPassDelete(TRUE); mInputEditor->setFont(LLViewerChat::getChatFont()); - mInputEditorTopPad = mChatHistory->getRect().mBottom - mInputEditor->getRect().mTop; + mInputEditorPad = mChatLayoutPanel->getRect().getHeight() - mInputEditor->getRect().getHeight(); setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); @@ -708,15 +712,11 @@ void LLFloaterIMSessionTab::forceReshape() } -void LLFloaterIMSessionTab::reshapeChatHistory() +void LLFloaterIMSessionTab::reshapeChatLayoutPanel() { - LLRect chat_rect = mChatHistory->getRect(); + LLRect chat_layout_panel_rect = mChatLayoutPanel->getRect(); LLRect input_rect = mInputEditor->getRect(); - - int delta_height = chat_rect.mBottom - (input_rect.mTop + mInputEditorTopPad); - - chat_rect.setLeftTopAndSize(chat_rect.mLeft, chat_rect.mTop, chat_rect.getWidth(), chat_rect.getHeight() + delta_height); - mChatHistory->setShape(chat_rect); + mChatLayoutPanel->reshape(chat_layout_panel_rect.getWidth(), input_rect.getHeight() + mInputEditorPad, FALSE); } void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show) diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index f22e2b5744..e9393c5336 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -168,7 +168,8 @@ protected: LLOutputMonitorCtrl* mSpeakingIndicator; LLChatHistory* mChatHistory; LLChatEntry* mInputEditor; - int mInputEditorTopPad; // padding between input field and chat history + LLLayoutPanel * mChatLayoutPanel; + int mInputEditorPad; // padding between input field and chat history LLButton* mExpandCollapseLineBtn; LLButton* mExpandCollapseBtn; @@ -195,7 +196,7 @@ private: * and avoid overlapping, since input chat field can be vertically expanded. * Implementation: chat history bottom "follows" top+top_pad of input chat field */ - void reshapeChatHistory(); + void reshapeChatLayoutPanel(); bool checkIfTornOff(); bool mIsHostAttached; -- cgit v1.2.3 From bbfd1c0f2d89de50c0c0e026208036e2bc963104 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine <apaschenko@productengine.com> Date: Thu, 21 Mar 2013 18:44:01 +0200 Subject: CHUI-878 FIXED Torn off conversation window width can be reduced and lose vertical scroll bar: manually setting of the floater's minimal size --- indra/newview/llfloaterimsessiontab.cpp | 50 +++++++++++++++++----- indra/newview/llfloaterimsessiontab.h | 5 +++ .../skins/default/xui/en/floater_im_session.xml | 8 ++-- 3 files changed, 49 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 0dd61568f9..eab2ce7798 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -196,12 +196,29 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id) } } +void LLFloaterIMSessionTab::assignResizeLimits() +{ + bool is_participants_pane_collapsed = mParticipantListPanel->isCollapsed(); + + // disable a layoutstack's functionality when participant list panel is collapsed + mRightPartPanel->setIgnoreReshape(is_participants_pane_collapsed); + + S32 participants_pane_target_width = is_participants_pane_collapsed? + 0 : (mParticipantListPanel->getRect().getWidth() + LLPANEL_BORDER_WIDTH); + + S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth; + + setResizeLimits(new_min_width, getMinHeight()); + + this->mParticipantListAndHistoryStack->updateLayout(); +} + BOOL LLFloaterIMSessionTab::postBuild() { BOOL result; mBodyStack = getChild<LLLayoutStack>("main_stack"); - + mParticipantListAndHistoryStack = getChild<LLLayoutStack>("im_panels"); mCloseBtn = getChild<LLButton>("close_btn"); mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); @@ -218,6 +235,8 @@ BOOL LLFloaterIMSessionTab::postBuild() mGearBtn = getChild<LLButton>("gear_btn"); mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); + mRightPartPanel = getChild<LLLayoutPanel>("right_part_holder"); + mToolbarPanel = getChild<LLLayoutPanel>("toolbar_panel"); mContentPanel = getChild<LLLayoutPanel>("body_panel"); mInputButtonPanel = getChild<LLLayoutPanel>("input_button_layout_panel"); @@ -297,6 +316,15 @@ BOOL LLFloaterIMSessionTab::postBuild() LLFloaterIMSessionTab::onSlide(this); } + // The resize limits for LLFloaterIMSessionTab should be updated, based on current values of width of conversation and message panels + mParticipantListPanel->getResizeBar()->setResizeListener(boost::bind(&LLFloaterIMSessionTab::assignResizeLimits, this)); + mFloaterExtraWidth = + getRect().getWidth() + - mParticipantListAndHistoryStack->getRect().getWidth() + - (mParticipantListPanel->isCollapsed()? 0 : LLPANEL_BORDER_WIDTH); + + assignResizeLimits(); + return result; } @@ -669,8 +697,7 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() && mIsParticipantListExpanded && !mIsP2PChat; - mParticipantListPanel->setVisible(is_participant_list_visible); - + mParticipantListAndHistoryStack->collapsePanel(mParticipantListPanel, !is_participant_list_visible); // Display collapse image (<<) if the floater is hosted // or if it is torn off but has an open control panel. @@ -791,15 +818,18 @@ void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self) { if (!self->mIsP2PChat) { - bool expand = !self->mParticipantListPanel->getVisible(); - - // Expand/collapse the IM control panel - self->mParticipantListPanel->setVisible(expand); - gSavedSettings.setBOOL("IMShowControlPanel", expand); - self->mIsParticipantListExpanded = expand; - self->mExpandCollapseBtn->setImageOverlay(self->getString(expand ? "collapse_icon" : "expand_icon")); + bool should_be_expanded = self->mParticipantListPanel->isCollapsed(); + + // Expand/collapse the participant list panel + self->mParticipantListAndHistoryStack->collapsePanel(self->mParticipantListPanel, !should_be_expanded); + self->mParticipantListPanel->setVisible(should_be_expanded); + gSavedSettings.setBOOL("IMShowControlPanel", should_be_expanded); + self->mIsParticipantListExpanded = should_be_expanded; + self->mExpandCollapseBtn->setImageOverlay(self->getString(should_be_expanded ? "collapse_icon" : "expand_icon")); } } + + self->assignResizeLimits(); } void LLFloaterIMSessionTab::onCollapseToLine(LLFloaterIMSessionTab* self) diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index e9393c5336..f0899a3c09 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -140,6 +140,9 @@ protected: void appendMessage(const LLChat& chat, const LLSD &args = 0); std::string appendTime(); + void assignResizeLimits(); + + S32 mFloaterExtraWidth; bool mIsNearbyChat; bool mIsP2PChat; @@ -155,7 +158,9 @@ protected: LLUUID mSessionID; LLLayoutStack* mBodyStack; + LLLayoutStack* mParticipantListAndHistoryStack; LLLayoutPanel* mParticipantListPanel; // add the widgets to that see mConversationsListPanel + LLLayoutPanel* mRightPartPanel; LLLayoutPanel* mContentPanel; LLLayoutPanel* mToolbarPanel; LLLayoutPanel* mInputButtonPanel; diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 1ad54bdb6b..d8b085063f 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -14,7 +14,6 @@ width="394" can_resize="true" can_tear_off="false" - min_width="340" min_height="190" positioning="relative"> <floater.string name="call_btn_start">Conv_toolbar_open_call</floater.string> @@ -223,9 +222,10 @@ <layout_panel name="speakers_list_panel" follows="all" - min_width="115" + expanded_min_dim="115" + min_dim="0" width="150" - height="275" + height="275" user_resize="true" auto_resize="false"> </layout_panel> @@ -241,7 +241,7 @@ user_resize="true" auto_resize="true" visible="true" - name="left_part_holder" + name="right_part_holder" min_width="221"> <panel name="trnsAndChat_panel" -- cgit v1.2.3 From abf1bf79f2d45ba42389397f9013d5552f7d672d Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales <gilbert@lindenlab.com> Date: Thu, 21 Mar 2013 16:16:54 -0700 Subject: CHUI-881 ([CHUIBUG]Viewer crashes when user drag and drop the participant from the people floater to the one of the tool bars): Problem was that the item dragged from the people list was not of type inventoryitem. Instead of casting to an inventoryitem and checking if the item being dragged is a widgit, instead look at the cargo type (which also specifies that the dragged item is a widgit but doesn't need to typecast). --- indra/llui/lltoolbar.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index b9256dd890..1c74395c66 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -1059,10 +1059,9 @@ BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, // Convert drag position into insert position and rank if (!isReadOnly() && handled && !drop) { - LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; - LLAssetType::EType type = inv_item->getType(); - if (type == LLAssetType::AT_WIDGET) + if (cargo_type == DAD_WIDGET) { + LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; LLCommandId dragged_command(inv_item->getUUID()); int orig_rank = getRankFromPosition(dragged_command); mDragRank = getRankFromPosition(x, y); -- cgit v1.2.3